Transcript

1

Mike HatfieldSenior Software Engineer, Alfresco

twitter: @mikehatfield

2

What We’ll Cover

• Architecture• Challenges to customization and extension

• Plans for improvement

• Case Study: the DoD 5015.2 Extensions• Extension Example

• Status Indicators• Custom Actions• Custom Metadata• Filters

3

4

Custom UICustom UI

Custom UICustom UI

Custom UICustom UI

New FiltersNew Filters

New FiltersNew Filters

New FiltersNew Filters

5

• Consolidate scattered action configuration• share-config-custom.xml instead of webscriptconfig• Still possible to restrict & specialise actions on details pages

• New actions via configuration where practicable• jar file for client-side UI assets, I18N• CSS and JS dependencies via config (see Forms & Header)

• Leverage Repository Actions & scripts• Custom Views

• Web-tier rendering• Open CMIS

6

7

Custom Actions

Numerous new and overridden actions to support the DoD requirements specification.

8

Custom Toolbar

Sensitive to current folder type. New and overridden actions.

Custom Filters

Removed unsuitable filters (user filters, tags). One static, one dynamic (populated from list of saved searches on the Repository).

9

“documentLibrary” container type determines components

10

11

documentlibrary.js

connector.get("/slingshot/doclib/container/" + siteId + "/" + containerId);"dod:filePlan"

model.doclibType = fromRepoType("dod:filePlan");“dod5015”

documentlibrary.js

connector.get("/slingshot/doclib/container/" + siteId + "/" + containerId);"dod:filePlan"

model.doclibType = fromRepoType("dod:filePlan");“dod5015”

documentlibrary.ftl

<@region id=doclibType+ "documentlist" scope="template" protected=true />

documentlibrary.ftl

<@region id=doclibType+ "documentlist" scope="template" protected=true />

Surf Component Binding

template.dod5015-documentlist.documentlibrary.xml

<url>/components/documentlibrary/dod5015/documentlist</url>

Surf Component Binding

template.dod5015-documentlist.documentlibrary.xml

<url>/components/documentlibrary/dod5015/documentlist</url>

12

DoD 5015.2 Method

documentlibrary.js

page = sitedata.getPage("site/" + siteId + "/dashboard");pageMeta = eval('(' + p.properties.pageMetadata + ')');contentType = doclibMeta.type;

connector.get("/slingshot/doclib/container/" + siteId + "/" + containerId+ “?type=“ + toRepoType(contentType));

”dod:filePlan”

documentlibrary.js

page = sitedata.getPage("site/" + siteId + "/dashboard");pageMeta = eval('(' + p.properties.pageMetadata + ')');contentType = doclibMeta.type;

connector.get("/slingshot/doclib/container/" + siteId + "/" + containerId+ “?type=“ + toRepoType(contentType));

”dod:filePlan”

presets.xml

<preset id="rm-site-dashboard"><page id="site/${siteid}/dashboard"><properties><pageMetadata>{"documentlibrary":{…, "type":"dod5015"}}</pageMetadata>

presets.xml

<preset id="rm-site-dashboard"><page id="site/${siteid}/dashboard"><properties><pageMetadata>{"documentlibrary":{…, "type":"dod5015"}}</pageMetadata>

13

Web QuickStart Method

LoadWebSiteDataGet.java

NodeRefdocLib = siteService.getContainer(siteId, COMPONENT_DOCUMENT_LIBRARY);

siteService.createContainer(siteId, COMPONENT_DOCUMENT_LIBRARY, WebSiteModel.TYPE_WEBSITE_CONTAINER, null);

ornodeService.setType(docLib, WebSiteModel.TYPE_WEBSITE_CONTAINER);

LoadWebSiteDataGet.java

NodeRefdocLib = siteService.getContainer(siteId, COMPONENT_DOCUMENT_LIBRARY);

siteService.createContainer(siteId, COMPONENT_DOCUMENT_LIBRARY, WebSiteModel.TYPE_WEBSITE_CONTAINER, null);

ornodeService.setType(docLib, WebSiteModel.TYPE_WEBSITE_CONTAINER);

dashlet

connector.get("/api/loadwebsitedata?site=" + siteId);

dashlet

connector.get("/api/loadwebsitedata?site=" + siteId);

14

YUI Helps

YUI developers added a number of helper functions to allow OO-style JavaScript modules.

• Notice:• constructor• superclass• extend• augment• etc…

15

• Full override / replacement control on all tiers.

• Your code can be almost completely independent of Alfresco’s.

Pros

• Mandatory component mapping , even for “native” components.

• Still have to copy/paste where <include> cannot be used, e.g. I18N.

• Repository folder type to component prefix issue.

• Not a 100% “clean” override mechanism.

Cons

16

Big Development Overhead

template.dod5015-actions-common.documentlibrary.xmltemplate.dod5015-documentlist.documentlibrary.xmltemplate.dod5015-file-upload.documentlibrary.xmltemplate.dod5015-fileplan.documentlibrary.xmltemplate.dod5015-flash-upload.documentlibrary.xmltemplate.dod5015-html-upload.documentlibrary.xmltemplate.dod5015-navigation.documentlibrary.xmltemplate.dod5015-savedsearch.documentlibrary.xmltemplate.dod5015-title.documentlibrary.xmltemplate.dod5015-toolbar.documentlibrary.xmltemplate.dod5015-tree.documentlibrary.xml…And that’s just the browse page!

17

• Overview • Customisations

• Status Indicators• Custom Metadata• New Filters• Custom Action

