diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/action.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/action.lib.ftl new file mode 100644 index 0000000000..29c1c15fe5 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/action.lib.ftl @@ -0,0 +1,25 @@ +<#macro resultsJSON results> + <#escape x as jsonUtils.encodeJSONString(x)> +{ + "totalResults": ${results?size}, + "overallSuccess": ${overallSuccess?string}, + "successCount": ${successCount}, + "failureCount": ${failureCount}, + "results": + [ + <#list results as r> + { + <#list r?keys as key> + <#assign value = r[key]> + <#if value?is_number || value?is_boolean> + "${key}": ${value?string}<#if key_has_next>, + <#else> + "${key}": "${value}"<#if key_has_next>, + + + }<#if r_has_next>, + + ] +} + + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/action.lib.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/action.lib.js new file mode 100644 index 0000000000..815eeb45dc --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/action.lib.js @@ -0,0 +1,181 @@ +/** + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +/** + * Data List Component: action + * + * For a single-asset action, template paramters address the item. + * For multi-item actions, optional template parameters address the source or destination node, + * and a JSON body addresses the items involved in the action. + * + * @param uri {string} node/{store_type}/{store_id}/{id} + */ + +/** + * Main script entry point + * @method main + */ +function main() +{ + var nodeRef = null, + rootNode = null, + params = {}; + + if (url.templateArgs.store_type !== null) + { + /** + * nodeRef input: store_type, store_id and id + */ + var storeType = url.templateArgs.store_type, + storeId = url.templateArgs.store_id, + id = url.templateArgs.id; + + nodeRef = storeType + "://" + storeId + "/" + id; + rootNode = resolveVirtualNodeRef(nodeRef); + if (rootNode == null) + { + rootNode = search.findNode(nodeRef); + if (rootNode === null) + { + status.setCode(status.STATUS_NOT_FOUND, "Not a valid nodeRef: '" + nodeRef + "'"); + return null; + } + } + + params.nodeRef = nodeRef; + params.rootNode = rootNode; + } + + // Multiple input files in the JSON body? + var items = getMultipleInputValues("nodeRefs"); + if (typeof items != "string") + { + params.items = items; + } + + // Check runAction function is provided the action's webscript + if (typeof runAction != "function") + { + status.setCode(status.STATUS_BAD_REQUEST, "Action webscript must provide runAction() function."); + return; + } + + // Actually run the action + var results = runAction(params); + if (results) + { + if (typeof results == "string") + { + status.setCode(status.STATUS_INTERNAL_SERVER_ERROR, results); + } + else if (typeof results.status == "object") + { + // Status fields have been manually set + status.redirect = true; + for (var s in results.status) + { + status[s] = results.status[s]; + } + } + else + { + /** + * NOTE: Webscripts run within one transaction only. + * If a single operation fails, the transaction is marked for rollback and all + * previous (successful) operations are also therefore rolled back. + * We therefore need to scan the results for a failed operation and mark the entire + * set of operations as failed. + */ + var overallSuccess = true, + successCount = 0, + failureCount = 0; + + for (var i = 0, j = results.length; i < j; i++) + { + overallSuccess = overallSuccess && results[i].success; + results[i].success ? ++successCount : ++failureCount; + } + model.overallSuccess = overallSuccess; + model.successCount = successCount; + model.failureCount = failureCount; + model.results = results; + } + } +} + +/** + * Resolve "virtual" nodeRefs into nodes + * + * @method resolveVirtualNodeRef + * @param virtualNodeRef {string} nodeRef + * @return {ScriptNode|null} Node corresponding to supplied virtual nodeRef. Returns null if supplied nodeRef isn't a "virtual" type + */ +resolveVirtualNodeRef: function ParseArgs_resolveVirtualNodeRef(nodeRef) +{ + var node = null; + if (nodeRef == "alfresco://company/home") + { + node = companyhome; + } + else if (nodeRef == "alfresco://user/home") + { + node = userhome; + } + else if (nodeRef == "alfresco://sites/home") + { + node = companyhome.childrenByXPath("st:sites")[0]; + } + return node; +} + +/** + * Get multiple input values + * + * @method getMultipleInputValues + * @return {array|string} Array containing multiple values, or string error + */ +function getMultipleInputValues(param) +{ + var values = [], + error = null; + + try + { + // Was a JSON parameter list supplied? + if (typeof json != "undefined") + { + if (!json.isNull(param)) + { + var jsonValues = json.get(param); + // Convert from JSONArray to JavaScript array + for (var i = 0, j = jsonValues.length(); i < j; i++) + { + values.push(jsonValues.get(i)); + } + } + } + } + catch(e) + { + error = e.toString(); + } + + // Return the values array, or the error string if it was set + return (error !== null ? error : values); +} \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/duplicate.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/duplicate.post.desc.xml new file mode 100644 index 0000000000..243f9add69 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/duplicate.post.desc.xml @@ -0,0 +1,8 @@ + + duplicate + Data List Action - Duplicate single or multiple items + /slingshot/datalists/action/duplicate/node/{store_type}/{store_id}/{id} + argument + user + required + diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/duplicate.post.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/duplicate.post.json.ftl new file mode 100644 index 0000000000..e2f0e9da9f --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/duplicate.post.json.ftl @@ -0,0 +1,2 @@ +<#import "action.lib.ftl" as actionLib /> +<@actionLib.resultsJSON results=results /> \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/duplicate.post.json.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/duplicate.post.json.js new file mode 100644 index 0000000000..fbc8080ad8 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/duplicate.post.json.js @@ -0,0 +1,77 @@ + + +/** + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +/** + * Duplicate multiple items action + * @method POST + */ + +/** + * Entrypoint required by action.lib.js + * + * @method runAction + * @param p_params {object} Object literal containing items array + * @return {object|null} object representation of action results + */ +function runAction(p_params) +{ + var results = [], + items = p_params.items, + item, result, nodeRef; + + // Must have array of items + if (!items || items.length == 0) + { + status.setCode(status.STATUS_BAD_REQUEST, "No items."); + return; + } + + for (item in items) + { + nodeRef = items[item]; + result = + { + nodeRef: nodeRef, + action: "duplicateItem", + success: false + } + + try + { + itemNode = search.findNode(nodeRef); + if (itemNode != null) + { + // TODO: DUPLICATE NODE + } + } + catch (e) + { + result.success = false; + } + + results.push(result); + } + + return results; +} + +/* Bootstrap action script */ +main(); diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/items.delete.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/items.delete.desc.xml new file mode 100644 index 0000000000..66d1385765 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/items.delete.desc.xml @@ -0,0 +1,8 @@ + + files + Data List Action - Delete single or multiple items + /slingshot/datalists/action/items + argument + user + required + diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/items.delete.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/items.delete.json.ftl new file mode 100644 index 0000000000..e2f0e9da9f --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/items.delete.json.ftl @@ -0,0 +1,2 @@ +<#import "action.lib.ftl" as actionLib /> +<@actionLib.resultsJSON results=results /> \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/items.delete.json.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/items.delete.json.js new file mode 100644 index 0000000000..de5df33a63 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/action/items.delete.json.js @@ -0,0 +1,77 @@ + + +/** + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +/** + * Delete multiple items action + * @method DELETE + */ + +/** + * Entrypoint required by action.lib.js + * + * @method runAction + * @param p_params {object} Object literal containing items array + * @return {object|null} object representation of action results + */ +function runAction(p_params) +{ + var results = [], + items = p_params.items, + item, result, nodeRef; + + // Must have array of items + if (!items || items.length == 0) + { + status.setCode(status.STATUS_BAD_REQUEST, "No items."); + return; + } + + for (item in items) + { + nodeRef = items[item]; + result = + { + nodeRef: nodeRef, + action: "deleteItem", + success: false + } + + try + { + itemNode = search.findNode(nodeRef); + if (itemNode != null) + { + result.success = itemNode.remove(); + } + } + catch (e) + { + result.success = false; + } + + results.push(result); + } + + return results; +} + +/* Bootstrap action script */ +main(); diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/data.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/data.post.desc.xml new file mode 100644 index 0000000000..b85fd1ee9a --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/data.post.desc.xml @@ -0,0 +1,9 @@ + + DataLists - Data retrieval + Data Lists Component - retrieve data within a given list + /slingshot/datalists/data/site/{site}/{container}/{list} + /slingshot/datalists/data/node/{store_type}/{store_id}/{id} + argument + user + required + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/data.post.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/data.post.json.ftl new file mode 100644 index 0000000000..95d7957faf --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/data.post.json.ftl @@ -0,0 +1,36 @@ +<#import "item.lib.ftl" as itemLib /> +<#escape x as jsonUtils.encodeJSONString(x)> +{ + "totalRecords": ${data.paging.totalRecords?c}, + "startIndex": ${data.paging.startIndex?c}, + "metadata": + { + "parent": + { + <#if data.parent??> + <#assign parentNode = data.parent.node> + "nodeRef": "${parentNode.nodeRef}", + "permissions": + { + "userAccess": + { + <#list data.parent.userAccess?keys as perm> + <#if data.parent.userAccess[perm]?is_boolean> + "${perm?string}": ${data.parent.userAccess[perm]?string}<#if perm_has_next>, + + + } + } + + } + }, + "items": + [ + <#list data.items as item> + { + <@itemLib.itemJSON item /> + }<#if item_has_next>, + + ] +} + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/data.post.json.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/data.post.json.js new file mode 100644 index 0000000000..6b2b8f8c22 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/data.post.json.js @@ -0,0 +1,111 @@ + + + + +/** + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +/** + * Main entry point: Return data list with properties being supplied in POSTed arguments + * + * @method getData + */ +function getData() +{ + // Use helper function to get the arguments + var parsedArgs = ParseArgs.getParsedArgs(); + if (parsedArgs === null) + { + return; + } + + var fields = null; + // Extract fields (if given) + if (json.has("fields")) + { + // Convert the JSONArray object into a native JavaScript array + fields = []; + var jsonFields = json.get("fields"), + numFields = jsonFields.length(); + + for (count = 0; count < numFields; count++) + { + fields.push(jsonFields.get(count).replace("_", ":")); + } + } + + // Try to find a filter query based on the passed-in arguments + var filter = parsedArgs.filter, + allNodes = [], node, + items = []; + + var filterParams = Filters.getFilterParams(filter, parsedArgs) + query = filterParams.query; + + // Query the nodes - passing in default sort and result limit parameters + if (query !== "") + { + allNodes = search.query( + { + query: query, + language: filterParams.language, + page: + { + maxItems: (filterParams.limitResults ? parseInt(filterParams.limitResults, 10) : 0) + }, + sort: filterParams.sort, + templates: filterParams.templates, + namespace: (filterParams.namespace ? filterParams.namespace : null) + }); + + for each (node in allNodes) + { + try + { + items.push(Evaluator.run(node, fields)); + } + catch(e) {} + } + } + + return ( + { + fields: fields, + luceneQuery: query, + paging: + { + totalRecords: items.length, + startIndex: 0 + }, + parent: + { + node: parsedArgs.listNode, + userAccess: + { + create: parsedArgs.listNode.hasPermission("CreateChildren") + } + }, + items: items + }); +} + +/** + * Document List Component: doclist + */ +model.data = getData(); \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/evaluator.lib.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/evaluator.lib.js new file mode 100644 index 0000000000..79bc3d6008 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/evaluator.lib.js @@ -0,0 +1,205 @@ +/** + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +var Evaluator = +{ + /** + * Cache for cm:person objects + */ + PeopleObjectCache: {}, + + /** + * Gets / caches a person object + * + * @method getPersonObject + * @param nodeRef {string} NodeRef of a cm:person object + */ + getPersonObject: function Evaluator_getPersonObject(nodeRef) + { + if (nodeRef == null || nodeRef == "") + { + return null; + } + + if (typeof Evaluator.PeopleObjectCache[nodeRef] == "undefined") + { + var person = search.findNode(nodeRef); + Evaluator.PeopleObjectCache[nodeRef] = + { + userName: person.properties.userName, + firstName: person.properties.firstName, + lastName: person.properties.lastName, + displayName: (person.properties.firstName + " " + person.properties.lastName).replace(/^\s+|\s+$/g, "") + }; + if (person.assocs["cm:avatar"] != null) + { + Evaluator.PeopleObjectCache[nodeRef].avatar = person.assocs["cm:avatar"][0]; + } + } + return Evaluator.PeopleObjectCache[nodeRef]; + }, + + /** + * Cache for nodes that are subtypes of cm:cmobject + */ + ContentObjectCache: {}, + + /** + * Gets / caches a content object + * + * @method getContentObject + * @param nodeRef {string} NodeRef + */ + getContentObject: function Evaluator_getContentObject(nodeRef) + { + if (nodeRef == null || nodeRef == "") + { + return null; + } + + if (typeof Evaluator.ContentObjectCache[nodeRef] == "undefined") + { + var node = search.findNode(nodeRef); + try + { + Evaluator.ContentObjectCache[nodeRef] = node; + } + catch(e) + { + // Possibly a stale indexed node + return null; + } + } + return Evaluator.ContentObjectCache[nodeRef]; + }, + + /** + * Generate displayValue and any extra metadata for this field + */ + decorateFieldData: function Evaluator_decorateFieldData(objData, node) + { + var value = objData.value, + type = objData.type, + displayValue = value, + obj; + + if (type == "cm:person") + { + obj = Evaluator.getPersonObject(value); + if (obj != null) + { + displayValue = obj.displayName; + objData.metadata = obj.userName; + } + } + else if (type == "datetime" || type == "date") + { + objData.metadata = type; + } + else if (node.isSubType("cm:folder")) + { + obj = getContentObject(node.nodeRef); + if (obj != null) + { + displayValue = obj.displayPath.substring(companyhome.name.length() + 1); + } + } + else if (node.isSubType("cm:object")) + { + obj = getContentObject(node.nodeRef); + if (obj != null) + { + displayValue = obj.properties["cm:name"]; + } + } + + objData.displayValue = displayValue; + }, + + /** + * Node Evaluator - main entrypoint + */ + run: function Evaluator_run(node, fields) + { + var permissions = {}, + actionSet = "", + actionLabels = {}, + createdBy = Common.getPerson(node.properties["cm:creator"]), + modifiedBy = Common.getPerson(node.properties["cm:modifier"]), + nodeData = {}; + + /** + * PERMISSIONS + */ + permissions = + { + "create": node.hasPermission("CreateChildren"), + "edit": node.hasPermission("Write"), + "delete": node.hasPermission("Delete") + }; + + // Use the form service to parse the required properties + scriptObj = formService.getForm("node", node.nodeRef, fields, fields); + + // Make sure we can quickly look-up the Field Definition within the formData loop... + var objDefinitions = {}; + for each (formDef in scriptObj.fieldDefinitions) + { + objDefinitions[formDef.dataKeyName] = formDef; + } + + // Populate the data model + var formData = scriptObj.formData.data; + for (var k in formData) + { + var isAssoc = k.indexOf("assoc") == 0, + value = formData[k].value, + type = isAssoc ? objDefinitions[k].endpointType : objDefinitions[k].dataType, + objData = + { + type: type + }; + + if (value instanceof java.util.Date) + { + objData.value = utils.toISO8601(value); + } + else + { + // java.util.List instances are returned from ScriptFormData.java as Strings + objData.value = value; + } + + Evaluator.decorateFieldData(objData, node); + nodeData[k] = objData; + } + + return( + { + node: node, + nodeData: nodeData, + actionSet: actionSet, + actionPermissions: permissions, + createdBy: createdBy, + modifiedBy: modifiedBy, + tags: node.tags, + actionLabels: actionLabels + }); + } +}; diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/filters.lib.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/filters.lib.js new file mode 100644 index 0000000000..03eca60717 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/filters.lib.js @@ -0,0 +1,151 @@ +/** + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +var Filters = +{ + /** + * Create filter parameters based on input parameters + * + * @method getFilterParams + * @param filter {string} Required filter + * @param parsedArgs {object} Parsed arguments object literal + * @return {object} Object literal containing parameters to be used in Lucene search + */ + getFilterParams: function Filter_getFilterParams(filter, parsedArgs) + { + var filterParams = + { + query: "+PARENT:\"" + parsedArgs.nodeRef + "\" ", + limitResults: null, + sort: [ + { + column: "@{http://www.alfresco.org/model/content/1.0}name", + ascending: true + }], + language: "lucene", + templates: null + }; + + // Max returned results specified? + var argMax = args.max; + if ((argMax !== null) && !isNaN(argMax)) + { + filterParams.limitResults = argMax; + } + + // Create query based on passed-in arguments + var filterData = String(filter.filterData || ""), + filterQuery = filterParams.query; + + // Common types and aspects to filter from the UI + var filterQueryDefaults = + " -TYPE:\"{http://www.alfresco.org/model/content/1.0}systemfolder\"" + + " -@cm\\:lockType:READ_ONLY_LOCK"; + + switch (String(filter.filterId)) + { + case "recentlyAdded": + case "recentlyModified": + case "recentlyCreatedByMe": + case "recentlyModifiedByMe": + var onlySelf = (filterData.indexOf("ByMe")) > 0 ? true : false, + dateField = (filterData.indexOf("Created") > 0) ? "created" : "modified", + ownerField = (dateField == "created") ? "creator" : "modifier"; + + // Default to 7 days - can be overridden using "days" argument + var dayCount = 7, + argDays = args.days; + if ((argDays !== null) && !isNaN(argDays)) + { + dayCount = argDays; + } + + // Default limit to 50 documents - can be overridden using "max" argument + if (filterParams.limitResults === null) + { + filterParams.limitResults = 50; + } + + var date = new Date(); + var toQuery = date.getFullYear() + "\\-" + (date.getMonth() + 1) + "\\-" + date.getDate(); + date.setDate(date.getDate() - dayCount); + var fromQuery = date.getFullYear() + "\\-" + (date.getMonth() + 1) + "\\-" + date.getDate(); + + filterQuery = "+PARENT:\"" + parsedArgs.nodeRef; + if (parsedArgs.nodeRef == "alfresco://sites/home") + { + // Special case for "Sites home" pseudo-nodeRef + filterQuery += "/*/cm:dataLists"; + } + filterQuery += "\""; + filterQuery += " +@cm\\:" + dateField + ":[" + fromQuery + "T00\\:00\\:00.000 TO " + toQuery + "T23\\:59\\:59.999]"; + if (onlySelf) + { + filterQuery += " +@cm\\:" + ownerField + ":" + person.properties.userName; + } + filterQuery += " -TYPE:\"{http://www.alfresco.org/model/content/1.0}folder\""; + + filterParams.sort = [ + { + column: "@{http://www.alfresco.org/model/content/1.0}" + dateField, + ascending: false + }]; + filterParams.query = filterQuery + filterQueryDefaults; + break; + + case "createdByMe": + // Default limit to 50 documents - can be overridden using "max" argument + if (filterParams.limitResults === null) + { + filterParams.limitResults = 50; + } + + filterQuery = "+PARENT:\"" + parsedArgs.nodeRef; + if (parsedArgs.nodeRef == "alfresco://sites/home") + { + // Special case for "Sites home" pseudo-nodeRef + filterQuery += "/*/cm:dataLists"; + } + filterQuery += "\""; + filterQuery += " +@cm\\:modifier:" + person.properties.userName; + filterQuery += " -TYPE:\"{http://www.alfresco.org/model/content/1.0}folder\""; + filterParams.query = filterQuery + filterQueryDefaults; + break; + + case "node": + filterParams.query = "+ID:\"" + parsedArgs.nodeRef + "\""; + break; + + case "tag": + // Remove any trailing "/" character + if (filterData.charAt(filterData.length - 1) == "/") + { + filterData = filterData.slice(0, -1); + } + filterParams.query += "+PATH:\"/cm:taggable/cm:" + search.ISO9075Encode(filterData) + "/member\""; + break; + + default: + filterParams.query = filterQuery + filterQueryDefaults; + break; + } + + return filterParams; + } +}; diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/item.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/item.lib.ftl new file mode 100644 index 0000000000..fc8d9a0999 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/item.lib.ftl @@ -0,0 +1,67 @@ +<#macro itemJSON item> + <#escape x as jsonUtils.encodeJSONString(x)> + <#assign node = item.node> + <#assign tags><#list item.tags as tag>"${tag}"<#if tag_has_next>, + "nodeRef": "${node.nodeRef}", + "createdOn": "${xmldate(node.properties.created)}", + "createdBy": + { + "value": "${item.createdBy.userName}", + "displayValue": "${item.createdBy.displayName}" + }, + "modifiedOn": "${xmldate(node.properties.modified)}>", + "modifiedBy": + { + "value": "${item.modifiedBy.userName}", + "displayValue": "${item.modifiedBy.displayName}" + }, + "actionSet": "${item.actionSet}", + "tags": <#noescape>[${tags}], + "permissions": + { + "userAccess": + { + <#list item.actionPermissions?keys as actionPerm> + <#if item.actionPermissions[actionPerm]?is_boolean> + "${actionPerm?string}": ${item.actionPermissions[actionPerm]?string}<#if actionPerm_has_next>, + + + } + }, + <#if item.custom??>"custom": <#noescape>${item.custom}, + "actionLabels": + { + <#if item.actionLabels??> + <#list item.actionLabels?keys as actionLabel> + "${actionLabel?string}": "${item.actionLabels[actionLabel]}"<#if actionLabel_has_next>, + + + }, + "itemData": + { + <#list item.nodeData?keys as key> + <#assign data = item.nodeData[key]> + "${key}": + { + <#if data.value?is_boolean> + "value": ${data.value?string}, + <#elseif data.value?is_number> + "value": ${data.value?c}, + <#else> + "value": "${data.value}", + + <#if data.metadata??> + "metadata": "${data.metadata}", + + <#if data.displayValue?is_boolean> + "displayValue": ${data.displayValue?string} + <#elseif data.displayValue?is_number> + "displayValue": ${data.displayValue?c} + <#else> + "displayValue": "${data.displayValue}" + + }<#if key_has_next>, + + } + + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/item.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/item.post.desc.xml new file mode 100644 index 0000000000..ff31516a8d --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/item.post.desc.xml @@ -0,0 +1,8 @@ + + DataLists - Single item data retrieval + Data Lists Component - retrieve data for a single item by nodeRef + /slingshot/datalists/item/node/{store_type}/{store_id}/{id} + argument + user + required + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/item.post.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/item.post.json.ftl new file mode 100644 index 0000000000..0ed6ae7c0b --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/item.post.json.ftl @@ -0,0 +1,30 @@ +<#import "item.lib.ftl" as itemLib /> +<#escape x as jsonUtils.encodeJSONString(x)> +{ + "metadata": + { + "parent": + { + <#if data.parent??> + <#assign parentNode = data.parent.node> + "nodeRef": "${parentNode.nodeRef}", + "permissions": + { + "userAccess": + { + <#list data.parent.userAccess?keys as perm> + <#if data.parent.userAccess[perm]?is_boolean> + "${perm?string}": ${data.parent.userAccess[perm]?string}<#if perm_has_next>, + + + } + } + + } + }, + "item": + { + <@itemLib.itemJSON data.item /> + } +} + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/item.post.json.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/item.post.json.js new file mode 100644 index 0000000000..0ca5bf49d7 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/item.post.json.js @@ -0,0 +1,83 @@ + + + +/** + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +/** + * Main entry point: Return data list with properties being supplied in POSTed arguments + * + * @method getData + */ +function getData() +{ + // Use helper function to get the arguments + var parsedArgs = ParseArgs.getParsedArgs(); + if (parsedArgs === null) + { + return; + } + + var fields = null; + // Extract fields (if given) + if (json.has("fields")) + { + // Convert the JSONArray object into a native JavaScript array + fields = []; + var jsonFields = json.get("fields"), + numFields = jsonFields.length(); + + for (count = 0; count < numFields; count++) + { + fields.push(jsonFields.get(count).replace("_", ":")); + } + } + + // Try to find a filter query based on the passed-in arguments + var node = search.findNode(parsedArgs.nodeRef), + items = []; + + if (node != null) + { + try + { + item = Evaluator.run(node, fields); + } + catch(e) {} + } + + return ( + { + fields: fields, + parent: + { + node: parsedArgs.listNode, + userAccess: + { + create: parsedArgs.listNode.hasPermission("CreateChildren") + } + }, + item: item + }); +} + +/** + * Document List Component: doclist + */ +model.data = getData(); \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/list.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/list.lib.ftl new file mode 100644 index 0000000000..1fc5e5e73b --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/list.lib.ftl @@ -0,0 +1,11 @@ +<#macro listJSON list> + <#escape x as jsonUtils.encodeJSONString(x)> +{ + "name": "${list.name}", + "title": "${list.properties.title!list.name}", + "description": "${list.properties.description!""}", + "nodeRef": "${list.nodeRef}", + "itemType": "${list.properties["dl:dataListItemType"]!""}" +} + + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/lists.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/lists.get.desc.xml new file mode 100644 index 0000000000..2559e84268 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/lists.get.desc.xml @@ -0,0 +1,10 @@ + + DataLists + Data Lists Component - retrieve data lists within a given site and container, or by container nodeRef + /slingshot/datalists/lists/site/{site}/{container}/ + /slingshot/datalists/lists/site/{site}/{container} + /slingshot/datalists/lists/node/{store_type}/{store_id}/{id} + argument + user + required + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/lists.get.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/lists.get.js new file mode 100644 index 0000000000..aba59374c3 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/lists.get.js @@ -0,0 +1,46 @@ + + +/** + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +/** + * Main entry point: Return list of Data Lists + * + * @method getDataLists + */ +function getDataLists() +{ + // Use helper function to get the arguments + var parsedArgs = ParseArgs.getParsedArgs(); + if (parsedArgs === null) + { + return; + } + + return ( + { + container: parsedArgs.rootNode, + lists: parsedArgs.rootNode.children + }); +} + +/** + * Document List Component: doclist + */ +model.datalists = getDataLists(); \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/lists.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/lists.get.json.ftl new file mode 100644 index 0000000000..a7c477e328 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/lists.get.json.ftl @@ -0,0 +1,12 @@ +<#import "list.lib.ftl" as listLib /> +<#escape x as jsonUtils.encodeJSONString(x)> +{ + "container": "${datalists.container.nodeRef?string}", + "datalists": + [ + <#list datalists.lists as list> + <@listLib.listJSON list /><#if list_has_next>, + + ] +} + \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/parse-args.lib.js b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/parse-args.lib.js new file mode 100644 index 0000000000..7e9e355797 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/datalists/parse-args.lib.js @@ -0,0 +1,208 @@ +/** + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +var Common = +{ + /** + * Cache for person objects + */ + PeopleCache: {}, + + /** + * Gets / caches a person object + * + * @method getPerson + * @param username {string} User name + */ + getPerson: function Common_getPerson(username) + { + if (username == null || username == "") + { + return null; + } + + if (typeof Common.PeopleCache[username] == "undefined") + { + var person = people.getPerson(username); + if (person == null && username == "System") + { + person = + { + properties: + { + userName: "System", + firstName: "System", + lastName: "User" + }, + assocs: {} + }; + } + Common.PeopleCache[username] = + { + userName: person.properties.userName, + firstName: person.properties.firstName, + lastName: person.properties.lastName, + displayName: (person.properties.firstName + " " + person.properties.lastName).replace(/^\s+|\s+$/g, "") + }; + if (person.assocs["cm:avatar"] != null) + { + Common.PeopleCache[username].avatar = person.assocs["cm:avatar"][0]; + } + } + return Common.PeopleCache[username]; + } +}; + +var ParseArgs = +{ + /** + * Get and parse arguments + * + * @method getParsedArgs + * @param containerType {string} Optional: Node Type of container to create if it doesn't exist, defaults to "cm:folder" + * @return {array|null} Array containing the validated input parameters + */ + getParsedArgs: function ParseArgs_getParsedArgs(containerType) + { + var rootNode = null, + nodeRef = null, + listNode = null; + + if (url.templateArgs.store_type !== null) + { + /** + * nodeRef input: store_type, store_id and id + */ + var storeType = url.templateArgs.store_type, + storeId = url.templateArgs.store_id, + id = url.templateArgs.id; + + nodeRef = storeType + "://" + storeId + "/" + id; + rootNode = ParseArgs.resolveVirtualNodeRef(nodeRef); + if (rootNode == null) + { + rootNode = search.findNode(nodeRef); + if (rootNode === null) + { + status.setCode(status.STATUS_NOT_FOUND, "Not a valid nodeRef: '" + nodeRef + "'"); + return null; + } + } + + listNode = rootNode; + } + else + { + /** + * Site and container input + */ + var siteId = url.templateArgs.site, + containerId = url.templateArgs.container, + listId = url.templateArgs.list, + siteNode = siteService.getSite(siteId); + + if (siteNode === null) + { + status.setCode(status.STATUS_NOT_FOUND, "Site not found: '" + siteId + "'"); + return null; + } + + rootNode = siteNode.getContainer(containerId); + if (rootNode === null) + { + rootNode = siteNode.createContainer(containerId, containerType || "cm:folder"); + if (rootNode === null) + { + status.setCode(status.STATUS_NOT_FOUND, "Data Lists container '" + containerId + "' not found in '" + siteId + "'. (No permission?)"); + return null; + } + + rootNode.properties["cm:description"] = "Data Lists"; + rootNode.save(); + } + listNode = rootNode; + + if (listId !== null) + { + listNode = rootNode.childByNamePath(listId); + if (listNode === null) + { + status.setCode(status.STATUS_NOT_FOUND, "List not found: '" + listId + "'"); + return null; + } + } + } + + // Filter + var filter = null; + if (args.filter) + { + filter = + { + filterId: args.filter + }; + } + else if (typeof json !== "undefined" && json.has("filter")) + { + filter = jsonUtils.toObject(json.get("filter")); + if (filter == null) + { + filter = + { + filterId: "" + } + } + } + + var objRet = + { + rootNode: rootNode, + listNode: listNode, + nodeRef: String(listNode.nodeRef), + filter: filter + }; + + return objRet; + }, + + /** + * Resolve "virtual" nodeRefs into nodes + * + * @method resolveVirtualNodeRef + * @param virtualNodeRef {string} nodeRef + * @return {ScriptNode|null} Node corresponding to supplied virtual nodeRef. Returns null if supplied nodeRef isn't a "virtual" type + */ + resolveVirtualNodeRef: function ParseArgs_resolveVirtualNodeRef(nodeRef) + { + var node = null; + if (nodeRef == "alfresco://company/home") + { + node = companyhome; + } + else if (nodeRef == "alfresco://user/home") + { + node = userhome; + } + else if (nodeRef == "alfresco://sites/home") + { + node = companyhome.childrenByXPath("st:sites")[0]; + } + return node; + } +};