SharePoint 2010. Iniciar un flujo de trabajo en múltiples elementos de una lista

En SharePoint 2010 tenemos una opción para seleccionar varios elementos en una lista pero cuando se seleccionan varios elementos, la ribbon sólo permite eliminar elementos y configurar el envío alertas, pero ¿dónde está el comando de flujo de trabajo?

Por definición, para iniciar un flujo de trabajo en un elemento de lista, tienes que hacerlo a través de la página de inicio de flujo de trabajo y, si el workflow tiene un formulario de inicialización, también tendrás que escribir estos parámetros. Con estas limitaciones, SharePoint no permite a los usuarios iniciar un flujo de trabajo en múltiples elementos, pero ¿por qué no puedo hacerlo con un flujo de trabajo sin parámetros?

Creo que esto es una característica que falta en SharePoint 2010 porque podríamos hacerlo usando la API de SharePoint o los servicios Web sin problemas. Y ahora ¿qué podemos hacer para implementar esta funcionalidad?

 

Primero tenemos que crear un comando de la ribbon mediante una acción personalizada y en esta acción, tenemos dos opciones para comenzar el flujo de trabajo, la primera de ellas es utilizando una página de aplicación, pasando los elementos seleccionados como parámetros y utilizar el servidor api para iniciar el proceso y la segunda opción, más flexible y elegante, usando JavaScript y los servicios Web de SharePoint para iniciar el flujo en cada uno de los elementos seleccionados.

SPServices al recates!!

Como bien saben, SPServices en una librería de jQuery que encapsula los servicios Web de SharePoint de forma que podamos utilizarlos con bastante sencillez. SPServices tiene un espacio de nombre para Workflow con operaciones que nos permiten iniciar un flujo (StartWorkflow), inclusive si este tuviera parámetros.

Es tan fácil de usar, sólo necesitamos la URL del elemento, el id de la plantilla de flujo de trabajo y, si fuera necesario, los parámetros.

$().SPServices({

operation: “StartWorkflow”,

item: currentItemURL,

templateId: workflowGUID,

workflowParameters: workflowParams,

async: true,

completefunc: function () {

SP.UI.Notify.addNotification(“Workflow process started on selected item.”, false);

}

});

 

Para obtener el id de la plantilla, SPServices nos proporciona otra función (GetTemplatesForItem) que nos devuelve todos los flujos asociados a un elemento. Todo lo que tenemos que hacer es obtener las plantillas y encontrar nuestro flujo por nombre.

