Presentation is loading. Please wait.

Presentation is loading. Please wait.

Dynamic UI Generation with Alfresco Share and Aikau

Similar presentations


Presentation on theme: "Dynamic UI Generation with Alfresco Share and Aikau"— Presentation transcript:

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);


Download ppt "Dynamic UI Generation with Alfresco Share and Aikau"

Similar presentations


Ads by Google