Framework Guidelines to Develop Home Widgets¶
Overview¶
IFS Home widgets are developed independently from the IFS client framework, ensuring minimal code dependencies on the core application. Widgets are organized into libraries based on their respective product areas, and each widget library can contain multiple widgets. These libraries are packaged as Node modules and published to Bitbucket, where they are then referenced as dependencies within the client framework’s package.json
file.
Although the development of widgets is separate from the client framework, the delivery of new widgets or updates to existing ones must be incorporated into a client framework release to be provided to customers. This ensures compatibility and streamlined integration within the IFS Cloud environment.
Fig 1. Technical Architecture
Widget Base Library¶
This is a base library that includes useful components, directives, and services which makes the widget development process easier. This also includes a schematic which can be used to generate new libraries without worrying about the boilerplate code and configurations.
Link | |
---|---|
Artifacts | https://bitbucket.org/ifs-pd/ifs-cloudhome-base |
Source Code | https://bitbucket.org/ifs-pd/ifs-cloudhome-base-source |
Widget Libraries¶
These libraries contain the widget artifacts that are integrated as Node packages within the IFS Cloud client framework. Each library consists of a set of widgets grouped according to defined criteria. Currently, widgets are categorized into libraries based on their associated product area. It is recommended to follow this same structure when developing new widgets to ensure consistency and ease of integration.
Example:
Product Area | Link |
---|---|
Asset Management | https://bitbucket.org/ifs-pd/ifs-cloudhome-widgets-asset |
HCM | https://bitbucket.org/ifs-pd/ifs-cloudhome-widgets-hcm |
Framework | https://bitbucket.org/ifs-pd/ifs-cloudhome-widgets-framework |
Widget Workspace¶
This is the repository where the widget-related code should be included, either in an existing widget library or in a new library. This also includes a Testground application which can be used for testing the widgets before integrating with the IFS client framework. This workspace is already configured with the Widget base library and IFS Design system packages (Granite Tokens, Granite Icons, Granite component, Granite Kendo Components).
Link | |
---|---|
Work Space | https://bitbucket.org/ifs-pd/ifs-cloudhome-workspace |
Widget development process¶
- The widget is developed in the relevant project inside the widget workspace repo (Please refer to the Getting Started With Widget Development to learn more about widget development guidelines).
-
Upon completion of development and integration of all required automated tests into your feature branch, a comprehensive code review must be conducted by the client framework development and QA teams. Once you are prepared to proceed, create a pull request to merge your changes into the master branch of the widget workspace. Please ensure to include members from the IFS Cloud client framework and representatives from your product area as reviewers. This process ensures that your contribution meets the necessary quality standards and facilitates seamless integration.
-
Once the code changes are reviewed and approved, the developer can merge the changes into the master branch of the widget workspace.
- Once the code is merged into the master branch, it will trigger the automatic publishing process (make sure to commit your code changes according to the commit message guidelines provided in the next sections, so it will trigger the semantic-release process automatically to publish the widgets into the Artifact libraries).
- If the release pipeline is successful, you can see that the artifacts are properly copied and the package version is updated in the relevant node package (widget artifact library).
- Finally, the node dependency in the client framework needs to be updated with the new version of the relevant widget library and if it involves adding a new widget, the metadata file in the client framework that includes the list of widgets needs to be updated as well.
Getting Started With Widget Development¶
Initial Steps¶
- To get started with widget development, clone the Workspace repository. Run the Testground app with the included sample widgets.
npm install
ng serve
Note : This library can be used as a reference to understand how to use base framework functionalities such as communicating with backend, navigation, configuration and handling translations, as well as to see how the IFS Design system elements including as granite components, granite icons and granite tokens can be used for widget development.
Creating a New Library / Widget¶
-
Create a new Library Project : Use the schematics provided by
@ifsworld/cloud-home-widget-base
to generate a new library project. -
Run
npm run schematics:add-widget
and follow the cli instructions.
Provide :
- Library Name
- Widget Name
-
Widget Size
and it will generate all the boilerplate code. (Refer the Widget Naming section)
Note : To add another widget to the same library, run the same command but give the existing library name when asked.
$ npm run schematics:add-widget
> ifs-cloud-home-widgets-workspace@0.0.0 schematics:add-widget
> schematics @ifsworld/cloud-home-widget-base:add-widget
? Library Name? @ifsworld/widgets-asset
? Widget ID? RecentDocumentsWidget
? Widget width? Half | Full
? Widget height? Medium | Dynamic
? Does the widget has configuration? Yes | No
Add Widgets to the Testground app¶
To add new widgets to the Testground app, add the widget selector, component and metadata to widgetMetadata object in projects\widget-testground\src\app\widget-meta\widget-metadata.ts
See how sample widgets are added and follow the same structure.
Naming Conventions¶
Library Name¶
Please use the following naming pattern when creating a new library in the workspace,
<Widget namespace>/<Widget library name prefix>-<Product area name>
- Widget namespace : Use the namespace '@ifsworld' for all widget libraries
- Widget library name prefix : Use the prefix 'widgets'
- Product area name : Name / Identifier of the product area that the widget library belongs to
Examples:
- @ifsworld/widgets-fnd
- @ifsworld/widgets-hcm
- @ifsworld/widgets-asset
Widget ID¶
Every widget must have a unique ID, so the following naming pattern must be followed when creating the ID for the widget,
<Unique widget identifier><Widget suffix (same for all widgets)>
- The first part of the widget is the unique name of the widget
- Use the common suffix "Widget" at the end of the widget ID
Examples:
- TimeReportingShortcutsWidget
- RecentDocumentsWidget
Client and Projection Files Connected to a Widget¶
In some cases, a .projection
file is used to create the data structures and data sets required to get data into the widgets. Also, a .client
file can be used to utilize marble field translations for widget translation needs (Please refer to the Translations
section for more details on enabling translations for the widgets). It is recommended to create new client and projection files for each widget to include the widget-related code.
A widget can be connected to one projection only. Through this projection, the widget can communicate with the IFS backend through Get, Post, Patch, Delete requests or odata functions and actions. If there is a connected projection in the widget metadata, projection grants are checked for the current user at IFS Application startup. The widget will be available to the user only if the projection is granted.
Projection name¶
The name of the projection file should be the same as the widget ID with the common suffix Handling
at the end to make the file consistent with the other projection files in the system in general.
Example:
- Widget ID : RecentDocumentsWidget
- Projection : RecentDocumentsWidgetHandling.projection
Client name¶
The name of the client file should be the same as the widget ID.
Example:
- Widget ID : RecentDocumentsWidget
- Projection : RecentDocumentsWidget.client
Widget Metadata¶
Widget metadata includes important metadata related to the widget.
export const RecentDocumentsWidgetMetadata: Metadata = {
id: 'RecentDocumentsWidget',
title: 'WidgetTitle', //translation key
description: 'WidgetDescription', //translation key
width: WidgetWidth.Full,
height: WidgetHeight.Dynamic,
keywords: ['test', 'widget','framework'],
projection: 'RecentDocumentsWidgetHandling',
icon: 'education',
translations: {
type: WidgetTranslationType.MarbleClientMetadata,
client: 'RecentDocumentsWidget',
list: 'TranslationsList',
defaultTranslations: translations
},
config: [
{
id: 'input-1',
type: WidgetConfigInputType.Text,
value: 'Default Name',
},
{
id: 'input-2',
type: WidgetConfigInputType.Number,
value: '37',
}
]
};
Property | Description |
---|---|
id | Unique identifier for the widget, use the guidelines shown in the previous section when defining the widget Id |
title | Property name that contains the translatable text for the widget title (in Marble client file or default translations file) |
description | Property name that contains the translatable text for the widget description (in Marble client file or default translations file) |
width | Width of the widget (Full or Half), default value is Full |
height | Height of the widget (Medium or Dynamic), default value is Dynamic |
keywords | Keywords useful to search for the widget |
projection | The Marble projection file connected with the widget that contains the data structures/sources |
translations | Used to define the details related to translations |
config | Used to define the details related to widget configurations |
Translations¶
Property | Description |
---|---|
type | Type of source for translations. Either Marble client metadata (WidgetTranslationType.MarbleClientMetadata) or JSON file in the code |
client | Marble client file name that contains the translations for the widget |
defaultTranslations | Name of the default translations JSON file inside the code structure. The recommended name is 'translations.json' |
Config¶
Property | Description |
---|---|
id | Unique identifier for the widget configuration item |
type | Configuration item type, Currently supported types are listed under WidgetConfigInputType enum. Text | TextArea | Number | Boolean | Checkbox | Radio | Dropdown | Custom |
value | Initial value for the configuration item when the widget is initialized for a user for the first time. |
Testing the widgets locally during development¶
Visual and workflow testing¶
After adding the new widget metadata into widget-metadata.ts
, initiate the Testground application by executing npm run start
. This command activates the Testground app in watch mode, allowing you to edit the widget and view template changes in real time. Additionally, you can observe visual modifications, including the widget's behavior in both Light and Dark themes, directly within the Testground application.
Utilizing the Testground App for Widget Testing¶
The Testground app incorporates base service files essential for the services provided by the IFS Client Framework upon widget integration. Within this environment, you can mock the returned values to thoroughly test your widgets. For instance, if your widget makes a call to an OData function such as GetEmployee(Id='abc')
, you can obtain and utilize the mock response within the file at \widget-testground\src\app\services\custom-widget-base-data-provider.service.ts
for effective testing.
Syncing Widget With Client Framework¶
Using Automatic Script (fastest way)¶
-
you can find this script in
ifs-cloudhome-workspace/deploy-widget.sh
-
In the client framework, set
"preserveSymlinks": true,
underarchitect > build > options
inangular.json
-
Syntax
bash deploy-widget.sh <widget-name>
Example :
bash deploy-widget.sh widgets-crm
-
To make it work you should have following project structure
-
It launches
ifs-technology-client-framework
in the end. Backend should be launched earlier.
- To learn more about - How to launch BE for your new widget : Click here.
Using npm-Link¶
When the widget is ready to be tested in the client-framework, you can use npm-link to add your library as a dependency to client framework and test it in the client framework local server. Click Here
- Build your library and change directory to
dist/your-library-name
. - npm link
- In the client framework, set
"preserveSymlinks": true,
underarchitect > build > options
inangular.json
. - From the client framework
root
, run npm link your-library-name. This will link your library dependency to client framewotk. - Add your widget metadata to
src\app\shell\cloud-home\custom-widgets\metadata\custom-widget-metadata.ts
- Start client framework dev server.
Refer Setup Your Development Environment for more information on setting up local development server in client framework.
Using The Beta Track¶
In the workspace repository (ifs-pd/ifs-cloudhome-workspace ) we are maintaining a beta track that can be used for self publishing the widget artifacts without any approvals. Refer Committing code changes and Publishing widget artifacts sections for more information on how to publish widget artifacts.
Once the widget is published in the beta track you can add the widget dependency to client framework package.json
with the correct release tag. Please see the example below.
"@ifsworld/widgets-asset": "git+ssh://git@bitbucket.org:ifs-pd/ifs-cloudhome-widgets-asset.git#release-1.0.0-beta.1",
Add the widget metadata to custom-widget-metadata.ts
and start the development server.
Using The ux-staging-dev Environment¶
Once the widget is ready to be tested in an actual IFS Cloud environment before merging to master, ux-staging-dev
environment can be used. Update the package.json
with the correct dependency, run npm
install to generate package-lock.json
, add widget metadata to custom-widget-metadata.ts
and raise a PR to ux-staging-dev
branch.
Go to : Environment link
For frontend developers - in servers.txt
you should add the following context in the config
as a first line :
IFSCLOUD UX staging dev,jdbc:oracle:thin:@//DSE1PDE847.corpnet.ifsworld.com:1521/IFSPDB,internal_ux,IFSAPP
Projection and client changes can be deployed to this back.
Go to : Server
Best Practices¶
Committing Code Changes¶
Commit Message Format¶
semantic-release uses the commit messages to determine the consumer impact of changes in the codebase. Following formalized conventions for commit messages, semantic-release automatically determines the next semantic version number, generates a changelog and publishes the release.
Use the provided commitzen configuration in the project to add new commits. It will make sure that the commits are in the correct format which helps semantic release to figure out the next release version. Use command npm run commit
Don't Use Manual Commits¶
- For a patch release use
fix
- For a minor release: use
feat
- For a major release use
feat
and add an additional comment when asked for BREAKING_CHANGE?
Publishing widget artifacts¶
The process of publishing the widget artifacts as node packages depends on whether a widget artifact library (Bitbucket repository) is already available to publish the widget into, or whether you need to create a new repository for your product area to publish the widget artifacts.
If the widget library exists, then you don’t need to do anything, in particular, to publish the widgets, committing the code with the proper commit messages above and merging the code to the master branch of the workspace repository will trigger the automated pipeline to publish the widget artifacts into the proper widget library.
If it is required to create a new widget repository to publish the widget artifacts, then follow the below guidelines to create a new repository.
Tasks :
- Create a repository in
Widget-library. Repository name should match
IFS/CloudHome/Widgets/<LibraryName>
.
Note : Reach out to project owners if you don’t have the necessary permissions.
- Add the library name in kebab case ( ifs-cloudhome-widgets-yourlib
) to publish.sh script as the TARGET_REPOSITORY
.
- Add new library to package.json
build script (build: libraries property in scripts of main package.json
)
- Add library to lerna.json
- publish.sh
should be given execute access in the pipeline
Package releases are automated after the above configurations. Semantic release (npm: semantic-release ) which utilizes the semantic versioning spec (Semantic Versioning 2.0.0 ) is used for package versioning.
Integrating with Client Framework¶
A published widget library can be integrated with client framework with the below steps.
- Add the dependency to package.json and generate package-lock.json by running npm install. Make sure the correct path is used for the Bitbucket repository which contains the artifacts and the correct package version is used after #.
"@ifsworld/widgets-asset": "git+ssh://git@bitbucket.org:ifs-pd/ifs-cloudhome-widgets-asset.git#release-1.0.0-beta.1",
- Add the widget metadata to 'src\app\shell\cloud-home\custom-widgets\metadata\custom-widget-metadata.ts'.
entryComponent
should be the entry point to the widget and if there is a widget configuration, add it as theconfigComponent
.
'RecentDocumentsWidget': {
entryComponent: RecentDocumentsWidgetComponent,
configComponent: RecentDocumentsWidgetConfigurationComponent,
metadata: RecentDocumentsWidgetMetadata
},
Code Style¶
For better code style configure IDE to auto fix line indentation.
- In VSCode ctrl + , (comma)
- Select User tab which is next to workspace (Selected by default)
- Search
auto actions on save
and in first result clickEdit in settings.json
- Add this to your file:
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
- Your code will be far more readable
Troubleshooting:¶
-
When upgrading package versions, make sure the
resolved
commit hash is updated inpackage-lock.json
. recommended best practice is to uninstall the old package first and then install the new package. -
If you are not seeing your new changes locally, try clearing
node_modules
and angular cache.
Note : Deleting node_modules
is lengthy process and sometimes you might not be able to do it straight away, therefore you can consider removing node_modules/@ifsworld
.