sábado, 11 de agosto de 2018

Ocultar opciones del panel de resultados de búsqueda en SharePoint 2013

Esta semana me pidieron que pusiera un buscador en una página en un SharePoint 2013. Entonces para ello, agregue una caja de búsqueda y un panel de resultados de búsqueda.

Sí se deja el panel de resultados tal y como viene tiene la siguiente apariencia:

Tras verlo, nos pidieron que ocultáramos todas las opciones que aparecían para evitar que los usuarios se liaran con otra cosa que no fuera buscar. Entonces es cuando tuvimos que ocultar algunas opciones por medio de la configuración (En rojo en la captura) y otras por CSS (En azul en la captura):


Para ocultar las opciones en rojo, deberemos editar la página y editar el elemento web. Dentro del menú Configuración deberemos desmarcar las siguientes opciones:


En cambio, para ocultar la parte en azul, habría que poner un elemento web del tipo Editor de secuencias de comando en el cual pondremos el siguiente código CSS:

<style>
    #NoResult div, #NoResult ul {
        display: none
    }
    #NoResult .ms-srch-result-noResultsTitle {
        display: inherit
    }
    .ms-srch-result-noResultsTitle {
        padding-bottom: 0px;
    }
</style>

Con lo cual, quedarían todas las zonas indicadas ocultas:


Existiría otra opción que sería crear plantilla de presentación especifica, pero eso lo veremos en otra entrada del blog.

sábado, 17 de marzo de 2018

Cambiar usuario en SharePoint 2013

En versiones anteriores de SharePoint se podía cambiar de usuario desde Acciones del sitio. En SharePoint 2013 no he encontrado esa opción. Pero para poder cambiar de usuario, podremos hacerlo desde la dirección:

/_layouts/15/closeconnection.aspx?loginasanotheruser=true

Nos mostrará la ventana de inicio y nos permitirá introducir el usuario y la contraseña.


sábado, 24 de febrero de 2018

Aceptación de condiciones con SharePoint

Esta semana me han pedido que al acceder a la página principal de un SharePoint saliera un recordatorio respecto a la normativa corporativa de la empresa. Querían que saliera todas las veces que accedían al portal.

Solución rápida: Un alert de JavaScript.

Como era de esperar a los tres días les ha parecido que no era una buena solución y que les parecía mejor la solución que les propuse inicialmente, que sólo saliera la primera vez que accedes al espacio y que quedase registrado cuando has dicho que estabas de acuerdo con los términos legales de la empresa.

Para ello, lo primero que he creado ha sido una lista llamada AceptaciónCondiciones. En ella, sólo utilizo la columna Título, Creado por y Creado. Todas ellas propias del tipo de contenido Elemento, propio de una lista personalizada.

Y en la página de inicio he incluido el siguiente script en un editor de secuencias de comando:
<script type="text/javascript">
 $( document ).ready(function(){
 var usuario = $().SPServices.SPGetCurrentUser({
  fieldNames: ["FirstName", "LastName", "UserName"],
  debug: false
 });
 $().SPServices({
    operation: "GetListItems",
    async: false,
    listName: "AceptacionCondiciones",
    CAMLViewFields: "<ViewFields><FieldRef Name='Title' /></ViewFields>",
CAMLQuery: "<Query><Where><Eq><FieldRef Name='Title'/><Value Type='Text'>"+usuario.UserName+"</Value></Eq></Where></Query>",
    completefunc: function (xData, Status) {
if($(xData.responseXML).SPFilterNode("z:row").length == 0){
//No está y lo incluyo
alert('Advertencia: Este acceso sólo está disponible para usuarios autorizados por personal del servicio. Cualquier intento de acceso no autorizado quedará registrado para su posterior análisis. La documentación aquí alojada es para uso profesional, no permitiéndose su divulgación. ');
AddListItem(usuario.UserName);
}    
    }
  });
})
function AddListItem(TitleField) {
        $().SPServices({
            operation: "UpdateListItems",
            async: false,
            batchCmd: "New",
            listName: "AceptacionCondiciones",
            valuepairs: [["Title", TitleField]],
            completefunc: function (xData, Status) {   
            }
        });
    }