• Based on Alfresco Community 3.4.b• Need to use AMP on the Repository until refactoring work is complete• Share extensions via .jar and web-extension folder

18

Overview

19

20

Provide the user a quick indication of the current status of a folder or document, e.g. aspects applied.

Calculated in evaluator.lib.js

• Repository• evaluator.lib.js

• Share• I18N messages• Indicator images

21

/* Exif metadata */

if (node.hasAspect("exif:exif"))

{

status["exif"] = true;

}

/* Geographic */

if (node.hasAspect("cm:geographic"))

{

status["geographic"] = true;

}

22

1. share.jar!/org/springframework/extensions/surf/custom-slingshot-geographic-context.xml

<bean id="geographic.custom.resources" class="org.springframework.extensions.surf.util.ResourceBundleBootstrapComponent">

<property name="resourceBundles">

<list>

<value>alfresco.messages.geographic</value>

</list>

</property>

</bean>

1. share.jar!/alfresco/messages/geographic.properties

tip.geographic=Geo Location

tip.exif=EXIF Metadata

23

status[”exif"] = true;

status["geographic"] = true;

share.jar!/META-INF/components/documentlibrary/images

1.exif-indicator-16.png

2.geographic-indicator-16.png

24

Rendered entirely by the web browser from JSON data.

• Repository• item.lib.ftl• Maybe also JavaScript logic

• Share• I18N messages• Override cell renderer

25

1. alfresco.amp!/WEB-INF/classes/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/item.lib.ftl

<#if node.hasAspect("cm:geographic")>“geolocation”:{ "latitude": ${(node.properties["cm:latitude"]!0)?c}, "longitude": ${(node.properties["cm:longitude"]!0)?c}},</#if>

<#if node.hasAspect(”exif:exif")>“exif”:{ …},</#if>

26

1. shared/classes/alfresco/web-extension/site-webscripts/org/alfresco/components/documentlibrary/actions-common.get.head.ftl

<@script type="text/javascript" src="${page.url.context}/res/components/geographic/geographic-extension.js"></@script>

27

1. Override fnRenderCellDescription

share.jar!/META-INF/components/geographic/geographic-extension.js

YAHOO.util.Event.onContentReady("alf-hd", function(){ if (Alfresco.DocumentList) {Alfresco.DocumentList.prototype.fnRenderCellDescription = function

DL_fnRenderCellDescription() { … if (record.exif) {desc += scope.msg(“detail.exposure”) + record.exif.exposureTime; } … } }}

28

Allow easy filtering by any Repository logic, most commonly a Lucene or Alfresco FTS search query.

• Repository• filters.lib.js

• Share• I18N messages• Filter webscriptconfig

29

1. shared/classes/alfresco/web-extension/site-webscripts/org/alfresco/components/documentlibrary/filter.get.config.xml

<filters>

<filter id="geo" label="link.geo-located" />

<filter id="exif" label="link.exif" />

</filters>

30

1. alfresco.amp!/WEB-INF/classes/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/filters.lib.js

case "geo":filterQuery = "+PATH:\"" +parsedArgs.rootNode.qnamePath + "//*\"";filterQuery += "+ASPECT:\"cm:geographic\"";filterParams.query = filterQuery break;

case "exif":filterQuery = "+PATH:\"" +parsedArgs.rootNode.qnamePath + "//*\"";filterQuery += "+ASPECT:\"exif:exif\"";filterParams.query = filterQuery break;

31

Can be configured to only appear if a folder or document is in a particular state and/or the user has the correct permission(s) and/or the page is within a Site context and/or the action is on the browse or details page.

• Repository• evaluator.lib.js• Action processing (optional)

• Share• I18N messages• Action configuration• Client-side logic & images

32

/* Geographic */

if (node.hasAspect("cm:geographic"))

{

status["geographic"] = true;

permissions["geographic"] = true;

}

33

1. shared/classes/alfresco/web-extension/site-webscripts/org/alfresco/components/documentlibrary/documentlist.get.config.xml

2. shared/classes/alfresco/web-extension/site-webscripts/org/alfresco/components/document-details/document-actions.get.config.xml

3. etc…

<actionSet id="document">

<action type="simple-link" id="onActionGeographic" permission="geographic" href="{geographicUrl}" label="actions.document.geographic" />

</actionSet>

34

1. shared/classes/alfresco/web-extension/site-webscripts/org/alfresco/components/documentlibrary/actions-common.get.head.ftl

<@link rel="stylesheet" type="text/css" href="${page.url.context}/res/components/geographic/geographic-extension.css" />

2. share.jar!/META-INF/components/geographic/geographic-extension.css

.doclist .onActionGeographica{ background-image: url(pin.png) !important;}

35

var override = Alfresco.DocumentList || Alfresco.DocumentActions;

// Store reference to getActionUrls() function to allow extension.

vargetActionUrls_geographic = override.prototype.getActionUrls;

override.prototype.getActionUrls = function(recordData)

{

varactionUrls = getActionUrls_geographic.apply(this,

arguments);

actionUrls["geographicUrl"] = Alfresco.util.siteURL(

"geographic-map?nodeRef=" + recordData.nodeRef);

return actionUrls;

};

36

37

38

• Consolidate scattered action configuration• New actions via configuration where practicable• Remove references to non-core Share code• Leverage Repository Actions & scripts• Custom Views

39

• Feedback

40

wiki.alfresco.com/wiki/Shareblogs.alfresco.com/wp/mikeh/

top related