$().SPServices({

operation: “GetTemplatesForItem”,

item: itemURL,

async: true,

completefunc: function (xData, Status) {

var currentItemURL = this.item;

$(xData.responseXML).find(“WorkflowTemplates > WorkflowTemplate”).each(function (i, e) {

if ($(this).attr(“Name”) == “Invoice Approve”) {

var guid = $(this).find(“WorkflowTemplateIdSet”).attr(“TemplateId”);

if (guid != null) {

workflowGUID = “{“ + guid + “}”;

//En este punto, tenemos nuestros id y tenemos que hacer el inicio del workflow }

}

}

}

})

 

Ahora, en el método de la acción personalizada, tenemos que recorrer todos los elementos seleccionados y utilizar el método StartWorkflow, de SPServices, para cada uno.

function StarSignWorkflow(listId) {

RemoveAllStatus(true);

waitDialog = SP.UI.ModalDialog.showWaitScreenWithNoClose(‘Starting approval workflow process on selected item’, ‘Please, wait until we finished this long operation.’, 76, 400);

 

//Get the selected items

clientContext = new SP.ClientContext.get_current();

var web = clientContext.get_web();

var list = web.get_lists().getById(listId);

var items = SP.ListOperation.Selection.getSelectedItems(ctx);

totaSelItems = items.length;

 

//Because only have items Id, we need to use Client Object Model to get EncodeAbsUrl.

var query = new SP.CamlQuery();

var queryString = ‘<View><Query><Where><In><FieldRef Name=”ID”/><Values>’;

for (index in items) {

var valueString = ‘<Value Type=”Integer”>’ + items[index].id + ‘</Value>’;

queryString = queryString + valueString;

}

query.set_viewXml(queryString + ‘</Values></In></Where></Query></View>’);

this.collListItems = list.getItems(query);

clientContext.load(collListItems, ‘Include(EncodedAbsUrl)’);

//In the success callback, we’ll have all the selected items with the absolute url.

clientContext.executeQueryAsync(Function.createDelegate(this, this.onInitProcessSuccess), Function.createDelegate(this, this.onInitProcessFail));

}

function onInitProcessSuccess() {

var listItemEnumerator = this.collListItems.getEnumerator();

 

//If our workflow has default init param, we can provide it in this way to run workflow with default values.

var workflowParams = “<Data><Approvers></Approvers><NotificationMessage></NotificationMessage>” +

“<DurationforSerialTasks></DurationforSerialTasks><DurationUnits></DurationUnits>” +

“<CC></CC><CancelonRejection></CancelonRejection><CancelonChange></CancelonChange>” +

“<EnableContentApproval></EnableContentApproval></Data>”;

try {

var counter = 1;

var total = totaSelItems;

 

//Traverse all the selected items

while (listItemEnumerator.moveNext()) {

var oListItem = listItemEnumerator.get_current();

var itemURL = oListItem.get_item(‘EncodedAbsUrl’);

var workflowGUID = null;

 

//Before start the workflow, we used GetTemplatesForItem to get Workflow Template Id.

$().SPServices({

operation: “GetTemplatesForItem”,

item: itemURL,

async: true,

completefunc: function (xData, Status) {

var currentItemURL = this.item;

$(xData.responseXML).find(“WorkflowTemplates > WorkflowTemplate”).each(function (i, e) {

if ($(this).attr(“Name”) == “Invoice Approve”) {

var guid = $(this).find(“WorkflowTemplateIdSet”).attr(“TemplateId”);

if (guid != null) {

workflowGUID = “{“ + guid + “}”;

$().SPServices({

operation: “StartWorkflow”,

item: currentItemURL,

templateId: workflowGUID,

workflowParameters: workflowParams,

async: true,

completefunc: function () {

if (total == counter) {

if (waitDialog != null) {

waitDialog.close();

}

SP.UI.Notify.addNotification(“Started workflow approved process for selected invoice.”, false);

window.location.reload();

}

counter++;

}

});

}

}

});

}

});

}

} catch (e) {

if (waitDialog != null) {

waitDialog.close();

}

AddStatus(“There is an exception. Error: “ + e.message, “red”);

}

}

Como hemos visto, tenemos una forma sencilla de permitir a nuestros usuarios iniciar un flujo en varios elementos a la misma vez, gracias a SPServices que nos facilita la vida para trabajar con SharePoint desde cliente.

 

Saludos a todos…

SharePoint 2013. Como se hizo CompartiMOSS.com

Un gran paso para la comunidad y para SharePoint!

Si ya disfrutábamos de la revista CompartiMOSS y de todo su contenido relacionado con SharePoint en PDF, ahora, además, tenemos un portal donde podemos leer los artículos y buscar en su contenido.

Gracias a la oportunidad que nos han brindado desde la dirección de la revista y aprovechando que tenemos nueva versión de SharePoint, desde General de Software hemos implementado este sitio utilizando las nuevas características de publicación de SharePoint 2013.

 

Diseño

Nuestro experto en UX, Santiago Porras, ha diseñado (a base de latigazos J) todo el sitio basándose en las revistas anteriores y en la aplicación de Windows 8 que creó para ella. Todo esto, utilizando el nuevo Design Manager que nos permitió implementar, desde WebMatrix, la página maestra del sitio y las plantillas de páginas que necesitábamos para el contenido.

Contenido

SharePoint utiliza toda su potencia como gestor documental para las funcionalidades de publicación y esto nos permite crear tipos de contenido para la definición de Números de la revista, Artículos de la Revista, Autor y Partner. Con estos tipos de contenidos, definimos la información que necesitamos para cada uno, por ejemplo, para los Artículos definimos el campo Número de la revista, utilizando la taxonomía de navegación, y el campo Autor, también utilizando la taxonomía de navegación. Así, cuando creamos un artículo le especificamos, utilizando el selector de etiquetas, el número al que pertenece y su autor, entre otras propiedades.

Para mostrar resúmenes de contenido, hemos utiliza el nuevo Web Part de Búsqueda de contenido. Este Web Part nos permite consultar el contenido indexado, filtrarlo por la jerarquía de navegación actual, etc. Además, los nuevos Display Template nos permite diseñar como se va a representar la información, utilizando JavaScript y HTML, con lo que nos olvidamos de los XSL Template que tenemos en otros Web Parts de consulta de contenido.

Navegación

Para favorecer el SEO, utilizamos la nueva Navegación administrada, mediante una jerarquía de etiquetas de nuestros metadatos administrados. La idea es que para acceder a un número de la revista, utilicemos la url http://www.compartimoss.com/revistas/numero-14 y no la url de su ubicación real http://www.compartimoss.com/paginas/revistas/numero-14.aspx. Aprovechando que ya se ha publicado el número 14, os recomiendo un artículo sobre SEO en SharePoint 2013 del amigo Jose Quinto.

En cuanto a la navegación, comentaros que nos queda algún que otro problemilla que solucionar, ya que si no usamos el Web Part de Búsqueda de Contenido y utilizamos el de Consulta de Contenido o el de Vínculos de Resumen, no termina de responder adecuadamente a las url administradas y hemos tenido que poner las físicas, ya que teníamos que publicar el sitio. Lo corregiremos, aunque por lo que hemos podido averiguar, parece un bug y tendremos que crear nuestros propios Web Parts para esto.

Búsquedas

Algo que veíamos fundamental, en la web de CompartiMOSS, es que se pueda buscar el contenido de un artículo y eso SharePoint lo sabe hacer muy bien. Utilizando el buscador empresarial, indexamos todo el contenido, las páginas de artículos y los números que tenemos en PDF, para que se pueda buscar sobre él.

Aprovechando la taxonomía hemos incluido, en los resultados de las búsquedas, un Web Part de refinamiento que nos permite filtrar por Número, Autor o Etiqueta del artículo.

Siguiente versión

Ya tenemos planteadas nuevas funcionalidades, que ya iremos contando. De momento, el primer paso será actualizar la aplicación de Windows 8 para que lea el contenido directamente de SharePoint y publicar la versión de Windows Phone.

 

Saludos a todos…

 

P.D. Recordaros que el licenciamiento en SharePoint 2013 ha cambiado y que la licencia de servidor para publicación se ha sustituido por la licencia de servidor normal, con lo que se ha rebajado el precio considerablemente.

Cómo los mayas no pudieron evitarlo, seguimos un año más

Otro año toca, entramos en el 2013 sobreponiéndonos a las predicciones Mayas del fin del mundo y al intento de los políticos de acabar con todo lo conocido y habitual de este mundo. Nos toca aprender de lo pasado en el 2011 y en el 2012 para conseguir superar el 2013, pese a quién le pese. Bajo mi humilde opinión, sólo lo podemos conseguirlo emprendiendo e innovando, consiguiendo que nuestras viejas y nuevas ideas lleguen a materializarse y que empiecen a caminar. Lo que siempre comento cuando hablo de emprender desarrollando para las Store, lanza una primera pequeña versión de tu idea, estudia cómo evoluciona y si funciona, ponte con ella para conseguir que te mantenga.

Como todos los años, gracias a todos por vuestra lectura, por vuestros aportes y por otro año más que, a rasgos generales, os resumo:

WebCast

CompartiMOSS

  • Número 11. Hablamos sobre UXDesignPoint, un punto de encuentro para diseñadores de SharePoint dentro de SUGES
  • Número 12. Enseñamos los usuarios externos de SharePoint Online
  • Número 13. Artículo sobre la novedades en Social Enterprise de SharePoint 2013 y me tocó entrevista personal.
  • Publicamos la app de Windows 8

TenerifeDev

Artículos destacados

Iniciamos este 2013 con el primer logro, de muchos que me planteo conseguir: mi tercer año como MVP en SharePoint Server. Un logro que no se consigue solo, necesitas de un gran equipo (Santiago Porras, Gregorio Dorta, TenerifeDev, SUGES, CompartiMOSS, etc.) que te ayude a conseguirlo, una gran empresa (General de Software) que te apoye con él y una familia que te entienda y te permita tener tiempo para todo esto, por esto y mucho más GRACIAS A TODOS.

 

Sólo me queda desearos un feliz año 2013, esperando que sigamos todos consiguiendo nuestras metas y logros, pese a quién le pese.

 

Saludos a todos…