</script>

Lo que hace este Script es guardar en una variable llamada "usuario" el Nombre, Apellido y Nombre de usuario. Luego hago una llamada a la lista AceptacionCondiciones a través de una Query de CALM preguntando si existe algún elemento que en la columna Title (Nombre interno de la columna Título) que contenga el valor de UserName del usuario de DA que esta accediendo a la página principal.
En caso de que no este, hago saltar un Alert de JavaScript con el texto deseado y tras ello incluyo en la lista el usuario, a través de la función AddListItem, completando el campo Titulo con el UserName y como los campos "Creado" y "Creado por" toman automáticamente el nombre a mostrar del usuario y el momento en que hemos aceptado las condiciones.

Ya tendríamos nuestra lista de aceptación de condiciones pedida.

Sí nos hubieran pedido que esta aceptación saliera en cualquier página de nuestro sitio, bastaría con incluir este Script en la página maestra e incluir la línea que indica donde esta la lista, por si estamos en un sitio diferente al de la lista:
webURL: "https://URL del sitio donde esta mi lista de Aceptación de condiciones",

Quedando algo como:
 $().SPServices({
    webURL: "https://URL del sitio donde esta mi lista de Aceptación de condiciones",
    operation: "GetListItems",
    async: false,

Y el resto igual.

Posiblemente con .Net se pudiera hacer algo más completo, pero seguro que también sería más costoso en tiempo.

sábado, 27 de enero de 2018

Validation failed: Cannot resolve Activity

Tras varios años trabajando con SharePoint 2013, hay un error muy común cuando hago flujos de 2010 con SharePoint Designer 2013.
Consiste en que si copias y pegas acciones o simplemente el flujo es muy grande, hay veces que al ir a publicarlo, puede aparecer un mensaje del tipo:

(0, 0) Activity 'ID257' validation failed: Cannot resolve Activity 'ID420'

Lo gracioso es que si comprobamos errores en el flujo, nos dirá que no existen errores en nuestro flujo, pero al publicarlos no nos dejará.

Solución: Copiar cada uno de los pasos que tenga el flujo y pegarlos. Tras ello eliminar el original y darle a publicar.





Y misterios de SharePoint, ya no nos sale este error y el flujo se publica correctamente.

Espero que a alguien más le sirva de solución como me ha servido a mí.

domingo, 10 de diciembre de 2017

Botón de adjuntar documentos

Trabajando con SharePoint 2013 es común que cuando utilizamos una lista como formulario, nos digan: "Pero quiero que también se pueda adjuntar documentos..."

Esto se debe a que el botón de adjuntar se encuentra en la Ribbon superior dentro del menú Editar y si no se tiene conocimiento de SharePoint no es intuitivo encontrarlo:


Para ello, lo que suelo hacer es crear una vista de datos del formulario de nuevo elemento. Lo cual me permite personalizarlo tal y como nos lo pidan. Y adicionalmente, puedo hacer dos cosas para solucionar el problema del adjunto.

La primera es utilizar la función de Javascript UploadAttachment() que hace exactamente lo mismo que la opción adjuntar de la Ribbon superior. En teoría se puede utilizar con enlace o como botón:

<a href="javascript:UploadAttachment()">Attach File</a>

<button onclick="javascript:UploadAttachment()">Attach File</button>

Lo cierto es que la opción button, suele presentar un comportamiento anómalo, del cual desconozco el motivo y lo que suelo hacer es falsear el enlace para que parezca un botón:

<tr>
<td width="190px" valign="top" class="ms-formlabel">
<H3 class="ms-standardheader">
<nobr>Adjuntar archivo
</nobr>
</H3>  
</td>
<td width="200px" valign="top">
<a href="javascript:UploadAttachment()" style="border:1px solid #ababab;padding:5px;text-decoration:none;color:#444;">Adjuntar archivo</a>
</td>
</tr>

Y esto nos genera un botón como:



Que tras hacer clic nos presenta el formulario de selección:


Y nos mostrará los elementos adjuntados:


La otra opción es mostrar directamente el formulario de selección en el formulario de nuevo elemento. Para ello bastará con el siguiente código:

<tr>
<td width="190px" valign="top" class="ms-formlabel">
<H3 class="ms-standardheader">
<nobr>Adjuntar</nobr>
</H3>
</td>
<td width="400px" valign="top" class="ms-formbody">
<table>
<tr>
<td valign="top" class="ms-formbody" id="attachmentsOnClient" style="width: 300px">
<span dir="ltr">
<input type="file" name="fileupload0"  id="onetidIOFile" size="20" title="Name"></input>
</span>
</td>
<td width="100px" valign="top" class="ms-formbody">
<input name="Button1" type="button" value="Adjuntar" onclick='OkAttach()' style="width: 6em;" />
<span id="idSpace"></span>
</td>
</tr>
</table>
</td>
</tr>

Esto nos mostrará lo siguiente:


Y mostrará el comportamiento similar al anterior, con la salvedad de que nos ahorra un clic.

Ambos son igual de validos y facilitan al usuario el poder adjuntar documentos.





sábado, 14 de octubre de 2017

Copia Oculta en SharePoint Designer

Recientemente un cliente nos ha solicitado que quería estar en copia oculta de los correos electrónicos que se generan desde los flujos de trabajo de SharePoint.

Al abrir SharePoint Designer 2013, vemos que tenemos la acción de enviar correo electrónico disponible, si la ponemos en nuestro flujo, podemos ver que nos presenta sólo las opciones de Para y Copia, pero no la de Copia Oculta:


Para poder acceder a la copia oculta, tendremos que acceder a las Propiedades de la acción en el flujo de trabajo:


Esto hará que se abra la ventana emergente que nos permitirá incluir los destinatarios en copia urgente:


Desde el menú de BBC podremos incluir a dichos miembros:


sábado, 23 de septiembre de 2017

Botón de Guardar y Cancelar personalizados en SharePoint

Normalmente cuando hacemos una vista de datos en SharePoint, nos suelen aparecer dos botones de Guardar y Cancelar.

En dichos botones, en algunas versiones de SharePoint no ha funcionado el modificar el redirect, ni el value. Es decir, a donde deben enviarnos tras hacer clic en ellos y cual es el texto a mostrar en el botón.

La manera que yo utilizo es en lugar de utilizar un control de tipo SharePoint, utilizar uno de tipo button. Quedando en la vista de datos, un código equivalente al siguiente:


<table>
  <tr>
    <td width="99%" class="ms-toolbar" nowrap="">
      <IMG SRC="/_layouts/images/blank.gif" width="1" height="18"/>
    </td>
    <td class="ms-toolbar" nowrap="">
      <input type="button" id="savebutton1" value="  Enviar  " name="btnSave" onclick="javascript: {ddwrt:GenFireServerEvent('__commit;__redirect={/Misitio/Paginas/SolicitudRegistrada.aspx}')}" />
    </td>
    <td class="ms-separator">&#160;</td>
    <td class="ms-toolbar" nowrap="" align="right">
      <input type="button" id="cancelbutton1" value="   Salir   " name="btnCancel" onclick="javascript: {ddwrt:GenFireServerEvent('__redirect={/Mistio/Paginas/SolicitudCancelada.aspx}')}" />
    </td>
  </tr>
</table>

Donde lo que nosotros personalizaremos serán los valores del campo Value y las URL de las llamadas Javascript de los onclick