Download presentation
Published byMildred Thompson Modified over 8 years ago
1
Dynamic UI Generation with Alfresco Share and Aikau
Kevin Dorr Sr. Solutions Engineer Alfresco Channel Americas
2
Agenda What Why Where How
3
What is Aikau? A Interesting Story
4
Aikau History 1st lifeguard at Waimea Bay – over 500 rescues
In 1978, the Polynesian Voyaging Society was seeking volunteers for a 30 day, 2,500-mile (4,000 km) journey to follow the ancient route of the Polynesian migration between the Hawaiian and Tahitian island chains. At 31 years of age, Aikau joined the voyage as a crew member. TheHokule'a left the Hawaiian islands on March 16, The double-hulled voyaging canoe developed a leak in one of the hulls and later capsized about twelve miles (19 km) south of the island of Molokai. In an attempt to get help, Aikau paddled toward Lanai on his surfboard.[6] Although the rest of the crew was later rescued by the U.S. Coast Guard Cutter Cape Corwin, Aikau was never seen again. He removed his lifejacket since it was hindering his paddling of the surfboard. The ensuing search for Aikau was the largest air-sea search in Hawaiian history
5
UI / UX is Terrifying and Complex
In the 1970s, bumper stickers and T-shirts with the phrase "Eddie Would Go" spread around the Hawaiian Islands and to the rest of the world. According to maritime historian Mac Simpson, "Aikau was a legend on the North Shore, pulling people out of waves that no one else would dare to. That's where the saying came from -- Eddie would go, when no else would or could. Only Eddie dared."[7] The phrase originated during the first Eddie contest. The waves were huge and the conditions were extremely dangerous. While the contest organizers were discussing whether to put it on, Mark Foo looked at the conditions and said "Eddie would go." The phrase stuck and the Eddie went
6
Custom UI Development, Really?
Yeah Really!
7
Some Things People Say to Me
Share would be great if it just had a way to… Share seems just like Sharepoint, except then you find out it’s not. Share is way more than I want to expose my users to… I really liked that Workdesk thing that you guys had. Why did you get rid of it again? I want my user experience to look exactly like this: I’m porting my product so that it will work with Share. So how do I do that?
8
Example Aikau User Interfaces
9
Ok, So Where is this Stuff, Anyway
Using Aikau and Aikau Tools
10
The Aikau Screen Builder
Circa 2014… Circa 2013…
11
Displaying an Aikau Page
Stand Alone Page Webscripts /share/page/dp/ws/{webscript URL} /share/page/site/{site}/dp/ws/{ws URL} Hybrid Pages (Share header and footer) /share/page/hdp/ws/{ws URL} Hybrid Remote Pages (from Repo) /share/page/site/{site}/p/{page name} /share/page/hrp/p/{page name}
12
Adding an Aikau Page to a Site
Hook to an Existing Page I will show an example Pass the Current Context to a New Page We will publish an example Or, Create a New Standalone Page and Configure it In through the Site Menu Same as it was
13
Aikau Resources Blogs! Summit Videos Ole Hejlskov’s Tutorial
Search for Dave Draper Summit Videos Last year = 100 level This year = 200 level Ole Hejlskov’s Tutorial Documentation! Me! We are interested in hearing about your projects!
14
Just How Flexible Is It? Aikau Widgets, Styling, and Internationalization
15
Alfresco Widget Library
16
Adding Widgets Easy to Add New Widgets
Please open source if appropriate! Commerical opportunity! Dojo Widgets can be Used Directly I showed an example of extending a Dojo widget last year But… You can Configure in ANY JS Library! I will show a jQuery example We will publish an Angluar example Let us know what other examples you would like!
17
Styling and Themes Widgets can Have an Individual CSS File
Add the CSS to the META-INF directory Theme support is limited right now Widgets need to use a common convention in order for themes to work Engineering has not focused on this yet But, it will be coming!
18
Text and Internationalization
Best Practice is to Use a Properties File Add all of your UI strings as properties Get them using the msg.get() function This Allows the Interface to be Internationalized using Filename Extensions A properties file with a “fr” extension will be selected if the interface is in French mode Just like standard Java
19
The Nitty Gritty “Wax Your Board!”
20
To Review… Files need to be in the same directory
page-name.get.desc.xml (Webscript Descriptor) page-name.get.js (WebScript Controller) page-name.get.html.ftl (Freemarker Template) page-name.get.properties (Optional Text Strings) Files need to be in the same directory Anywhere under site-webscripts is ok
21
To Review… Page Descriptor
<webscript> <shortname>Create page via JSON editor</shortname> <description>A page definition for creating pages using a JSON editor</description> <family>Aikau</family> <url>/page-editor</url> </webscript>
22
To Review… Freemarker Template
group="share"/>
23
To Review… the JS Page Controller
{ "widgets": [ "id": "SET_PAGE_TITLE", "name": "alfresco/header/SetTitle", "config": { "title": "Alfresco Summit Demo" } }, "name": "alfresco/layout/AlfSideBarContainer", "initialSidebarWidth": "300" ]
24
Page Layout Hand Code the JSON Programmatically Generate the JSON
I showed an example of extending a Dojo widget last year Programmatically Generate the JSON Interesting examples in the Faceted Search page Use the Page Creator Tool! Very functional – also configurable Great start on a page However, not all of the widgets are on the palette
25
Page Webscript Basics Define your JSON Any Way you Want
Once again, interesting examples in the Faceted Search page Add in Any Additional Logic You Need It’s a Javascript file! There are lots of built in Alfresco functions, Dojo function, etc. You can dynamically splice page components together – I will show an example
26
How Do I Get Data on the Page?
Services are Exposed as Components In the Page Builder Tool Palette Look at the search code for examples Also Special Data Widgets Quick and Dirty Data Structures (QuaDDS) Stores data structures you define as JSON in a folder in the repo in the Data Dictionary 1001 uses!
27
Capturing Events Events Use Pub/Sub Paradigm Pub/Sub is by Name
They will bubble up through the DOM You can also limit the scope – Dojo stuff Pub/Sub is by Name Easy to generate or subscribe to an event You can marshal a data package to go along with the event I will show some examples
28
Fully Dynamic Page Creation Example
“Eddie Would Go!”
29
Demonstration Scenario
Acme Manufacturing Technical Support Target: CSRs and Support Engineers Handle Problem Reports (mostly from Wiley E. Coyote) Extend the Basic Search Page Searches on Acme Case Specific Types Tune Searches for User Types Needs to be done Yesterday!!!
30
That Sinking Feeling
31
Leveraging an Existing Page
32
What We Will Do Add a Toggle to the Search Page
Toggle between the default keyword search and a “special” search page Add a Form on the Special Search Page Define the form with the Page Creation Tool Search for Particular Content Types Provide Different Search Criteria by User
33
Infrastructure and Code Setup
34
Setup to Extend the Search Form
Need to Define 2 Files: A Module Extension Definition The JavaScript for the Aikau Page/Form Extension Packaging Module extension in alfresco/site-data/extensions Code in alfresco/site-webscripts/… Deliver as a jar (for development) or AMP (for production)
35
Maven 2.0 Package Setup
36
Define the Module Extension File
File: alfresco/site-data/extensions/acme-special-search-extension.xml <extension> <modules> <module> <id>Acme Special Search</id> <auto-deploy>true</auto-deploy> <!-- Always pass evaluation --> <evaluator type="default.extensibility.evaluator"/> <!-- Apply the following webscript customizations when the base evaluator above passes --> <customizations> <!-- This handles full Aikau page customizations, e.g. faceted-search --> <customization> <targetPackageRoot>org.alfresco.share.pages.faceted-search </targetPackageRoot> <sourcePackageRoot>com.acme.customizations.special-search</sourcePackageRoot> </customization> </customizations> </module> </modules> </extension>
37
Adding the Search Toggle Button
38
Adding the Search Toggle Button
39
Dynamically Adding to the Search Page
Identify the Code to Extend Adding New Functionality to the Page Identify the Form to Add to Add Widget Definitions Handle the Toggle Event Using a Special Aikau Trick! Deploy and See What Happens!
40
Finding the Search Page Code
41
Finding the Search Page Code
42
Finding the Search Page Code
43
Search Page Code Files […]
Web Script: org/alfresco/share/pages/faceted-search/faceted-search.get Script Properties Id: org/alfresco/share/pages/faceted-search/faceted-search.get Short Name: Aikau Faceted Search Page […] File: org/alfresco/share/pages/faceted-search/faceted-search.get.desc.xml <webscript> <shortname>Aikau Faceted Search Page</shortname> <description>Prototype Aikau based Faceted Search Page</description> <family>Aikau</family> <url>/faceted-search</url> </webscript> File: org/alfresco/share/pages/faceted-search/faceted-search.get.html.ftl group="share"/> File: org/alfresco/share/pages/faceted-search/faceted-search.get.properties
44
Locating the ID to Hook Widgets To
File: org/alfresco/share/pages/faceted-search/faceted-search.get.js var scopeSelection = { id: "FCTSRCH_TOP_MENU_BAR", name: "alfresco/layout/LeftAndRight", config: { widgets: [ { name: "alfresco/html/Label", label: msg.get("faceted-search.scope.label") } }, name: "alfresco/menus/AlfMenuBar", id: "FCTSRCH_SCOPE_SELECTION_MENU", name: "alfresco/menus/AlfMenuBarSelect", <….>
45
Building the Page Toggle
File: alfresco/site-webscripts/com/acme/customizations/special-search/facted-search.get.js // Create links for hiding and showing the advanced search... var showAdvancedSearchLink = { name: "alfresco/renderers/PropertyLink", align: "right", config: { visibilityConfig: hideRegularSearch, currentItem: { label: "Display Acme Case Mgt Search" }, propertyToRender: "label", renderSize: "small", useCurrentItemAsPayload: false, publishTopic: "ALF_SHOW_ADVANCED_SEARCH", publishPayloadType: "CONFIGURED", publishPayload: { show: true } };
46
Building the Page Toggle
File: alfresco/site-webscripts/com/acme/customizations/special-search/facted-search.get.js var hideAdvancedSearchLink = { name: "alfresco/renderers/PropertyLink", align: "right", config: { visibilityConfig: showAdvancedSearch, currentItem: { label: "Display Regular Search" }, propertyToRender: "label", renderSize: "small", useCurrentItemAsPayload: false, publishTopic: "ALF_SHOW_ADVANCED_SEARCH", publishPayloadType: "CONFIGURED", publishPayload: { show: false } }; // Add the new widgets to the main stack... var topMenuBar = widgetUtils.findObject(model.jsonModel.widgets, "id", "FCTSRCH_TOP_MENU_BAR"); if (topMenuBar && topMenuBar.config && topMenuBar.config.widgets) { topMenuBar.config.widgets.splice(3, 0, showAdvancedSearchLink, hideAdvancedSearchLink);
47
Dynamic Form Extension!
48
Special Aikau Visibility Trick
File: alfresco/site-webscripts/com/acme/customizations/special-search/facted-search.get.js // Set up some config for showing and hiding the advanced search features... var showAdvancedSearch = { initialValue: false, rules: [ { topic: "ALF_SHOW_ADVANCED_SEARCH", attribute: "show", is: [true], isNot: [false] } ] }; var hideRegularSearch = { initialValue: true, is: [false], isNot: [true]
49
What it Looks Like
50
What it Looks Like
51
Adding the Search Forms
52
Generating a New Search Interface
53
Generating a New Search Interface
54
Generating a New Search Interface
55
Generating a New Search Interface
56
Generating a New Search Interface
57
Page Creator Output File: AcmeCSRForm.get.js model.jsonModel = {
publishOnReady: "", services: "", widgets: [ { name: "alfresco/forms/Form", config: { displayButtons: true, okButtonLabel: "OK", cancelButtonLabel: "Cancel", fieldId: "bff6e205-2af1-423b-81d7-79b2af7089a0", name: "alfresco/forms/controls/DojoValidationTextBox", label: "Case Id", name: "prop_acme_caseid", value: "", description: "Enter the case identifier" } },
58
Finding the Form to Append to
59
Finding the Search Code Hook
File: org/alfresco/share/pages/faceted-search/faceted-search.get.js // Compose the search form model var searchForm = { id: "FCTSRCH_SEARCH_FORM", name: "alfresco/forms/SingleTextFieldForm", config: { useHash: true, okButtonLabel: msg.get("faceted-search.search-form.ok-button-label"), okButtonPublishTopic : "ALF_SET_SEARCH_TERM", okButtonPublishGlobal: true, okButtonIconClass: "alf-white-search-icon", okButtonClass: "call-to-action", textFieldName: "searchTerm", textBoxIconClass: "alf-search-icon", textBoxCssClasses: "long hiddenlabel", textBoxLabel: msg.get("faceted-search.search-form.search-field-label") } };
60
Grabbing the Form Hook File: alfresco/site-webscripts/com/acme/customizations/special-search/facted-search.get.js var searchForm = widgetUtils.findObject(model.jsonModel.widgets, "id", "FCTSRCH_SEARCH_FORM"); if (searchForm && searchForm.config) { searchForm.config.scopeFormControls = false; searchForm.config.visibilityConfig = hideRegularSearch; }
61
Copy and Paste the Form Definition
File: alfresco/site-webscripts/com/acme/customizations/special-search/facted-search.get.js var advancedSearchOptions = [ { label: “CSR View", value: JSON.stringify([ // paste form fields for form 1 here ]) }, label: “Management View", // paste form fields for form 2 here } ];
62
After the Paste… File: alfresco/site-webscripts/com/acme/customizations/special-search/facted-search.get.js // Define two new custom forms - one for a CSR and one for a manager. Add as an array so that { var advancedSearchOptions = [ // we can use a selector to display and select which form: label: “CSR View", // pasted form fields for form 1 here: value: JSON.stringify([ name: "alfresco/forms/controls/DojoValidationTextBox", name: "prop_acme_caseid", label: "Case Id", config: { value: "", }, } description: "Enter the case identifier" name: "prop_case_customer", label: "Case Customer", description: "Enter the customer name" name: "prop_acme_casedescr", label: "Case Description", description: "Enter all or part of the case description" name: "alfresco/forms/controls/DojoSelect", name: "prop_acme_casestatus", label: "Case Status", description: "Select the case status", unitsLabel: "", fixed: [ optionsConfig: { value: "PendCustomer" label: "Pending Customer", value: "PendSupport" label: "Pending Support", value: "PendReseach" label: "Pending Research", label: "Pending Engineering", value: "PendEngineering" value: "PendStale" label: "Stale / Timed Out", ] name: "alfresco/forms/controls/DojoRadioButtons", name: "prop_acme_casedisposition", label: "Case Disposition", description: "Select the case disposition", value: "Open" label: "Case Open", label: "Case Closed", value: "Closed" value: "Deferred" label: "Case Deferred", ]) label: “Management View", // pasted form fields for form 2 here name: "prop_acme_caseoverdue", label: "Case Overdue", value: "true" label: "Yes", value: "false" label: "No", ];
63
Add the Container for the Forms
File: alfresco/site-webscripts/com/acme/customizations/special-search/facted-search.get.js // Create a form for selecting the advanced form... var advancedSearchFormSelect = { name: "alfresco/forms/Form", config: { showCancelButton: false, showOkButton: false, scopeFormControls: false, widgets: [ { name: "alfresco/forms/controls/DojoSelect", fieldId: "ADVANCED_SEARCH_OPTION", label: "Acme Case Data Search", visibilityConfig: showAdvancedSearch, optionsConfig: { fixed: advancedSearchOptions } ] };
64
Add the Container for the Forms
File: alfresco/site-webscripts/com/acme/customizations/special-search/facted-search.get.js // Create a form for selecting the advanced form... var advancedSearchFormSelect = { name: "alfresco/forms/Form", config: { showCancelButton: false, showOkButton: false, scopeFormControls: false, widgets: [ { name: "alfresco/forms/controls/DojoSelect", fieldId: "ADVANCED_SEARCH_OPTION", label: "Acme Case Data Search", visibilityConfig: showAdvancedSearch, optionsConfig: { fixed: advancedSearchOptions } ] };
65
Add the Code to Post the Form
File: alfresco/site-webscripts/com/acme/customizations/special-search/facted-search.get.js // Create a dynamic form for displaying each advanced form... var dynamicForm = { name: "alfresco/forms/DynamicForm", config: { visibilityConfig: showAdvancedSearch, scopeFormControls: false, subscriptionTopic: "_valueChangeOf_ADVANCED_SEARCH_OPTION", okButtonLabel: msg.get("faceted-search.search-form.ok-button-label"), okButtonPublishTopic: "ALF_ADVANCED_SEARCH", okButtonPublishGlobal: true, showCancelButton: false } }; // Bind the new widgets to the main stack... var mainVerticalStack = widgetUtils.findObject(model.jsonModel.widgets, "id", "FCTSRCH_MAIN_VERTICAL_STACK"); if (mainVerticalStack && mainVerticalStack.config && mainVerticalStack.config.widgets) { mainVerticalStack.config.widgets.splice(3, 0, advancedSearchFormSelect, dynamicForm);
66
Finished Result Page
67
Finished Result Page
68
Project Complete!
69
Bonus: Adding a Custom Widget
It’s Easy and Fun!
70
Additional Scenario Add a Slider Widget to the Search Page
Allow a user to use a slide to search by file size We will use a jQuery Slider, Since we like jQuery We’ll need to set up the jQuery JavaScript and CSS libraries
71
Module Definition File
File: alfresco/site-data/extensions/slider-extension.xml <extension> <modules> <module> <id>Custom Search Form</id> <auto-deploy>true</auto-deploy> <!-- Always pass evaluation --> <evaluator type="default.extensibility.evaluator"/> <!-- Apply the following webscript customizations when the base evaluator above passes --> <customizations> <!-- This handles full Aikau page customizations, e.g. faceted-search --> <customization> <targetPackageRoot>org.alfresco.share.pages.faceted-search</targetPackageRoot> <sourcePackageRoot>com.alfresco.customizations.slider</sourcePackageRoot> </customization> </customizations> <configurations> <config evaluator="string-compare" condition="WebFramework" replace="false"> <web-framework> <dojo-pages> <packages> <package name="summit" location="js/lib/summit"/> <package name="jquery" location="js/lib/jquery" main="jquery "/> <package name="jqueryui" location="js/lib/jquery-ui " main="jquery-ui"/> </packages> </dojo-pages> </web-framework> </config> </configurations>
72
JavaScript Customization
File: alfresco/site-webscripts/com/alfresco/customizations/slider/facted-search.get.js var searchForm = widgetUtils.findObject(model.jsonModel.widgets, "id", "FCTSRCH_SEARCH_FORM"); if (searchForm) { searchForm.name = "alfresco/forms/Form"; searchForm.config = { okButtonLabel: "Custom Search", okButtonPublishTopic : "ALF_ADVANCED_SEARCH", okButtonPublishGlobal: true, widgets: [ name: "summit/Slider", config: { name: "searchTerm", value: 50, label: "Slider", unitsLabel: "Gb" } ] };
73
Finished Result Page
74
Q&A Thank you for attending!
75
Finding the Search Code
File: org/alfresco/share/pages/faceted-search/faceted-search.get.js // Put all components together var main = { id: "FCTSRCH_MAIN_VERTICAL_STACK", name: "alfresco/layout/VerticalWidgets", config: { baseClass: "side-margins", widgets: [ { name: "alfresco/html/Spacer", height: "14px" } }, headingForSearchForm, searchForm, // more widget declarations
76
Finding the Search Code
File: org/alfresco/share/pages/faceted-search/faceted-search.get.js main.config.widgets.splice(2, 0, scopeSelection); // Append services with those required for search services.push("alfresco/services/NavigationService", "alfresco/services/SearchService", "alfresco/services/ActionService", "alfresco/services/DocumentService", "alfresco/dialogs/AlfDialogService", "alfresco/services/PreferenceService", "alfresco/services/QuickShareService", "alfresco/services/RatingsService", "alfresco/services/CrudService", "alfresco/services/NotificationService", "alfresco/services/ContentService"); // Add in the search form and search doc lib... widgets.unshift(accessMenu); widgets.push(main);
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.