Developers Guide
User Manual:
Open the PDF directly: View PDF .
Page Count: 108
Download | |
Open PDF In Browser | View PDF |
Infor Homepages Widget SDK Developers Guide Copyright © 2019 Infor Important Notices The material contained in this publication (including any supplementary information) constitutes and contains confidential and proprietary information of Infor. By gaining access to the attached, you acknowledge and agree that the material (including any modification, translation or adaptation of the material) and all copyright, trade secrets and all other right, title and interest therein, are the sole property of Infor and that you shall not gain right, title or interest in the material (including any modification, translation or adaptation of the material) by virtue of your review thereof other than the non-exclusive right to use the material solely in connection with and the furtherance of your license and use of software made available to your company from Infor pursuant to a separate agreement, the terms of which separate agreement shall govern your use of this material and all supplemental related materials ("Purpose"). In addition, by accessing the enclosed material, you acknowledge and agree that you are required to maintain such material in strict confidence and that your use of such material is limited to the Purpose described above. Although Infor has taken due care to ensure that the material included in this publication is accurate and complete, Infor cannot warrant that the information contained in this publication is complete, does not contain typographical or other errors, or will meet your specific requirements. As such, Infor does not assume and hereby disclaims all liability, consequential or otherwise, for any loss or damage to any person or entity which is caused by or relates to errors or omissions in this publication (including any supplementary information), whether such errors or omissions result from negligence, accident or any other cause. Without limitation, U.S. export control laws and other applicable export and import laws govern your use of this material and you will neither export or re-export, directly or indirectly, this material nor any related materials or supplemental information in violation of such laws, or use such materials for any purpose prohibited by such laws. Trademark Acknowledgements The word and design marks set forth herein are trademarks and/or registered trademarks of Infor and/or related affiliates and subsidiaries. All rights reserved. All other company, product, trade or service names referenced may be registered trademarks or trademarks of their respective owners. Publication Information Release: Publication date: March 12, 2019 Document code: Contents Contents About this guide ................................................................................................................................. 11 Version log ..................................................................................................................................... 11 Contacting Infor.............................................................................................................................. 12 Chapter 1 Introduction .................................................................................................................. 13 Purpose ................................................................................................................................... 13 Who Should Read This Document .......................................................................................... 13 Widget Developer knowledge and responsibilities.................................................................. 13 Chapter 2 Overview ....................................................................................................................... 14 Introduction .................................................................................................................................... 14 Disclaimer ...................................................................................................................................... 15 AngularJS support removed .......................................................................................................... 15 Widget SDK Contents .................................................................................................................... 15 Documentation ........................................................................................................................ 16 API ..................................................................................................................................... 16 OpenSourceLicenses .............................................................................................................. 16 Samples ................................................................................................................................... 16 Widgets.............................................................................................................................. 16 Source ..................................................................................................................................... 16 Technologies.................................................................................................................................. 17 Enterprise Components for Infor Design System .......................................................................... 17 Chapter 3 Widgets ......................................................................................................................... 18 Widget framework .......................................................................................................................... 18 Widget types .................................................................................................................................. 18 Inline widget ............................................................................................................................. 18 jQuery widget .................................................................................................................... 18 Angular widget................................................................................................................... 19 Widget SDK Developers Guide | 3 Contents External widget ........................................................................................................................ 19 Hybrid widget ........................................................................................................................... 19 Widget technology choice .............................................................................................................. 19 Tenant widgets............................................................................................................................... 20 Tenant widgets disclaimer ............................................................................................................. 20 Widget manifest ............................................................................................................................. 21 Mandatory manifest properties ................................................................................................ 21 Widget ID ........................................................................................................................... 21 Type ................................................................................................................................... 21 Version .............................................................................................................................. 22 Name ................................................................................................................................. 22 Title, Description vs Localization ....................................................................................... 22 Module name ..................................................................................................................... 22 URL ................................................................................................................................... 23 Framework......................................................................................................................... 23 Author ................................................................................................................................ 24 Optional manifest properties ................................................................................................... 24 Display version .................................................................................................................. 24 AOT version....................................................................................................................... 24 Localization........................................................................................................................ 25 Category ............................................................................................................................ 27 Application logical ID ......................................................................................................... 28 Application version ............................................................................................................ 28 Shared modules ................................................................................................................ 28 Help URL ........................................................................................................................... 29 Settings.............................................................................................................................. 29 Default size ........................................................................................................................ 30 Max size ............................................................................................................................ 31 Enable publish ................................................................................................................... 31 Enable settings when published ....................................................................................... 31 Enable title edit .................................................................................................................. 31 Enable settings .................................................................................................................. 32 Enable application selector ............................................................................................... 32 Enable catalog................................................................................................................... 32 Enable custom properties ................................................................................................. 32 Enable refresh ................................................................................................................... 33 Icon file .............................................................................................................................. 33 Screen shots for the widget catalog .................................................................................. 34 4 | Widget SDK Developers Guide Contents Requires config ................................................................................................................. 34 Empty config ...................................................................................................................... 35 Target ................................................................................................................................ 35 Targets .............................................................................................................................. 36 Banner widget ................................................................................................................................ 36 Mobile widget ................................................................................................................................. 36 Enabling content for Infor Go .................................................................................................. 37 Enabling a widget for Infor Go ................................................................................................. 37 Widget menu in Infor Go.......................................................................................................... 38 Developing for mobile .............................................................................................................. 38 Limitations ......................................................................................................................... 38 Accessing native features ....................................................................................................... 38 Inline widget implementation ......................................................................................................... 39 Widget module ......................................................................................................................... 39 Widget factory function ............................................................................................................ 39 Widget context ......................................................................................................................... 40 Widget instance ....................................................................................................................... 40 Widget state ............................................................................................................................. 40 Widget activation ..................................................................................................................... 41 Identifiers for automated UI (E2E) tests .................................................................................. 41 Widget settings .............................................................................................................................. 42 Settings for a published widget ............................................................................................... 42 User settings for a published widget ................................................................................. 42 Implicit widget settings............................................................................................................. 43 External widget settings........................................................................................................... 43 Metadata settings UI................................................................................................................ 43 Custom settings UI .................................................................................................................. 44 Accessing settings ................................................................................................................... 44 Saving settings ........................................................................................................................ 44 Settings events ........................................................................................................................ 44 Settings opening................................................................................................................ 45 Settings saved ................................................................................................................... 45 Ad-hoc settings ........................................................................................................................ 45 Widget context values.................................................................................................................... 45 Resolving priority ..................................................................................................................... 46 Qualifying a value .................................................................................................................... 46 Using widget context values in a URL template ...................................................................... 47 Widget SDK Developers Guide | 5 Contents Accessing widget context values in code ................................................................................ 47 Ming.le application settings ..................................................................................................... 47 Framework values ................................................................................................................... 47 Using widget context values in the test container ................................................................... 48 Chapter 4 jQuery widgets.............................................................................................................. 49 Introduction .................................................................................................................................... 49 Widget factory function .................................................................................................................. 49 Performance tips ............................................................................................................................ 50 Creating a widget package ............................................................................................................ 50 Chapter 5 Angular widgets ........................................................................................................... 51 Introduction .................................................................................................................................... 51 AOT vs JIT ..................................................................................................................................... 51 AOT documentation................................................................................................................. 52 The future of AOT .................................................................................................................... 52 The future of JIT ...................................................................................................................... 52 Angular modules and components ................................................................................................ 52 Module imports ........................................................................................................................ 52 Module declarations and entry components ........................................................................... 53 Widget factory function .................................................................................................................. 53 JIT factory function .................................................................................................................. 53 AOT factory function ................................................................................................................ 53 File structure .................................................................................................................................. 54 Widget context and instance ......................................................................................................... 54 Constructor injection of widget context and instance ................................................. 55 Input properties for widget context and instance ........................................................ 55 Templates ...................................................................................................................................... 56 Creating a widget package ............................................................................................................ 56 Chapter 6 External widgets ........................................................................................................... 57 Introduction .................................................................................................................................... 57 External widget implementation .............................................................................................. 57 Creating a widget package ............................................................................................................ 58 Chapter 7 Localization................................................................................................................... 59 Localization .................................................................................................................................... 59 6 | Widget SDK Developers Guide Contents Localization scripts .................................................................................................................. 60 LangFromManifestToResx.js ............................................................................................ 60 LangFromResxToManifests.js .......................................................................................... 61 Chapter 8 Development environment .......................................................................................... 63 Introduction .................................................................................................................................... 63 Prerequisites .................................................................................................................................. 63 Samples ......................................................................................................................................... 64 Running the Samples in Visual Studio Code .......................................................................... 65 Running the Samples on a Node.js server.............................................................................. 65 Creating a new widget ................................................................................................................... 66 Testing with multiple widgets ......................................................................................................... 66 Static code analysis with TSLint .................................................................................................... 67 Running the linter .................................................................................................................... 67 Automatically fix problems ....................................................................................................... 67 Modifying or overriding rules ................................................................................................... 68 Chapter 9 Packaging ..................................................................................................................... 69 Files to include ............................................................................................................................... 69 Mandatory files ........................................................................................................................ 69 Optional files ............................................................................................................................ 69 File optimizations ........................................................................................................................... 70 Homepages command pack script ................................................................................................ 70 Directory rules.......................................................................................................................... 70 AOT compilation ...................................................................................................................... 70 Manifest ............................................................................................................................. 70 Widget factory files ............................................................................................................ 71 Prerequisites ............................................................................................................................ 71 Pack and optimize: .................................................................................................................. 71 Examples..................................................................................................................... 71 Output.......................................................................................................................... 72 Shared modules ...................................................................................................................... 72 Angular AOT package recommendation ................................................................................. 72 Manual minification ........................................................................................................................ 73 Single module widget .............................................................................................................. 73 Multi-module widget................................................................................................................. 73 Widget SDK Developers Guide | 7 Contents Packaging widgets for an on-premise installation ......................................................................... 73 Widget installation package file ............................................................................................... 74 Chapter 10 ION API .......................................................................................................................... 75 Introduction .................................................................................................................................... 75 Retrieving OAuth access token ..................................................................................................... 75 Token timeout .......................................................................................................................... 76 Development environment ............................................................................................................. 76 Prerequisites ............................................................................................................................ 76 Acquire an OAuth token string .......................................................................................... 76 Set up the development configuration .............................................................................. 77 Developing and debugging ...................................................................................................... 77 Chapter 11 Homepages Widget Certification................................................................................ 78 Certification checklist ..................................................................................................................... 78 Development checklist ................................................................................................................... 80 Chapter 12 Resources ..................................................................................................................... 82 Chapter 13 Appendix Node.js ......................................................................................................... 83 Node.js ........................................................................................................................................... 83 Install Node.js .......................................................................................................................... 83 Verify the Node package manager .......................................................................................... 83 Verify the Node executable ..................................................................................................... 84 Chapter 14 Appendix Test............................................................................................................... 85 Widget Test Scenarios................................................................................................................... 85 Scenario 1: Basic features ...................................................................................................... 85 Pre-requisites .................................................................................................................... 85 Test .................................................................................................................................... 85 Scenario 2: Widget sizes ......................................................................................................... 91 Pre-requisites .................................................................................................................... 91 Test .................................................................................................................................... 91 Scenario 3: Publish widget ...................................................................................................... 92 Pre-requisites .................................................................................................................... 92 Test .................................................................................................................................... 92 Scenario 4: Publish the widget with one or more settings enabled ........................................ 95 Pre-requisites .................................................................................................................... 95 Test .................................................................................................................................... 95 8 | Widget SDK Developers Guide Contents Scenario 5: Configure settings on a published page .............................................................. 97 Pre-requisites .................................................................................................................... 97 Test .................................................................................................................................... 97 Scenario 6: Import and Export page with the widget ............................................................ 100 Pre-requisites .................................................................................................................. 100 Test .................................................................................................................................. 100 Scenario 7: Widget Title Logic............................................................................................... 102 Pre-requisites......................................................................................................................... 102 Test.................................................................................................................................. 102 Scenario 8: Widget Translations ........................................................................................... 106 Pre-requisites .................................................................................................................. 106 Test .................................................................................................................................. 106 Scenario 9: Export and Import page with configured published widget ................................ 107 Pre-requisites .................................................................................................................. 107 Test .................................................................................................................................. 107 Scenario 10: Polling............................................................................................................... 108 Pre-requisites .................................................................................................................. 108 Test .................................................................................................................................. 108 Widget SDK Developers Guide | 9 About this guide Version log The version log describes the changes between versions of this document. Version Date Changes 1.0 First version of the document. 1.1 Added information about Shared Modules as well as its restrictions. 1.1.1 Added language information, removed internal links and updated checklist. 1.1.2 Added enablePublish, updated checklist. 1.1.3 Added new widget category, updated with new manifest configuration options. 1.1.4 Banner widget as target. 1.1.5 Widget Localization. 1.2 Updated all information to new Angular interfaces and Angular component development 1.2.1 Deprecated sharedWidgetId. Support for widget variants will be removed. 1.2.2 Added AOT support for Angular widgets. Deprecated previous minify scripts. Deprecated sub directories in widget zip package files. Added homepages command script for build, minify and package. 1.2.3 Added manifest property maxSize. 1.2.4 Added manifest property screenshots. 1.2.5 Removed SoHoXi references and added links to Infor Design System, https://design.infor.com/ and the widget design guide, https://design.infor.com/resources/mingle-homepage-widget-guidelines . 1.2.6 Added information about tenant widgets. Removed SharedWidgetId, no longer supported in 12.0.32. Added information about Mobile. Developers Guide | 11 About this guide Added empty config information Contacting Infor If you have questions about Infor products, go to the Infor Xtreme Support portal at www.infor.com/inforxtreme. If we update this document after the product release, we will post the new version on this Web site. We recommend that you check this Web site periodically for updated documentation. If you have comments about Infor documentation, contact documentation@infor.com. 12 | Widget SDK Developers Guide Chapter 1 Introduction 1 Purpose The purpose of this document is to describe how to set up a development environment and build widgets using the Widget SDK. Who Should Read This Document Roles for which this document is primarily intended: Role Skills Web Application developer JavaScript, TypeScript, Angular, jQuery Widget Developer knowledge and responsibilities The widget developer needs to have a deep understanding and knowledge developing web applications. The skills are not only the ones listed above but also how to develop secure web applications, which uses all available techniques to protect against different kinds of attacks. The developer should have a deep understanding of the OWASP top 10 vulnerabilities and how to avoid them. Although the code is reviewed for inconsistent use of the Homepages API it is up to the widget developer to provide a stable and secure widget that does not affect the Homepages application negatively. The widget developer is responsible for following the guidelines and checklists provided in this document. Developers Guide | 13 Overview Chapter 2 Overview 2 This chapter gives an overview of the Widget SDK. Introduction The Widget SDK is used to build widgets for Homepages in Infor Ming.le. A widget can be defined as: A small, single-purpose application that provides quick, at-a-glance information or quick access to simple interactive functions. Widgets are simpler and faster to access than full applications (apps) that may provide more functionality. Homepages may contain one or many pages and each page may contain one or many widgets. Widgets can be added to a page from the Widget Catalog. 14 | Widget SDK Developers Guide Overview Disclaimer Please note that only classes and functions documented in the Widget SDK API Documentation are publicly available for you to use. Anything that is not documented or explicitly marked with “internal” in the API documentation should not be used. Classes and functions that are not intended for public use may be removed or changed in future versions without notice. AngularJS support removed AngularJS support has been completely removed in Homepages version 12.0.32. Angular is the name for the Angular of today and tomorrow. AngularJS is the name for all v1.x versions of Angular. https://angular.io/guide/upgrade Widget SDK Contents This section describes the contents of the Widget SDK zip file. The folder structure can be seen below followed by an overview of each folder. - Documentation o API - OpenSourceLicenses - Samples o - Widgets Source o scripts ▪ lime ▪ typings ▪ vendor ▪ xi Widget SDK Developers Guide | 15 Overview Documentation Contains the developers guide in PDF format. API Contains the Widget SDK API documentation in HTML format. Open the index.html file in a browser to view the API documentation. OpenSourceLicenses Contains the license files for open source projects used in the Widget SDK. Samples Contains node scripts for web server, proxy and widget packaging. Additional npm package dependencies specified in package.json will also be installed into this directory. Widgets Contains all the sample widgets. Each sample widget folder also contains the generated JavaScript files with code comments for those that prefer plain JavaScript. This directory also contains configuration files for Visual Studio Code (.vscode/). Source Contains the Widget SDK script files, external dependencies, Enterprise components for Infor Design System and TypeScript typings files. 16 | Widget SDK Developers Guide Overview Technologies The Homepages framework is implemented using TypeScript, Angular and the Enterprise Components for Infor Design System. A widget may be implemented using these technologies as well but TypeScript and Angular are completely optional. Widgets should use the Enterprise Components for Infor Design System or follow Infor design guidelines. For widgets with limited functionality, use jQuery and the Enterprise Components for Infor Design System. Note that AngularJS has been deprecated, see AngularJS deprecated Enterprise Components for Infor Design System Enterprise Components for Infor Design System provides comprehensive tools for product development teams to create user experiences that are: Intuitive, Engaging, Purposeful, Functionally Relevant, and Beautiful. Enterprise Components for Infor Design System is a framework-independent UI component library built in js and css that is pattern-focused, template-driven, touch-enabled, responsive, accessible, and themable. Widget SDK Developers Guide | 17 Widgets Chapter 3 Widgets 3 This chapter describes the different widget types and widget related concepts. Widget framework The widget framework is responsible for the creation, layout and lifecycle management for all widgets. The widget framework also owns parts of what an end user would consider to be the widget. The widget border, widget title bar and widget menu are owned by the framework and a widget implementation is not allowed to directly access these parts of a widget. A widget implementation owns the widget body area, which is the area inside the widget border and below the widget title bar. Widget types There are two major types of widgets in Homepages which we will refer to as inline and external. There is also a hybrid type which, technically, is an inline widget with some external content. Inline widget An inline widget is loaded in the same page (DOM) as the Homepage framework. The widget may be implemented in JavaScript or TypeScript and can use the external frameworks supported by the Homepages framework such as jQuery and Angular. Since the widget is loaded in the same DOM as the framework it is very important that the widget does not interfere with the framework or other widgets on the page. The widget files are deployed on the Homepage server. This is the recommended widget type. jQuery widget jQuery widgets introduce the least technical overhead. For more information see chapter 4. 18 | Widget SDK Developers Guide Widgets Angular widget For more information see chapter 5. External widget An external widget is loaded in an IFrame using a URL that may contain parameters with values provided by the framework. The widget files may be deployed on any server that can be reached by the client. This widget type should be used with caution, especially if the external widget loads a lot of resources as it will impact the browser performance. This is not a recommended widget type. For more information see chapter 6. Hybrid widget A hybrid widget is an inline widget that creates an IFrame to load all or parts of its content. This type can be used when a widget requires more integration with the framework than is possible with an external widget, but the main widget content will be rendered by an external server. This widget type should be used with caution, especially if the external widget loads a lot of resources as it will impact the browser performance. This is not a recommended widget type. Widget technology choice After deciding the type of widget that you would like to develop, it’s time to make the technology choice for the framework that you would like to build the widget on, if you have decided to develop a hybrid or an inline widget. There are a few different choices, TypeScript or JavaScript. Angular or jQuery. Note that no other UI frameworks are allowed. For widgets with simple functionality and hybrids with for example a custom settings UI, jQuery is a good fit with minimal overhead. Pure jQuery widgets will also be faster, include less code as it does not need to have a JIT and an AOT bundle file as the Angular widgets do. With jQuery widgets, there is no need to deliver new packages as Homepages updates the Angular version which might be the case with AOT compiled widgets. For complex widgets Angular and TypeScript is a better fit. If Angular is the selected framework, we recommend that you use it with TypeScript. When it comes to the UI, if you develop in Angular you would use the Angular wrappers for the IDS Enterprise components, but if you use jQuery you would use the jQuery versions of the control library. Widget SDK Developers Guide | 19 Widgets To get familiar with the Angular component library, clone the below GitHub repository and follow the readme instructions on how to get the samples running locally. IDS Enterprise NG – Angular wrappers for the IDS Enterprise components https://github.com/infor-design/enterprise-ng Tenant widgets Tenant widgets are widgets developed by partners or customers for the cloud edition of Homepages. There is a certification process before a widget can be uploaded into a cloud environment. The process is not described in this document. The process will result in an artifact that can be uploaded and installed in Homepages. The concept of “Tenant widgets” are only applicable for the cloud edition of Homepages. There are some limitations and restrictions that applies to tenant widgets, for example the widget id must start with ‘tenant.’ and the manifest must have an author property specified. The sample “tenant.sample.angular.helloworld” is an example of a tenant widget. Once you have completed the certification process a tenant widget is deployed by first enabling the Tenant Widgets Feature in the Settings area in the Homepages Administration tool. After that feature is enabled there will be a new section called Tenant Widgets under the Widgets section. Note that only approved and signed packages from Infor can be uploaded. Tenant widgets disclaimer The web technologies are evolving in a rapid pace. It is not guaranteed that a developed widget will continue to work for an unlimited time. Angular and other dependencies that are used by the Homepages application continue to be developed and improved and as such they might introduce breaking changes that are out of our control. For major upgrades we’ll publish a notice that a transition is coming but it is important to know that if you develop tenant widgets then you have an obligation to keep up with the technology that Homepages is using and possibly do code changes to the widget that needs to go through the certification process again. There is therefore no guarantee that a widget will continue to work forever. There might be changes required on a yearly basis. 20 | Widget SDK Developers Guide Widgets Widget manifest The widget manifest is used to define a widget and each widget must have a manifest with all mandatory properties set. The manifest is a JSON file called “widget.manifest” that should be placed in the root widget folder. The data in the manifest is used to create an inline widget or address an external widget. The manifest also contains the information about the widget that is displayed in the widget catalog. Mandatory manifest properties The following manifest properties are mandatory and must be included in each widget manifest. Note that some of these properties are only mandatory for specific widget types, which is noted in the property descriptions. Widget ID The unique widget identifier. The ID must be unique among all widgets and should be chosen carefully. The ID should be like a package/namespace with lowercase words separated by dots. Include abbreviated product suites and product names in the ID to make it unique. For widgets developed by partners and customers the widget ID must start with the “tenant.” Prefix. This applies to tenant widgets that are installed in the cloud version of Homepages. Property name: widgetId Max length: 64 Example: "widgetId": "infor.sample.helloworld" Example: "widgetId": "infor.mingle.actions" Type The type of widget. The only supported types are inline and external. A hybrid widget should be defined as inline. Property name: type Valid values: inline | external Example: "type": "inline" Widget SDK Developers Guide | 21 Widgets Version The widget version number. The version number should consist of a minimum of two and a maximum of four positive integers separated by dots. The widget version is mainly intended as a technical version number for resolving compatibility with application versions. As long as a widget is backwards compatible there is no actual need to change the version number and it could remain as “1.0”. If you want to include build numbers of other release information you can use the optional displayVersion property, see the Optional manifest properties section. Property name: version Max length: 32 Example: "version": "1.0.0.0" Name The name of the widget. This name will never be visible for an end user and is mainly intended administration purposes. If you are not sure what name to pick use the localized widget title in English. Property name: name Max length: 64 Example: "name": "Hello World" Title, Description vs Localization Either Title and Description OR a Localization block with "en-US" and "widgetTitle" and "widgetDescription" is mandatory. If the widget is Localized in different languages it must have a Localization property with at least enUS with widgetTitle and widgetDescription set. If the widget is not going to be translated (applies to customer and partner developed widgets only) then the manifest must have the Title and Description property on the Manifest set. It is recommended to set the Name and Title to the same value (in English). For non-localized widgets it means that they will have Name, Title and Description set and all those are Mandatory. But Title and Description is not mandatory if Localization is used. Module name The name of the widget AMD module used to load the widget with SystemJS. This property is only mandatory if the widget type is inline. This property should be omitted for external widgets. The module name does not have to be unique. If necessary, it will be updated to a unique name during the mandatory minification step by the included bundle & minification script (See Pack and 22 | Widget SDK Developers Guide Widgets optimize script). The module name should match the name of a JavaScript file in the widget folder, excluding the .js file extension. The example below assumes that there is a file called widget.js in the root of the widget folder. Property name: moduleName Example: "moduleName": "widget" URL The URL or URL template for an external widget. This property is only mandatory if the widget type is external. This property should be omitted for inline widgets. A URL template may contain replacement variables that will be resolved using Ming.le application settings, Homepage properties and Widget settings. More information about this can be found in chapter Resolved widget values. The API documentation for the resolveAndReplace function in IWidgetContext also contains more information about URL template syntax. Property name: url Example: "url": "https://server/path" Example: "url": "{scheme}://{hostname}:{port}/{context}" Framework The client framework that the widget is using. Valid values are "angular", "jquery" or "angularjs" (during the transition period). This property is only mandatory if the widget type is inline. During a transition period to Angular it is ok to have this value blank, which will be defaulted to "angularjs". This is to avoid breaking existing widgets. As we move to Framework SDK 2.0, angularjs will not be an allowed value and those widgets will stop to work. When Framework SDK 2.0 is out the new default will be "angular". This property should be considered a mandatory property and as you deliver or update widgets this property should be set in the manifest. Property name: framework Example: "framework": "angular" Example: "framework": "jquery" Widget SDK Developers Guide | 23 Widgets Author The author of the widget. Note that this is only required for widgets developed by customers and partners, so called “tenant widgets”. Infor standard widgets should not have this property set. Property name: author Example: "author": "Sample Corporation" Optional manifest properties The following manifest properties are optional. Display version The widget display version. If this property is set the value will be displayed in the UI instead of the version property. The purpose of the display version is to allow additional information such as build numbers and other release information. Since the display version has no technical function it is not restricted to just integer and dot characters as the version property is. Note that the version property is still mandatory even if the displayVersion property is used. The display version can be automatically set by the homepage pack command setting by passing the script the extra parameter: node homepages pack “infor.sample.helloworld” --addDisplayVersion=true It is highly recommended to also include the version value in the display version. All standard Homepages widgets, for example, use the following display version format which starts with the technical widget version followed by the build date and time:. - Property name: displayVersion Max length: 32 Example: "displayVersion": " 1.0.20170316-154339" AOT version Set this property to an empty string for Angular widgets to enable AOT compilation and bundle using the homepages command script. This property will be automatically set by the homepages packaging script, using the Angular version used in the Homepages SDK, if the property exists in the manifest. 24 | Widget SDK Developers Guide Widgets Property name: aotVersion Example: "aotVersion": "" Example after package: "aotVersion": "6" Localization Localized language constants for the widget. The localization object should contain one property for each supported language. Standard widgets delivered by Infor should be localized. Perhaps the first version is not fully localized, but the goal should be to support all languages that are supported by the application the widget corresponds to. The languages that Homepages supports are: af-ZA Afrikaans - South Africa ar-SA Arabic - Saudi Arabia bg-BG Bulgarian - Bulgaria cs-CZ Czech - Czech Republic da-DK Danish - Denmark de-DE German - Germany el-GR Greek - Greece En-GB English - UK en-US English - United States es-AR Spanish - Argentina es-ES Spanish - Spain et-EE Estonian - Estonia fi-FI Finnish - Finland fr-CA French - Canada Widget SDK Developers Guide | 25 Widgets fr-FR French - France he-IL Hebrew - Israel hi-IN Hindi - India hu-HU Hungarian - Hungary it-IT Italian - Italy ja-JP Japanese - Japan ko-KR Korean - Korea lt-LT Lithuanian - Lithuania lv-LV Latvian - Latvia nb-NO Norwegian (Bokmål) Norway nl-NL Dutch - The Netherlands pl-PL Polish - Poland pt-BR Portuguese - Brazil pt-PT Portuguese - Portugal ro-RO Romanian - Romania ru-RU Russian - Russia sk-SK Slovakian - Slovakia sl-SI Slovenian - Slovenia sv-SE Swedish - Sweden th-TH Thai - Thailand tr-TR Turkish - Turkey uk-UA Ukrainian - Ukraine vi-VN Vietnamese - Vietnam zh-CN Chinese - China zh-TW Chinese - Taiwan 26 | Widget SDK Developers Guide Widgets Each language must contain a widget title and description property named widgetTitle and widgetDescription. These texts will be visible in the Widget Catalog. The title will also be used as the default widget title if this is not overridden in the widget implementation. It is recommended to have the same title and name (in English). If the widget is not translated to other languages, then there should be no localization property. The title and description should be set in the manifest instead. This means that the manifest in that case should have name, title and description. A widget may include additional localized language constants that will be available in runtime through the widget context. Labels for metadata settings may also be localized using this section. Property name: localization Example: "localization": { "en-US": { "widgetTitle": "Hello World", "widgetDescription": "Hello World Sample Widget." } } A few framework shared language constants will always be available through the widget context, without having to include them in the manifest localization. These are: “ok”, “cancel”, “yes”, “no”, “refresh”, “add” and “save”. Category An optional category that the widget belongs to. If a category is not specified, the widget will always be visible in the “All” category in the Widget Catalog. A widget that do not specify a category might also be assigned to a default category. The following categories are currently available: - application - businessintelligence - businessprocess - social - utilities - statisticsusage (since 12.0.10) Property name: category Example: "category": "application" Widget SDK Developers Guide | 27 Widgets Application logical ID An optional parameter, but if the widget is dependent on a specific application this property must be set. The value is the Logical Id prefix for the application the widget is dependent on. By specifying this, the widget will have access to the Application configuration in Ming.le for the specified application and the widget will only be available to those tenants that has the application. Property name: applicationLogicalId Example: "applicationLogicalId": "lid://infor.m3" Application version An optional parameter for the version of the related Application. This parameter should only be set if ApplicationLogicalId is set, and this is the minimum version of the application that the widget is valid for. If the widget is valid for all available versions the ApplicationVersion can be omitted, but when changes are introduced in the application that affects the widget, a new version of the widget can be created with a specified Application Version in the manifest. Property name: applicationVersion Example: "applicationVersion": "13.4" Shared modules On optional parameter for adding a shared JavaScript file with application logic. The shared module can be used by several widgets and will only be loaded once by the Framework. The value of this property is a list of SharedModule Entries that each has a name and a path. The path is optional but can be used to specify a different path (including name) of the actual JavaScript module being used. The name must be unique, and the included files should be minified. Property name: sharedModules Example: "sharedModules": [ { "name": "m3-common", "path": "m3-common-core/m3-common" } ] In this example, the module will be registered as “m3-common”, using JavaScript module “m3common-core/m3-common.js” NOTE! It is not allowed to include any JavaScript framework such as React, Immutable or any other JavaScript framework. Only shared application functions are permitted. 28 | Widget SDK Developers Guide Widgets Help URL An optional URL to documentation. If specified, a link to the documentation will be shown. The link supports replacement for application related widgets. Property name: helpUrl Examples: "helpUrl": " https://docs.infor.com/mingle/11.1ce/index.html" "helpUrl": "{Scheme}://{Hostname}:{Port}/{TenantId}/MyApp/Help" Settings The settings property can be used to define a list of settings metadata used for the metadata settings UI. Inline widgets may also specify settings in runtime and in this case this property is optional. An inline widget may even use a mix where some settings are specified in the manifest and some are added or modified in runtime. An external widget must specify settings in the manifest to be able to use the metadata settings UI. The settings metadata is also as part of the publish process where it is possible to enable specific settings in the Edit Publish Configuration dialog, so that one or more of the settings can be changed by the user on a published widget (but only for that user). It is also possible to completely disable all settings or a specific setting as user settings for a published widget. In which case, the setting would not be available in the Edit Publish Configuration dialog at all. The widgets that implement custom settings UI can still provide metadata if it makes sense to have some of the settings as user settings for published content. But it also means that the widget must check the current publish configuration when showing the settings UI to know what fields should be enabled, visible etc. A setting typically has a name, type, default value and a label. The settings property should contain an array of settings metadata objects where the following properties are supported. - name o - - type o The setting type, one of boolean, object, number, radio, selector or string o The default value is “string” o Note that the object type is not supported in the metadata settings UI, it requires a custom settings UI. defaultValue o - The name of the setting. Optional default value. labelId Widget SDK Developers Guide | 29 Widgets o - isHidden o - Indicates that the setting should be permanently hidden. The default value if false. maxLength o - A language constant ID for the setting label. The labelId should be defined in the localization property. The maximum length for a text input field. values o An array of value objects used if the type is selector or radio. Each object may contain the following properties. Use either the text or the textId property, not both. ▪ ▪ ▪ value • The item value. • The item text. text textId • - isEnabledWhenPublished o - A language constant for the item text. Indicates that the setting should not be configurable as a user setting when published. The default value is true. isMandatory o Indicates that the setting is mandatory. This property only applies to a setting with type selector or string. The default value is false. Default size The default size of a widget can be specified in the manifest using a property called defaultSize. If a default size is specified it will be used when adding the widget from the Widget Catalog. The property can be used to specify the number of columns or the number of columns and rows separated by comma. Column values can range from 1 - 4 and row values from 1 - 2. The default value is "1,1" and there is no need to use the property if this is the desired size. Property name: defaultSize Examples: "defaultSize": "defaultSize": "defaultSize": "defaultSize": "2" "2,2" "1,2" "4,2" 30 | Widget SDK Developers Guide Widgets Max size The max size of a widget can be specified in the manifest using a property called maxSize. If a max size is specified it will replace the default max size of 4,2 (four columns and two rows). The property can be used to specify the number of columns or the number of columns and rows separated by comma. Column values can range from 1 - 4 and row values from 1 - 2. The default value is "4,2" and there is no need to use the property if this is the desired size. It’s not allowed to set a value higher than this default value. Property name: maxSize Examples: "maxSize": "1" "maxSize": "2,2" "maxSize": "1,2" Enable publish A widget may set the enablePublish property to false to prevent the widget from being published. The default value is true. Publish must only be turned off if there are no widget specific settings. Property name: enablePublish Example: "enablePublish": false Enable settings when published A widget may set the enableSettingsWhenPublished property to false to disable user settings for the widget when published. The default value is true. The setting should be set to false if no widget specific user settings are applicable for a published widget. Property name: enableSettingsWhenPublished Example: "enableSettingsWhenPublished": false Enable title edit A widget may set the enableTitleEdit property to false to prevent the title from being available in Widget Settings. If enableTitleEdit is not specified it defaults to true and it is possible to change the widget title on a page. Property name: enableTitleEdit Example: "enableTitleEdit": false Widget SDK Developers Guide | 31 Widgets Enable settings A widget will have settings if it has settings defined in the definition or if it implements functions for generating metadata (see IWidgetSettings in the API Documentation). EnableSettings is defaulted to true but can be set to false, which means that no settings will be allowed. This means that the widget title can't be changed. To hide the Settings menu on the widget (called Configuration) but still have the framework support for settings see IWidgetSettings.enableSettingsMenu in the API Documentation. If the value for EnableSettings is false, the framework will return an exception if the application tries to trigger save. Property name: enableSettings Example: "enableSettings": false Enable application selector A widget with an application dependency (applicationLogicalId) combined with Settings section in the manifest will have an automatic generated UI. If there are multiple applications in Mingle for the local id prefix, a dropdown with the available applications is shown in the automatically generated UI. This is for selecting what application instance the widget is for. The ION API only supports one instance (root) or the widget needs to support selecting the context root for the ION API call. If the widget has an automatic UI but doesn’t need to configure the specific application instance it can hide the application selector by setting enableApplicationSelector to false. Property name: enableApplicationSelector Example: "enableApplicationSelector": false Enable catalog Setting the enableCatalog property to false means that the standard widget will not be displayed in the widget catalog. The default value is true. Such a widget can only be added by manually editing a JSON for a page, or by using a drillback to Homepages with widget configuration data that will add a configured widget directly to a private page. A standard widget with enableCatalog set to false can create published widgets that are added to the Widget Catalog. The configuration only applies to the standard widget. Property name: enableCatalog Example: "enableCatalog": false Enable custom properties Setting the enableCustomProperties property to true will allow the widget to resolve any value set as Ming.le custom properties. The default value is false. Only applies to widgets that has 32 | Widget SDK Developers Guide Widgets ApplicationLogicalId. These are extra custom properties that are sent to the Ming.le application as URL parameters when launching a parameter. Once enabled these properties are available using the IWidgetContext.resolve method or directly in URL templates in external widgets. To be sure the value is resolved against the Application and not any of the other sources the "application." prefix can be used in templates. Property name: enableCustomProperties Example: "enableCustomProperties": false Enable refresh The enableRefresh property can be used to get automatic refresh support for external widgets and partial refresh support for inline widgets. When this property is enabled for an external widget a refresh menu item will be added to the widget menu and a refresh button will be added to the widget title bar. When the user activates refresh the URL of the IFrame for the external widget will be reloaded. When this property is enabled for an inline widget the menu item and button will also be added but the widget must manually implement the refresh functionality by using the “refreshed” event function in the widget instance, see the IWidgetInstance interface. Inline widgets that already has a primary action button in the title bar will only get the refresh menu item. The refresh functionality can also be controlled for each widget instance by adding a widget setting with the same name as the manifest property, enableRefresh. If the manifest property is set to true and the widget setting is set to false it will override the manifest property and disable the refresh functionality by removing the menu item and the button. The enableRefresh widget setting will not have any effect if the manifest property is set to false, or not set at all. There is also a cooldown interval for the refresh functionality to prevent the user from spamming refresh requests. The cooldown interval cannot be controlled by the widget. Property name: enableRefresh Default value: false Example: " enableRefresh ": true Icon file A widget may include a custom icon that is shown in the Widget Catalog. By default, the icon in the widget catalog is determined by the category. The iconFile property should be set to the name of the icon file, including path if the file is not placed in the root of the widget package. The file must be a 60 px * 60 px PNG file following the Xi look and feel. It is recommended to call the file icon.png and place it in the root of the widget package. Widget SDK Developers Guide | 33 Widgets Please note that leading slashes such as "/images/icon.png" are not allowed. For sub paths use "images/icon.png". Property name: iconFile Example: "iconFile": "icon.png" Screen shots for the widget catalog A widget may include up to three png image files that will be shown in the details panel in the Widget Catalog. The image will be displayed in a 200 x 200 pixels container and if the image is clicked the image is shown in its original size. The max file size is 100 kb even though we recommend keeping the file size around 10 kb. The max pixel size is 740 * 760 pixels which represents a two column, two rows widget size. The min pixel size is 200 * 200 pixels. The manifest property should be set to the number of image files and the image files must be called screenshot1.png, screenshot2.png, screenshot3.png. Example: "screenshots": 2 The example widget has two screen shots screenshot2.png and screenshot3.png. Setting the value to 0 is not allowed. If there are no screenshots, then remove the property. Requires config Optional property requiresConfig can be used to specify if the widget needs to be configured before it can be used. If set to true, the widget content will be hidden until it has been configured and replaced by a button which opens the Configure Widget dialog. If the user is not allowed to configure the widget, it will be empty. If set to true, the widget configuration will be validated when the widget is loaded, reset to default or when settings are saved when closing the Configure Widget dialog. By default, this validation will be performed by the Framework, and the configuration will be interpreted as valid if at least one of the settings has an assigned value. If a custom validation is required, a widget may implement the IWidgetInstance.isConfigured function instead, please refer to the API Documentation for more information about this. When the widget has been configured according to the validation, the overlay UI will be removed, and the widget content will display. To specify a specific icon and message instead of the default UI. Please see the “Empty Config” manifest property. Note: requiresConfig shall never be set to true if the widget does not use settings, or if neither metadata settings UI nor custom settings UI are used. Property name: requiresConfig 34 | Widget SDK Developers Guide Widgets Example: " requiresConfig ": true Empty config A widget that requires configuration, i.e. requiresConfig is set to true, can specify an icon, title, description and action button by configuring the property emptyConfig. The properties that are configurable are “icon”, “titleId”, “descriptionId” and “buttonId”. All four properties are optional and type string. The icons that are available to use in the configuration, defined on the IDS Enterprise site, are the following : “generic”, “error-loading” (default), “new-project”, “no-alerts”, “noanalytics”, “no-budget”, “no-data”, “no-events”, “no-notes”, “no-orders”, “no-tasks”. To invoke the action button functionality the optional IWidgetInstance function emptyConfigClicked() should be implemented. See API documentation for more information. An example widget for the empty config state is available as infor.sample.angular.emptystate in the Widget SDK. The example widget uses the same property values as defined below. Property name: emptyConfig Example: “emptyConfig”: { “icon”: “no-budget”, “titleId”: “emptyStateTitle”, “descriptionId”: “emptyStateDescription”, “buttonId”: “emptyStateButton” } where “emptyStateTitle”, “emptyStateDescription” and “emptyStateButton” are localization constants. See Chapter 7 on Localization for more information on localization constants. The default UI for an empty widget, i.e. if requiresConfig is set to true but no emptyConfig is set, will consist of the default icon “error-loading”, button text “Configure Widget” and no title or description. Target The optional property target is used to define the widget as a Banner widget. To make the widget a Banner widget - set target to "banner". To make the widget a Mobile widget – set target to “mobile”. If the parameter is skipped the widget will become a regular widget. This property can only be used when there is only one target. Property name: target Widget SDK Developers Guide | 35 Widgets Example (banner only): "target": "banner" Example (mobile only): "target": "mobile" Targets This optional property is used to define the supported targets for the widget. If the widget is possible to add both as a regular widget and a banner widget, both targets are specified. It is also possible to include mobile in the targets. Property name: targets Example (banner widget example that can also be added as a regular widget): "targets": ["banner", "default"] Example (mobile widget example that can also be added as a regular widget): "targets": ["mobile", "default"] Example (mobile widget only, not available as a regular widget (except for admins that will still see the mobile widget): "targets": ["mobile"] Banner widget A Banner widget is a special widget that is added to the banner container. The banner container is located at the top of the page directly below the page header, and always spans the entire first row. It holds between one and four banner widgets and has a background color based on the color of the page (default is blue). When developing a Banner widget, it is important to make sure that it works with all colored background (blue, turquoise, purple, green, orange, grey and black) and that it responds well to different widths, since its size will depend on the user’s screen (or browser) width. A Banner widget is created by setting the target or targets property in the manifest. Mobile widget A Mobile widget is a widget that is built for the Infor Go mobile application for Android and IOS. When running on a mobile device the widget can access native device features like GPS information and camera. Infor Go is a mobile application that hosts different Infor applications suites for example HCM and Homepages. It acts like Ming.le for Mobile and allows easy access to your most used functions and 36 | Widget SDK Developers Guide Widgets options to add favorites for easy access to widgets, homepages and other screens in Infor applications. The Infor Go mobile application has support for viewing the Homepages pages and for viewing an individual widget in a stand-alone mode, giving maximum screen estate to the content view of the widget, a “widget only view”. In the “widget only view” the title bar of the widget is not displayed, only the widget content. This is a great view for building a mobile application through the Homepages framework. The widget can be added as a favorite in the mobile application for easy access. There are two options to specify the targets that the widget supports in the manifest. There is a target and a targets property. The targets for the default mode that is implicit if no target is defined is “default”. To add support for Infor Go and mobile, use the target “mobile”. Once a widget has support for mobile an extra option will be available when the configuration of a standard widget is published to a published widget. The option that will appear in the Publish Configuration dialog is “Enable for mobile devices”. Checking this check box means that the published widget will be available in the widget menu in Infor Go. Enabling content for Infor Go To enable pages and widgets in Infor Go there are two settings in the Homepages administration tool that needs to be enabled. • “View and Publish widgets for Infor Go” • “View pages in Infor Go” These settings will enable widgets and pages in Infor Go, respectively. It’s not supported to add more pages from the Widget catalog. Only the user’s current pages will be displayed if the pages are enabled in Infor Go setting is enabled. If the Infor Go application does not show any content, please verify that these settings are enabled and that the user have pages in My Pages / added pages when accessing Homepages in Ming.le. Enabling a widget for Infor Go In the manifest, if you have entered a value for the target property, remove that property and use targets instead. In the targets property add “mobile”. Example (mobile widget example that can also be added as a regular widget): "targets": ["mobile", "default"] If the standard widget requires configuration before it can load data you must add requiresConfig=true to the manifest. Widget SDK Developers Guide | 37 Widgets Widget menu in Infor Go The Homepages menu in Infor Go has a quick list of widgets that supports mobile devices. These are a combination of: • Standard widgets that have the target mobile and requiresConfig=false in the manifest. • Published variants of mobile standard widgets with the option: ”Enable for mobile devices enabled”. The standard widgets that requires configuration are filtered out from the list since it’s not supported to edit configuration of a widget in the mobile application. The mobile support is focused on viewing and using pages and widgets, not on their configuration. Developing for mobile When developing for mobile the development container does not support the IDevice interface which means that it will be complicated to fully test in a device unless it’s possible to deploy this in an onprem environment. If your widget support both default and mobile use the IDevice to check in which device the widget is currently running to enable different features. Always launch links and drillbacks through the IWidgetContext.launch, it will automatically open a new browser on a mobile device. For information on how to use the IDevice please see the infor.sample.mobile. Limitations There are several limitations to the Infor Go view of the widget to consider. The limitations are: • The widget is not allowed to be configured when running in mobile. • The screen resolution is different depending on mobile device so a responsive user interface is extremely important • The widget title bar is not available, nor the configure menu so any actions needs to be made available through the content area on the widget. If a widget supports both default and mobile, then it needs to be able to adapt to showing for example the primary action in the title bar when in normal mode. Accessing native features The access to the native functions is available through the IDevice available from IWidgetContext.getDevice(). The IDevice interface contains and API for accessing the following native services: • Location 38 | Widget SDK Developers Guide Widgets • Image • Video • Audio • Motion Sensors • Network • Read QR Code • Show map Inline widget implementation This section describes the basic steps required when implementing an inline widget. Refer to the sample widgets for code examples. For jQuery widgets refer to chapter 4 and for Angular widgets refer to chapter 5 for more details. Widget module An inline widget should be implemented as a module on a supported format that can be loaded using the module loader. The supported module formats are UMD and AMD. It is not allowed to explicitly use the module loader to load additional code. The widget module must export a widget factory function, see next section. Widget factory function The widget factory function is responsible for creating a widget instance. The widget factory function should be called “widgetFactory” and it should be exported from the widget module. The factory function must have the following signature which is also documented in the IWidgetModule2 interface. widgetFactory(context: IWidgetContext): IWidgetInstance; The widget factory function should return a widget instance object if it succeeds in creating the widget. If the widget cannot be created the function may return null, undefined or throw an exception. Widget SDK Developers Guide | 39 Widgets For examples and more details see chapter 4 for jQuery widgets and chapter 5 for Angular widgets. The widget context and widget instance are described in the following sections. Widget context The widget context is provided by the framework to the widget factory function for each widget that is instantiated. The context is specific to each widget instance and not shared. The context contains, among other things, the widget data, widget settings, the DOM element and various functions for interacting with the framework. See the IWidgetContext interface in the API documentation for more information. Widget instance The widget instance represents the runtime widget. Its main purpose is to let the framework notify the widget of different events such as when a widget is activated or deactivated, when settings are saved etc. All functions and properties defined in the IWidgetInstance interface are optional, so a widget factory function may return an empty object if none of the callbacks are used for example. See the IWidgetInstance interface in the API documentation for more information. For examples and more details see chapter 4 for jQuery widgets and chapter 5 for Angular widgets. Widget state A widget can have different states but using the widget state is optional. The different widget states are defined in the WidgetState class. The default widget state is “running”. The getState and setState functions on the widget context (IWidgetContext) can be used to check and set the widget state. A widget may set the state to “busy” when it is busy making a server request for example. When the widget is no longer busy it should set the state back to “running”. The framework may show busy indicator for widgets in the busy state. A widget may also set the state to “error” if it is missing settings or if backend service is not responding for example. If the issue is resolved the widget should set the state back to “running”. The framework may show some kind error indicator for widgets in the error state. 40 | Widget SDK Developers Guide Widgets Widget activation A widget can be activated or deactivated by the framework for different reasons, such as a change in visibility when user navigates to a new page. A widget is notified about activations through the activated and deactivated event functions on the widget instance (IWidgetInstance). The different types of activations are defined in the WidgetActivationType class. A widget that makes polling requests to a backend service or does any kind of periodic processing must handle activation. Widgets that do not use polling and don’t have any other periodic processing may choose to ignore activation notifications. A common scenario, as mentioned above, is a change in visibility. If a user navigates from one page to another all widgets that has defined the deactivated function would get a call with an activation object where the type is set to visibility. All widgets on the next page would get a similar call but on the activated function. Another example is when the settings dialog is opened and closed in which case the widget will also be deactivated and activated. When a widget is deactivated it should no longer make any server requests or do any other kind of processing. When a widget is activated again it may resume any suspended operations. The main reason for this is to prevent unnecessary load on both the client, network and backend servers when the user cannot see or interact with the widget content. Identifiers for automated UI (E2E) tests A widget cannot have any HTML id-attributes, except in a custom settings UI, since several widgets can be added to a page, making their IDs non-unique. If you want to add identifiers for the sole purpose of facilitating automated UI testing, add the following data attribute to elements: data-lm-tst-{applicationShortName}=”my-identifier” Example Widget SDK Developers Guide | 41 Widgets Widget settings A widget may have settings, but it is not required. If a widget has settings, it may use a metadata driven settings UI managed by the framework or use a custom settings UI implemented by the widget. Note that a custom settings UI is only supported for inline widgets. The widget settings are opened when the user clicks the Configure menu item in the widget menu. When the metadata settings UI is used, it is the framework that opens the settings dialog. When the custom settings UI is used, it might be the framework or the widget that opens the settings dialog. Please note that the settings data size should be kept to a minimum. It should basically be key-value pairs. There is a max size limitation per page that will prevent the user from saving the page if the widgets are storing too much data. If the settings UI depends on a lot of data, consider storing it in the browser local storage. Settings for a published widget A published widget or a widget on a published page will in most cases be configured in a way that affects settings. The default for a published widget is to disable settings completely. In this case, the Configure menu will not be available. For widgets that provide settings metadata it is also possible to enable/disable individual settings or show/hide individual settings. The person that publishes the widget or the page will decide which settings that should be available. For widgets that only defines settings metadata in the manifest and relies on the metadata settings UI everything is handled automatically by the framework. The metadata settings UI will disable settings that are disabled and hide settings that are hidden etc. Widgets that use a custom settings UI or that dynamically provides or modifies settings metadata must consider publish configurations made related to settings. When settings are disabled the Configure menu will not be available but if the widget exposes other ways to access settings the implementation must check if settings are disabled and act accordingly. The same is true for individual settings if metadata settings are used. The widget should check if individual settings are disabled if it creates a custom UI or if it is possible to change the setting from other places than the widget settings dialog. The IWidgetSettings2 interface contains functions for checking if settings are enabled/disabled or if individual settings are enabled/disabled or visible/hidden. Use the getSettings function in the IWidgetContext interface to get the IWidgetSettings2. User settings for a published widget Settings for a widget are normally stored as part of the page. For a published widget, things get a bit more complicated. When settings are disabled for a published widget or a widget on a published page, the settings are stored on the published widget or on the published page. If some settings are enabled a user can change those settings but these values are stored for that user only (on the page connection). This makes it possible to have a published widget with some settings that are disabled or hidden but some that are enabled and can be changed by the user. If the published widget is 42 | Widget SDK Developers Guide Widgets updated the user will receive new values for the disabled settings but the user will retain the values that were enabled. If the publisher of a widget wants to have full control of the widget settings, it is recommended to always disable settings (which is the default). In this case, all users will have received all updated settings when the widget is republished. Implicit widget settings There are some implicit widget settings such as the widget title that is handled by the framework. The framework automatically generates the UI for implicit settings when metadata settings are used. When a custom settings UI is used, it is up to the widget to support the implicit settings. If a widget with a custom settings UI wants to support editing of the title is must provide support for that in the custom UI. Note that title editing can be disabled for a published widget. This can be checked using the isTitleEditEnabled function on the IWidgetContext. External widget settings An external widget may use the metadata settings UI described below and let the framework store the settings. The widget may also handle all settings on its own. If the framework should handle the settings, the widget must define all settings in the manifest. There is no ad-hoc setting support for external widgets. The settings values can be used with replacement variables in the URL for the external widget. When the user changes the widget settings in the settings dialog the framework will reload the external widget using a URL with the new settings values. Metadata settings UI The metadata settings UI is generated automatically by the framework using settings metadata defined in the widget manifest or in runtime. The settings definitions contain the name, type, label etc for each setting. The metadata settings UI is limited to what the framework supports but the benefit is that the widget can declaratively define the settings UI and no implementation is necessary. For complex settings, the custom settings UI should be used instead. The metadata settings UI supports the following types: boolean, number, radio, selector and string. The object type is not supported in the metadata settings UI, a custom settings UI is required. Widget SDK Developers Guide | 43 Widgets Custom settings UI When the custom settings UI is used the content of the settings dialog is managed by the widget. To enable the custom settings UI the widget must set the widgetSettingsFactory function on the widget instance (IWidgetInstance). This function will be called when the settings dialog is displayed. Where to store the actual settings values is up to the widget. The custom settings values may be saved as part of the widget or using some external service. If the data should be saved as part of the widget it must be stored using the widget settings object. If the data is stored as part of the widget the save function on the widget context should be called to notify that framework that the widget settings have been changed. A widget may also choose to completely override the settings dialog. In this case the widget must handle everything related to the settings UI, including any dialogs etc. To prevent the framework from showing the settings dialog the widget must set the settingsOpening function on the IWidgetInstance and also set the cancel property to true on the function argument. The framework will call the settingsOpening function when the settings dialog is about to be displayed but if this is cancelled by the widget, no dialog will be opened. Accessing settings Settings are made available to an inline widget through the getSettings function on the widget context (IWidgetContext). External widgets will get settings on the URL if the URL is a template with settings replacement variables. When a widget is first added to the page the settings will contain default values for widgets that use metadata settings. If a widget does not define default values, do not have any settings, use ad-hoc or custom settings, the settings object might be empty. A widget should never assume that a settings value is available, and it should always check that settings values are correct before using them. The widget settings object (IWidgetSettings) defines some getter functions which have optional parameters for default values. It is also possible to use the values dictionary directly using the values property. See the API documentation for more information. Saving settings Settings are automatically saved by the framework when the metadata settings UI is used. It is possible to manually save settings using the save function on the widget context (IWidgetContext). This function should be used if the widget modifies settings internally or for widgets with a custom settings UI. Settings events The framework can notify a widget when settings are opening and when settings are saved. 44 | Widget SDK Developers Guide Widgets Settings opening The settingsOpening function on the widget instance will be called by the framework (if it is defined) when the user opens the widget settings. An object (IWidgetSettingsArg) is provided to the function with the settings metadata and values. A widget that uses the metadata settings UI and ad-hoc properties may choose to modify the settings metadata. The framework will open the settings dialog after this function returns and it will use any modified settings metadata or settings values. A widget that wants to completely override the default settings dialog should set the cancel property to true on the function argument when this function is called. Settings saved The settingsSaved function on the widget instance will be called by the framework (if it is defined) when settings are saved. An options object (IWidgetSettingsArg) is provided to the function with the settings metadata and values. Settings may be saved when the user closes the widget settings dialog or if the save function on the widget context has been called. An options object (IWidgetSettingsArg) is provided to the function with the settings values. Ad-hoc settings Ad-hoc settings can be used by inline widgets with a metadata settings UI. The ad-hoc settings metadata and values can be added or modified before the widget settings dialog is opened. The widget manifest does not need to contain any settings metadata in this scenario. A mix is also possible with some settings defined in the manifest and some ad-hoc settings defined in runtime. The settingsOpening function on the widget instance should be set so that the widget is notified when the settings dialog is opened. See the Settings events section above. Widget context values A widget context value is a value that has been resolved using a hierarchy of sources. The values can be used in URL templates or accessed from code using an API. The following three sources are supported. - Ming.le application settings o - These are only available to widgets that specify a logical ID prefix using the applicationLogicalId property in the manifest. Homepages properties Widget SDK Developers Guide | 45 Widgets o These properties are configured using the Homepages administration tool. - Widget settings - Framework values o These values must be qualified with the framework prefix Resolving priority Value are resolved with a specific priority order for each source. If a value cannot be found in the first source there is a fallback to next. The priority is Ming.le application settings, Homepage properties, Widget settings. Qualifying a value It is possible to qualify the key for a resolved value to override the default resolving priority and only check a specific source. This can be used if there is a naming conflict for the keys. If a widget specifies a setting with the same name as a Ming.le application setting the key can be prefixed to ensure that the value is retrieved from the widget settings for example. The following prefixes are supported: - application o - property o - Homepage property widget o - Ming.le application setting Widget setting framework o Framework values Example: {widget.port} 46 | Widget SDK Developers Guide Widgets Using widget context values in a URL template One scenario where context widget values can be used is in the URL template for an external widget. The keys are place within curly brackets in the template. Note that there is some special handling of the port key. If a port is not configured the port variable and the preceding colon will be removed when resolving the template. Example: {scheme}://{hostname}:{port}/{context} Accessing widget context values in code The IWidgetContext interface contains functions for resolving values. The resolve function can resolve a single value. The resolveAndReplace function can be used to manually resolve a URL template in code. Ming.le application settings The following Ming.le application settings are available for a widget that belongs to an existing Ming.le application. - version - productName - logicalIdPrefix - logicalId - hostname - context - port - useHttps Framework values The following framework values can be accessed in runtime. These values must always be qualified with the framework prefix. - pageid o The generated ID of the current page. Widget SDK Developers Guide | 47 Widgets - widgetid o - standardwidgetid o - The generated ID of the current widget. containerurl o - The standard ID of the current widget. widgetinstanceid o - The ID of the current widget. The URL of the container the hosts Homepages (usually Ming.le) or the URL to Homepages if used stand-alone or in development mode. random o A random string with 16 characters. Example: {scheme}://{hostname}:{port}/{context}/path/?pageid={framework.pageid} Using widget context values in the test container When developing a widget that uses resolved values it is possible to specify those values in a configuration file when using the test container. The file should be located in the Widgets folder. The file will only be used if the devConfiguration attribute is set. See example below:The sample solution contains an example of the configuration.json file. 48 | Widget SDK Developers Guide jQuery widgets Chapter 4 jQuery widgets 4 This chapter describes how to implement inline widgets using jQuery. Introduction The jQuery widgets introduce the least possible overhead. Widget factory function The widget factory function receives an IWidgetContext context and must return an IWidgetInstance instance. The Widget instance needs to implement at least one of the functions in the IWidgetInstance interface if TypeScript is used. This example is TypeScript and that is what we recommend as the homepage command scripts supports packaging of TypeScript files into a minified bundle file. Example: class HelloWorld implements IWidgetInstance { private root: JQuery; constructor(private widgetContext: IWidgetContext) { this.root = widgetContext.getElement(); this.root.html(" Hello jQuery world
"); } activated(arg: IWidgetActivationArg): void { } export const widgetFactory = (context: IWidgetContext): IWidgetInstance => { return new HelloWorld(context); }; Widget SDK Developers Guide | 49 jQuery widgets Performance tips Search for and apply any performance tips that are available for jQuery. For example: - Prefer simple selection first using ID first (and then by tag name) using a relative scope of the widget top element - Cache the jQuery objects as much as possible - Don’t use $.each(), use a for loop instead. - DOM manipulations should be minimized and preferably done in large chunks instead of small updates. Operations like prepend(), append() and after() are time consuming. Build a large chunk of html and use html to set the content. Creating a widget package jQuery widgets can be minified and packaged using the homepages command script. See chapter 9 for more information. 50 | Widget SDK Developers Guide Angular widgets Chapter 5 Angular widgets 5 This chapter describes how to implement inline widgets using Angular. Introduction An Angular widget is a widget implemented using the Angular framework. See the following page for documentation and general information about Angular. https://angular.io/ Refer to the widget samples for code examples of the concepts discussed in this chapter. AOT vs JIT An Angular widget can run in two different modes, JIT (Just in time) or AOT (Ahead of time). In JIT mode, the widget templates are compiled in runtime which is slow. In AOT mode, the widget templates are compiled during development to avoid the slow JIT compilation in runtime. One downside of using AOT is that the compiled factory script code (AOT factories) for the widget templates are only guaranteed to be compatible within one major Angular release. When a new major Angular version is released the AOT factories may no longer be compatible. To handle this scenario the Homepages framework supports a fallback to JIT if there are breaking changes in a newer Angular version. This will ensure that the widgets keep working but with reduced loading performance. The performance hit when using JIT depends on the size and complexity of the widget templates. When the widget templates are really small it might be OK to support JIT only, but in this case the widget could probably be implemented in jQuery instead. In most cases an Angular widget should support both JIT and AOT. The homepages command script that is part of the SDK makes it possible to build a widget package that supports both JIT and AOT. Widgets that support AOT must be verified with Homepages version 12.0.23 or later. Widget SDK Developers Guide | 51 Angular widgets AOT documentation For those who are interested in more details about AOT see the following Angular page. https://angular.io/guide/aot-compiler To avoid some pitfalls for AOT compared to JIT check the do’s and don’ts in the following page. https://github.com/rangle/angular-2-aot-sandbox#aot-dos-and-donts The future of AOT The Angular team is working on an improved AOT compiler that might be released for Angular 7. When / If Homepages switches to the new AOT compiler the widgets will need to be re-packaged to include factories for the newer version of AOT. This should not require any code changes in the widgets, but it will require compilation with the new Angular version. The future of JIT The Angular team has hinted that JIT support in runtime might be removed in favor of AOT for performance reasons. If this happens in future versions of Angular, it will be mandatory for widgets to support AOT. Angular modules and components An Angular widget must contain at least one Angular module decorated with @NgModule and one Angular component decorated with @Component. The widget may contain additional components but there must be one main widget component. The module and the main widget component are the main entry point for the widget and they must be returned by the widget factory function, see the following section. Both the module and the component classes should be exported. Module imports The widget module should import the CommonModule and any other modules that it requires such as the FormsModule. When using angular components for the Infor Design System it is recommended to import specific modules instead of the entire module. Use SohoButtonModule instead of SohoComponentsModule if you just need a button and so on. This will reduce the size of the generated factories when using AOT. 52 | Widget SDK Developers Guide Angular widgets Module declarations and entry components Add the widget components to the declarations and entryComponents arrays on the @NgModule declaration. In some cases, the widget may work without this but make sure to verify this in both JIT and AOT mode before omitting them. Widget factory function The widget factory function of an Angular widget is different compared to a jQuery widget. The widget instance that is returned from the factory function must contain a property called angularConfig that contains a configuration object specific to Angular. Angular widgets that support both JIT and AOT will have two different factory functions, one for JIT and one for AOT. The two factory functions must be placed in two different files. JIT factory function The JIT factory function should return a widget instance with the angularConfig property set. The angularConfig object should have the moduleType and componentType properties set. The moduleType is the widget Angular module class annotated with @NgModule. The componentType is the main widget component annotated with @Component. Example: export const widgetFactory = (context: IWidgetContext): IWidgetInstance => { return { angularConfig: { moduleType: MyWidgetModule, componentType: MyWidgetComponent } }; }; AOT factory function The main difference between the AOT factory function and the JIT factory function is that the AOT factory function should set the moduleFactory property instead of the moduleType. The module factory is a class generated by the AOT compiler and it will have the same name as the module class with the suffix “NgFactory”. Widget SDK Developers Guide | 53 Angular widgets The AOT factory function should return a widget instance with the angularConfig property set. The angularConfig object should have the moduleFactory and componentType properties set. The moduleFactory is the widget Angular module factory class annotated. The componentType is the main widget component annotated with @Component. Example: export const widgetFactory = (context: IWidgetContext): IWidgetInstance => { return { angularConfig: { moduleFactory: MyWidgetModuleNgFactory, componentType: MyWidgetComponent } }; }; File structure The file structure of an Angular widget project will be different depending on if the widget only supports JIT or if it supports both JIT and AOT. A JIT widget may contain a single script file while a JIT+AOT widget will contain at least three script files. A JIT widget may have the widget factory function and the widget code in the same file. An AOT widget requires one file with the common widget code and two factory files, one for JIT and one for AOT. The reason for having two factory files is to be able to package two versions of the same widget, one for JIT mode and one for AOT mode. Note that the widget factory file for AOT must be named the same as the widget module name with the suffix “-aot”. JIT widget example: widget.ts AOT widget example: main.ts widget.ts widget-aot.ts Refer to the Angular sample widgets for more details. Widget context and instance Most Angular Widget components needs access to the widget context and widget instance objects and there are two different options on how to achieve this. One option is to have the widget context 54 | Widget SDK Developers Guide Angular widgets and widget instance injected into the constructor of the component. The other option is to declare two input properties on the component. Constructor injection of widget context and instance This option is preferred if the widget needs to access either the widget context or the widget instance in the constructor. Since the widget context and instance are just interfaces it is necessary to use Angular InjectionToken objects declared in the lime module. See examples of the import statements and usage in a component constructor below. Additional examples can be found in the sample widgets. Import example: import { widgetContextInjectionToken, widgetInstanceInjectionToken, IWidgetContext, IWidgetInstance } from "lime"; Constructor example: constructor( @Inject(widgetContextInjectionToken) private readonly widgetContext: IWidgetContext, @Inject(widgetInstanceInjectionToken) private readonly widgetInstance: IWidgetInstance) { } It is recommended to always name the properties widgetContext and widgetInstance. If the properties are given different names the framework will automatically add properties with the standard names after the component has been created. This is for compatibility reasons since the injection support was added after the support for @Input properties. The IWidgetComponent interface should not be used in combination with constructor injection if the properties are declared private, which can be common in this scenario. Input properties for widget context and instance Widgets that do not need access to the widget context or widget instance in the constructor may declare two input properties that will be set by the framework after the component has been created. The properties should be named widgetContext and widgetInstance. Both properties should be annotated with @Input. The component may implement the IWidgetComponent interface where these two properties are declared. Example: export class MyComponent implements IWidgetComponent { @Input() widgetContext: IWidgetContext; @Input() widgetInstance: IWidgetInstance; Widget SDK Developers Guide | 55 Angular widgets It is important to know that the input properties will not be available in the constructor; inputs are available in the ngOnInit method. Therefore, any code that depends on the widget context or the widget instance needs to be in the ngOnInit function (or later). Consider using constructor injection if this is an issue. Templates All Angular widgets will contain at least one component template. A component template is defined in HTML. The template syntax is documented in the following page. https://angular.io/guide/template-syntax Widgets must currently use only inline template files to be able to support both JIT and AOT. External template files might be supported in future versions of the Homepages SDK. Note that all component properties and functions that are referenced from the template must be public. Private members will work in JIT, but it will break in AOT so make sure to not reference anything that is declared as private. Our recommendation is to reduce the complexity of the templates as much as possible. Use dedicated properties or functions in the widget component instead of creating complex expressions in the templates. Avoid using the safe navigation operator ( ?. ). Create objects in the constructor or use empty objects instead. The reason for these recommendations is that is reduces the size and complexity of the generated AOT factories. If a complex expression is used multiple times in a template it will be duplicated multiple times in the generated factory. It is better to create a function in the widget component that can be used from the template. Debugging is also simplified if there are no complex expressions in the templates. Refer to the Angular sample widgets for examples of component templates. Creating a widget package Angular widgets can be minified and packaged using the homepages command script. See chapter 9 for more information. 56 | Widget SDK Developers Guide External widgets Chapter 6 External widgets 6 This chapter describes how to implement the external widget type. Introduction An external widget is loaded in an IFrame using a URL that may contain parameters with values provided by the framework. The widget files may be deployed on any server that can be reached by the client. This widget type should be used with caution, especially if the external widget loads a lot of resources as it will impact the browser performance. This is not a recommended widget type. External widget implementation This section describes the basic steps required when implementing an external widget. An external widget is basically an external web page intended to be rendered in an IFrame and addressed using an URL with parameters. The URL may be absolute, but it is more likely that the URL is a template with replacement variables for server names and port numbers for the current environment. The URL parameters for the external widget may be hardcoded in the URL or they can be replacement variables for widget settings or profile settings. The replacement variables are described in section Widget context values. The framework can provide an external widget with settings through URL parameters and a metadata settings UI but there is no other interaction between an external widget and the framework. See the Widget settings section for more information about settings and the metadata settings UI. Widget SDK Developers Guide | 57 External widgets Creating a widget package Use the homepages command script to package the manifest into a zip file. It’s also possible to add an image for the widget catalog by setting the icon property in the manifest. See chapter 9 for more information. 58 | Widget SDK Developers Guide Localization Chapter 7 Localization 7 This chapter describes how to support localization of a widget. Localization Widgets can be localized using the Localization section in the manifest to specify constants and their values. The samples contain widgets that have localizations and include information on how to use the language object both in templates and in code. See for example the quicknote sample. All Infor provided widgets should be localized but as the localization cycle is a bit delayed it is possible that not all widgets are translated to all languages available in the corresponding Infor application. E.g. all M3 widgets should be translated to all the languages that M3 support. It is up to each product team to translate the constants in the manifest. If you are missing a translation or there is anything wrong with the translation, please report to support so that we can prioritize the requested languages. As a developer, you are responsible for providing a full set of constants in each language. That means that if you add a new constant in en-US, but you have a translation block in the widget manifest with other languages as well you need to add the new constants in English to each language section. There is no fallback to English within the manifest, each constant must exist in each language section. The localization block in the manifest must always have an en-US section. The overall process for the translation is as follows: 1. Add constants to the localization section in the manifest. a. Add widgetTitle and widgetDescription. b. When a new constant is added, and you already have translations in place, note that you must add the constant for all languages, with the default English text as a temporary fallback. Widget SDK Developers Guide | 59 Localization 2. Start using the Language service and object in code and in templates. 3. Extract language constants to a format that works well with translations tools or simply ask translators to update the manifest with their translations. a. For examples of localization script see below. Internally we use Node scripts to read the manifest file and then copy all constants to an .resx file which is a Microsoft XML file for translations. Please note that when dealing with localized content you need to consider an 30% increase in labels and text so please make sure to test in other languages as well. Localization scripts There are two scripts in the SDK that shows how to extract translations from widgets to resource files and vice versa. These are located in the Samples folder. LangFromManifestToResx.js This script will go through widget manifests and create a resource (.resx) file with all translations in the specified language. The output file can then be sent for translation to more languages. There are also two example resource files in Samples\Translations. Usage: node LangFromManifestToResx.js- languageCode o - pathToOutputLocation o - - Language code of translations to extract. Where the output file should be placed, relative to the script location. checkSubdirectories o If true, the script assumes that each specified folder in contains one or more widget folders. o If false, the script assumes that each folder specified in is a widget folder. widgetFolderNames o One or more paths to folders containing widget folders, or, one or more direct paths to widget folders. Example: node .\LangFromManifestToResx.js en-US .\ true .\Widgets 60 | Widget SDK Developers Guide Localization or node .\LangFromManifestToResx.js en-US .\ false .\Widgets\infor.sample.angular.helloworld .\Widgets\infor.sample.angular.example LangFromResxToManifests.js This script will go through .resx files and copy translations to the localization object of specified widgets. Usage: node .\LangFromResxToManifests.js true - baseLineResx o - File used as the baseline for translations. Should be the file that was sent for translation (usually en-US). pathToResxFiles o Path to a folder containing .resx-files. Filename should be Widgets.resx. Example: en-US-Widgets.resx - - checkSubdirectories o If true, the script assumes that each specified folder in contains one or more widget folders. o If false, the script assumes that each folder specified in is a widget folder. widgetFolderNames o One or more paths to folders containing widget folders, or, one or more direct paths to widget folders. Widget SDK Developers Guide | 61 Localization Example: node .\LangFromResxToManifests.js \Translations\en-US-Widgets.resx \Translations true \Widgets or node .\LangFromResxToManifests.js \Translations\en-US-Widgets.resx \Translations false \Widgets\infor.sample.angular.helloworld 62 | Widget SDK Developers Guide Development environment Chapter 8 Development environment 8 This chapter describes how to setup the Widget SDK development environment. Introduction The Widget SDK contains a development version of the Homepages application that can be used when developing and testing a widget. In the development environment, the Homepages application will not have access to a server and all data will be stored in the browser local storage. It is important to note that there are a lot of functions that will not be available in the development mode. The development mode supports testing one or more widgets at a time. The same widget can be added multiple times and on multiple pages. When developing inline widgets that makes server API calls the widget and server will need to support CORS or use a local proxy. If CORS is not supported, the local proxy must be replaced by making the server API calls via the ION API server to avoid cross domain calls. The Homepages application server will not act as a proxy. Prerequisites To be able to develop and test widgets you will need an editor for the source files and some kind of web server for serving the files. There are many different options depending on your preferences and the operating system used for development. This chapter will mention a couple of options but feel free to use your preferred tools. Some development tools such as Visual Studio contains all the functionality you need such as a source code editor, debugger and a built-in web server. Other tools may just have a source code Widget SDK Developers Guide | 63 Development environment editor and support for running command line tools. The minimal approach would be some kind of text editor and a Node.js web server, which is included in the SDK. Here is a list with a selection of the tools that you could use for widget development: - - - Visual Studio Code (Recommended) o Visual Studio Code is free and runs on Windows, macOS and Linux. o The SDK comes with preconfigured VS Code tasks for running the web server and TypeScript compilation in watch mode Visual Studio Professional or Enterprise o Requires a license o Minimum version is Visual Studio 2013 with update 4 Visual Studio Community o - Free version of Visual Studio with limited functionality Sublime Text + Node.js web server o Sublime Text is cross-platform source code editor The samples can be run in different ways for example using Visual Studio or using a Node.js server. To use a Node.js server follow the instruction in the Appendix on Node.js and NPM and make sure they are correctly installed before trying to run the samples. Samples The samples are in the Samples/Widgets folder. Widgets are loaded from the file structure, using the information in the widget.manifest file. Inline widgets will also contain a script file that is loaded with the current module loader. External widgets will only contain a manifest. The index.html file contains a list of different widgets contained in an lm-app Angular component. 64 | Widget SDK Developers Guide Development environment Uncomment the one you want to test and comment-out the others. Make sure there is only one lmapp on the page. You should not edit any files except for changing the dev-path that is located in the index.html file. The files will change in coming versions. Running the Samples in Visual Studio Code 1. Make sure the prerequisites described earlier in this chapter have been met. 2. Open the ./Samples/Widgets folder in VS Code. 3. Start the web server by running the build task “Start Server” (Windows: ctrl+shift+b) 4. Start TypeScript compilation in watch mode by running the build task “Typescript Watch” (Windows: ctrl+shift+b) 5. Open http://localhost:8080 in your preferred browser 6. Debug the project with F5 or run with Ctrl+F5. The Homepages application will be opened and the widget specified in index.html will be displayed. This requires the Debugger for Chrome extension for VS Code, which can be installed by navigating to the Extensions tab. Running the Samples on a Node.js server 1. Make sure the prerequisites described earlier in this chapter have been completed. 2. Open a command prompt in the Samples folder 3. In the command prompt: npm install 4. In the command prompt: node server 5. If the default port (8080) is available, the web server will be started. If the port is not available try to start the server on another port, for example: "node server 4000" 6. Open a browser and navigate to http://localhost:8080 If the server does not start check that the port is available or supply a port number. If there are other issues with the install check that NPM and Node.js is installed, according to the information in the Appendix. Widget SDK Developers Guide | 65 Development environment Creating a new widget These instructions describe how to create a new widget in the Sample project. 1. Create a widget by adding a folder with a lowercase widgetId name to the Widgets folder. Check the manifest documentation section for more information regarding naming rules. 2. In the folder create a widget.manifest and (optional) script file. a. For Angular AOT widgets create three script files: i. main.ts (suggestion name only. This file has the main widget code) ii. widget.ts (widget factory file for JIT) iii. widget-aot.ts (widget factory file for AOT) b. If creating an inline widget, make sure you implement the factory method in the script file. i. If creating an AOT Angular widget make sure to follow the factory files samples in chapter 5, Angular widgets. 3. In index.html update the active lm-app element and set the devWidget attribute to the id of your widget. 4. Run the project in Visual Studio or using Node.js and a local web server. Testing with multiple widgets It is possible to test with multiple widgets by adding multiple values separated by semi colon to the following attributes on the lm-app element: devWidget, devSettings and devCustom. Note that the devConfiguration attribute only supports a single value. When multiple attributes are used they must contain the same number of values separated by semi colon. Blank values are allowed however so you can just add a semi colon if a value is not needed for one of the widgets. The values for each attribute must be in the same order. Example with two widgets: Example with two widgets and settings for the second one only: 66 | Widget SDK Developers Guide Development environment Static code analysis with TSLint TSLint is included in the project to make it easier to avoid common mistakes and to keep a consistent code style. Most modern text editors and IDE:s can integrate with TSLint either out of the box or through extensions (See https://palantir.github.io/tslint/usage/third-party-tools/). There are two different tslint configurations in the Widgets directory: tslint.json This configuration is based on the recommended settings from the TSLint team, with some rules turned off. This one should be enough to detect many of the common mistakes that developers make, and to keep the code style consistent without being too pedantic. tslint-strict.json This configuration is used to lint all the provided samples, and we recommend that you use it for your widgets as well. It enforces some best practices in regard to keeping code maintainable and type-safe. You can configure Visual Studio Code to use this configuration by modifying the “tslint.configFile” property in the Workspace Settings file (Widgets/.vscode/settings.json). Running the linter The easiest way to lint your code is through your text editor or IDE. It can show errors and warnings next to the affected lines/symbols, and automatically fix them. Configuration depends on the editor/extension. If TSLint is not supported by your editor, you can always run it from the command line: Using the provided npm scripts (Samples/package.json): npm run lint npm run lint:strict # Lint using the standard config # Lint using the strict config Using the tslint executable (from the Widgets directory): npx tslint -c tslint-strict.json -p . # Local installation, npm>=5.2.0 tslint -c tslint-strict.json -p . # Globally installed tslint ../node_modules/tslint/bin/tslint ... # Local installation Automatically fix problems Some linting rules can be fixed automatically. It is highly recommended to configure your text editor to do this for you, since some problems can be tedious to fix manually. However, this can also be done with the CLI by adding the --fix option. Note that doing this will modify your source files. Example: tslint -c path/to/Widgets/tslint-strict.json -p path/to/Widgets –fix Widget SDK Developers Guide | 67 Development environment Modifying or overriding rules If there is some rule that contradict your preferred code standard, you can either modify the provided configuration files, or create a new configuration for your widget: Example // Widgets/my.example.widget/tslint.json { “extends”: “../tslint-strict.json”, “rules”: { “indent”: [true, “spaces”, 4], // Change a rule “max-line-length”: false // Disable a rule } } 68 | Widget SDK Developers Guide Packaging Chapter 9 Packaging 9 This chapter describes how to package a widget. The widget package can then be registered and deployed in the Ming.le Cloud Console for cloud environments or uploaded in the Administration tool for on-premise installations. Files to include A widget package should only include the files that are required in runtime. Any files that are not used in runtime such as source files or build artifacts should be excluded from the widget package. The widget packages are synchronized over networks and stored in databases and should be as small as possible. Mandatory files Which files are mandatory depends on the widget type. - Widget manifest o A widget manifest file called widget.manifest is required for all type of widgets. Widget module file o A widget module file is required for inline widgets. o Example: widget.js Optional files Optional files could be image files. Widget SDK Developers Guide | 69 Packaging File optimizations It is mandatory to optimize content by combining script files to a single file that is minified. All files that can be combined and minified should be. This will be a requirement for cloud deployed widgets. Please note that directories in the widget package is not allowed. Source code can be in directories and there can be multiple files and modules, but they need to be bundled into one file. Angular components must use inline templates. Homepages command pack script The Widget SDK includes a Node.js script that can be used to build and package all types of widgets. It will compile and bundle all TypeScript files used in the widget into a single JavaScript file (except any shared modules). The script will create named modules based on the widget ID and you can have multiple source files as modules which will be automatically bundled. Shared modules need to have the TypeScript file copied to each widget directory prior to executing the pack command. Directory rules All widgets must adhere to the following guidelines: - The widget directory must have the same name as the widget ID. Sub directories are only allowed for source code. Sub directories are not allowed for resources such as images. AOT compilation To enable AOT compilation there are three actions you need to take: 1. Add the aotVersion property with a blank value in manifest 2. Make sure widget directory rules are followed 3. Make sure there are two widget factory files created, one for AOT and one for JIT Manifest To enable AOT compilation for Angular widgets the manifest needs to contain the aotVersion property. Add the following to the manifest for Angular widgets: 70 | Widget SDK Developers Guide Packaging “aotVersion”: “” Widget factory files Be sure to have created two factory files for the widget module. One that is used for AOT and one that is used for JIT. o o o Source code in main.ts AOT factory function in widget-aot.ts JIT factory function in widget.ts Prerequisites - Ensure that you have installed Node.js o - - Can be verified with the command node -v Ensure that you have installed the node package dependencies o Change to the directory /Infor_HomepagesWidgetSDK/Samples o Execute npm install Ensure that the directory that contains the widget has the exact name as the widget ID. Pack and optimize: A widget can be minified and zipped for production by following below steps: 1. Open a command window in directory \Infor_HomepagesWidgetSDK\Samples 2. Execute command: node homepages pack “folder_name” Where “widget_id” corresponds to your widget folder. Example: node homepages “widget_id” The homepages command file has a help function that will print out the different commands and parameters that are available. Please check the help information for more information. Examples node homepages help node homepages pack "infor.sample.angular.helloworld" Widget SDK Developers Guide | 71 Packaging node homepages pack -widgets="infor.sample.angular.helloworld,infor.sample.angular.quicknote" node homepages pack --widget "Widgets/infor.sample.angular.helloworld" -outputPath "C:\Builds" node homepages pack --widget "C:\Source\Widgets\infor.sample.angular.helloworld" --outputPath "C:\Builds" –zip=false The default output location with be in a Builds directory relative to the script location unless the outputPath parameter is provided. Output The name of the zip file will include the name and version of the widget, as well as the current date and time. If the addDisplayVersion parameter is set the script will update the manifest with a displayVersion property. The output directory will contain the widget package zip, for example: infor.sample.angular.helloworld-1.0.20180323-114907.zip Shared modules Shared modules are supported like before. It is however important that the TypeScript file for the shared module is available in the same directory as the widget. It can be copied by a script prior to building the widget. Angular AOT package recommendation Make sure that the package script is run throughout development as it will discover issues related to template validation. You can also use a stricter validation by setting the fullTemplateTypeCheck parameter to true. Example: node homepages pack "Widgets/infor.sample.angular.helloworld" -fullTemplateTypeCheck=true Try to fix any issues related to the widget code. If there are remaining issues that cannot be addressed, you must build the widget package without full template type checks. There could for example be issues in one of the Infor Design System components used by the widget. 72 | Widget SDK Developers Guide Packaging Manual minification If packaging the widget using other methods than the included homepages script, a few things must be considered to ensure that the widget will work properly and not break other widgets or Framework modules. It’s recommended to use the homepages script for all builds. Single module widget If your widget only consists of one TypeScript file, i.e. there is only one module, the minification is straight-forward. If there is a single AMD module it can be anonymous, it’s not allowed to have a common name, such as “widget”, that might conflict with other modules when the widget is loaded by the Framework. A named module must be prefixed with the widgetID. The main module can have the widget ID as name and other should have it prefixed with the widgetID. Once minified, it can be packed manually together with the manifest and any additional resources. Multi-module widget If your widget consists of two or more TypeScript files (not shared modules), they must be combined into a single out-file when compiled for production. When combining several modules into one, the AMD modules in the resulting JavaScript will be named the same as the corresponding TypeScript file they originated from. For instance, the module from widget.ts will be named “widget”. Any named AMD modules must be unique, since the Framework will load the main widget module by its name in the multi-module scenario. The JavaScript modules must manually be updated to be prefixed with the widget id. And, any module importing another must update its import array to match the new name. The widget manifest “moduleName” property must be updated to reflect the new name for the main module, as well as the JavaScript file. After this, the JavaScript file can be minified and packed manually together with the manifest and any additional resources. The homepages command script supports multi module out of the box and will create UMD named modules using the folder name that must be set to the widget ID. Packaging widgets for an on-premise installation Widgets can be installed manually by a customer in an on-premise installation of Homepages. This is different compared to a cloud installation of Homepages where the widgets are automatically synchronized from the Infor Registry. The zip file for the Infor Registry is the format described in the previous section, e.g. one zip one widget. Widget SDK Developers Guide | 73 Packaging The widgets should be packaged with the homepages command script in the same way as There are two options for installing Standard widgets in an on-premise installation. Note that they use different zip formats. The widget installation package file (see below) is a zip that may contain multiple widgets and it can only be uploaded on the management pages for the Homepages server in the ION Grid. A simpler way to upload a widget is to use the new import functionality within the Homepages application itself. Open Homepages Administration and go to the Standard widgets section. There is an ‘import’ action available above the list of Standard widgets. In this tool, it is important to upload a zip that has just one widget and the widget.manifest directly in the root of the zip. Note that the zip should not have any directories. Refer to the Homepages administration guide for more information on how to import widgets in an on-premise installation. Widget installation package file There are two different installation formats for installing widgets. One is a zip file as described below. Such a file can only be installed in the Management pages for the Homepages application in the ION Grid. To upload a single widget zip file, use the Homepages Administration tool accessible from the Homepages menu within the Homepages application. A widget installation package file is simply a zip file that may contain one or more widget zip files. Even when installing a single widget, it must still be packaged into a widget installation package file. These are the basic steps for creating a widget installation package file: - Create zip files for each widget as described above (1-n) - Create a new zip file and add the widget zip files to it. Widget installation package file example: - Widgets.zip o infor.examplewidget1.zip o infor.example.widget2.zip o … o infor.example.widgetn.zip 74 | Widget SDK Developers Guide ION API Chapter 10 ION API 10 This chapter describes how call the ION APIs from an inline Homepage widget. Introduction The Widget SDK contains an API for retrieving the OAuth token that can be used when accessing the ION APIs. OAuth essentially allows access tokens to be issued to third-party clients by an authorization server, with the approval of the resource owner. The client then uses the access token to access the protected resources hosted by the resource server. ION APIs uses OAuth and before starting with Homepages development using the ION API there are some prerequisites that are required. 1. Application API deployed in ION API Server for a specific environment 2. Access to Ming.le and Homepages in that environment Retrieving OAuth access token The OAuth access token must be set as a request header. This means that all access to URL must be done in code and even if there are IDS components that takes an URL you must use another approach to be able to manually update the header before making the request. Homepages provides a consistent way to access a token that is shared among all widgets. IIonApiContext contains functions for retrieving the base URL to the ION API Server as well as the token and the header name and header. Widget SDK Developers Guide | 75 ION API Token timeout It is the responsibility of the Widget developer to handle authentication errors and retry any API call with a newly refreshed token. A new token can be requested by setting refresh to true. Note that this should only be done if the token is expired. Another important note is that you should not store the token in a variable for later use but always get it from the context. This means that if any other widget has requested a new token you will always get the latest one. Development environment There is an ION API widget sample. It shows how to connect to a M3 API but can be used as reference on how to set the required header and how to enter configuration for the ION API Base path. Please note that the example is not a complete solution but only a starting point. Prerequisites The following are the prerequisites for running the ION API sample but can be applied to any ION API usage. - Acquire the server and port number for the ION API server to test with. - Configure and start a localhost proxy with the ION API server and port number. Example: node proxy.js 8083 "server.infor.com" 443 Example: \Samples\StartIonApiProxy.cmd Acquire an OAuth token string 1. Log on to Ming.le example: https://server/tenant a. Locate the server that Homepages is running on within Ming.le. You will need to check the server and port for Homepages and apply it to the template below. Use the browser developer tools to locate the URL for the IFrame in which Homepages is running. i. Open the browser developer tools (how depends on browser) ii. Use the element inspector tool and click the top bar in Homepages. Look for an Iframe element with a context root called /lime 2. Open a new tab in the same browser and navigate to the Grid SAML Session Provider OAuth resource. 76 | Widget SDK Developers Guide ION API a. The Grid must be version 2.0 or later with a SAML Session Provider configured for the same IFS as Ming.le (these conditions are true for the Homepages Grid) Template: https://{homepagesserver}:{homepagesport}/grid/rest/security/sessions/oauth 3. Copy the OAuth token string from the browser window If there are issues you can verify if your user has access to the grid by navigating to the Grid user page. Note that you must be logged on to Ming.le before doing this. Example: https://{homepagesserver}:{homepagesport}/grid/user Set up the development configuration Set the ionApiToken property in the configuration.json file to the OAuth token string. Example: "ionApiToken": "V9k5niTDR1kq6RuYlEq3N3HxGq8u" Set the devConfiguration attribute on the lm-app to the name of the configuration.json file Example: Developing and debugging A widget using the ION API can be developed and debugged like any other widget. Just remember to start the proxy and configure the configuration.json file. The OAuth token will time out and when that happens you must acquire a new token and update the configuration.json file. The OAuth token might time out in production as well. If not using the executeIonApiAsync() API method, which handles this automatically, all API calls must be wrapped with a retry that is done after forcing a new token if a request results in a 401 HTTP response code. To force a refresh of the access token call getIonApiContextAsync with refresh set to true. Example: widgetContext.getIonApiContextAsync({refresh:true}).then(…..) Note this should only be done when a call has resulted in an unauthorized response. Widget SDK Developers Guide | 77 Homepages Widget Certification Chapter 11 Homepages Widget Certification 11 To be delivered as a standard Homepages widget the widget needs to be reviewed and certified by the User Platform / Homepages team. The reason we have a certification is that your widgets behavior may affect other widgets since it is not running in a sandboxed environment. It is also important that all recommendations in the developer’s guide have been followed. This chapter contains the certification checklist as well as a developer checklist with some things to consider when developing and testing your widget. Please note that the checklist is a short summary. Once ready for review contact Fredrik Eriksson, fredrik.eriksson@infor.com. The review process is Infor internal. Certification checklist Packaging • The manifest must be correct, e.g. unique widget id and correct information • Script files must be minified and combined into one single script file. It should be an anonymous script module or a named module with a unique name – for example the widget id. Use the homepages pack script to make sure the bundle result is correct. • Angular templates shall be inline and not result in an extra request to load them. • The widget package shall only contain a manifest, a script file and optional images. The package shall not contain map files or TypeScript files. If you have a shared JavaScript module the package may contain two script files. The total package size will also be considered. • It is not allowed to include JavaScript libraries as sharedModules. Only application logic is allowed as a shared module. Verify package • Use the lime-zipv tool to verify that the widget package zip is correct. Download the tool from GitHub, unzip and follow the read me instructions: https://github.com/infor-cloud/homepages-widget-sdk Development • The widget shall be translated to all languages that your backend application supports. • The widget shall always be backwards compatible if possible. It should never break with its previous configuration. • A widget that has settings must support publishing. o If settings are used the widget must respect the publish configuration that specifies which settings are enabled and visible etc. If you have actions available in the Widget Title bar or inline configuration that depends on settings, you need to read the API documentation carefully. o This also applies to a widget that is not published but has publish information on a published page 78 | Widget SDK Developers Guide Homepages Widget Certification o • • • • • • • • • • • • If the widget does not respect the publish configuration, user settings must be turned off when published. In that scenario, set enableSettingsWhenPublished to false in the manifest. Don’t store too much data as settings. Basically, only store key-value pairs. The page size must be kept to a minimum. There is a max size per page that will prevent the page from being saved if it is too big. Avoid polling for data updates o We don’t recommend polling. Implement the refresh action in the Widget Title bar instead. o If polling must be used, then make sure to use long intervals e.g. default interval 15 min and minimum 5 minutes. o If you implement polling, you must use the activated and deactivated event on the IWidgetInstance so that the widget isn’t requesting new data unless it is visible and active on a Page. The UI shall follow the Infor Design System guide. A widget shall be a small application that provide quick access to information or functionality. Avoid making the widget too complex, it shall not be a complete application. Don’t use global variables. Only access public documented homepages APIs. A widget is only allowed to make changes to the widget DOM element and its children. There must be no side effects affecting other parts of the DOM. Show inline messages for errors instead of showing dialogs. HTML ID attributes must include the unique widgetInstanceId from IWidgetContext. Don’t include any third-party libraries If using ::ng-deep as part of a CSS selector, it must be scoped, ex. :host ::ng-deep. Never load data that isn’t directly visible in the UI. E.g. if you have tabs with different data, only load the first tab. All data should be lazy loaded and loaded only when the data is displayed in the view. • Never use anything global. • It’s not allowed to add any JavaScript libraries. • It’s not allowed to link in CSS files as it would affect all widgets. • It’s not allowed to include