Creation of UI package "from scratch"

Prerequisites: Before getting started, make sure you have installed nodejs and @angular/cli

This instruction is for informational purposes only and aims to provide a better understanding of the principles of package development.

This guide provides information on building a basic plugin for the mef.dev technical preview platform. The basic plugin does not contain any business logic implementation. Its purpose is to provide the necessary structure for a plugin to work within the platform.

Note: Tested with the following versions of @angular/cli: 12.2.17, 13.3.8, 14.2.11, 15.2.8, 16.2.0

1. Creation Angular project

Create a standard Angular application using the Angular CLI:

 ng new <app-name>

Note: You need to enable routing during project creation or add routing manually later.

2. Adding dependencies

@natec/mef-dev-platform-connector

To work on the platform, you need to use @natec/mef-dev-platform-connector, which provides essential functionality. Install the package using:

npm i @natec/mef-dev-platform-connector

Note. Important:Make sure the installed version of mef-dev-platform-connector matches the version of Angular on your computer (you can check it by running the ng v command). You can find the version compatibility table here.

ngx-build-plus

To build the plugin, we use the resources provided by ngx-build-plus.

ng add ngx-build-plus

Note. The version of ngx-build-plus should also match the installed version of Angular. You can refer to the version compatibility table below

Angular / CLI ngx-build-plus
12 /12 ngx-build-plus@^12.0.0
13 /13 ngx-build-plus@^13.0.0
14 /14 ngx-build-plus@^14.0.0
15 /15 ngx-build-plus@^15.0.0
16 /16 ngx-build-plus@^16.0.0

3. Changing the base selector

When generating a project using @angular/cli, a base component AppComponent is generated with the selector app-root. We need to replace it with the selector of our plugin. This parameter is reserved within the platform when creating a plugin and is named FrontendPluginName. To make the change, follow these steps:

// src/app/app.component.ts
...
@Component({
selector:  'plugin-example', // 'app-root',
template:  '<router-outlet></router-outlet>', // <-- also replace standard content
styleUrls: ['./app.component.scss']
...
})
// src/index.html
...
<body>
    <plugin-example></plugin-example>  <!-- <app-root></app-root> -->
</body>
...

When using CLI publish, it's important to update the name property in the package.json file to match the desired project name. Additionally, you should verify that the project name is correctly configured in the angular.json file. By ensuring consistency between the project name specified in the package.json file and the configuration in the angular.json file, you can avoid potential issues during the publishing process.

4. Routing changes

For proper routing functionality within the plugin, it's crucial that ALL actual paths are contained within the children section.

Note: Failure to do so will result in the ENTIRE path being modified when navigating within the plugin, including platform navigation. While this won't render the plugin inoperable, further use of the platform may become unpredictable.

Additionally, to ensure correct navigation, the base paths should be passed through the updatePluginsRoutes(Routes) method. More details can be found here.

As a result, the declaration of paths should follow this structure:

// src/app/app-routing.module.ts
import { PlatformHelper } from  '@natec/mef-dev-platform-connector';
...
// const  routes: Routes = [];
const  routes: Routes = PlatformHelper.updatePluginsRoutes([
    {
        path:"",
        children:[
            // insert routes here
        ]
    }
]);
...

5. Creating of first component

NOTE! Implementing the layout directly in the AppComponent is not recommended. For better application development practices, it is advisable to extract all functionality into a separate component structure. Example

To achieve minimal functionality, you need to create one component:

ng g c test

After that, import it and add it to the routing configuration:

// src/app/app-routing.module.ts
import { PlatformHelper } from  '@natec/mef-dev-platform-connector';
import { TestComponent } from './test/test.component';
...
// const  routes: Routes = [];
const  routes: Routes = PlatformHelper.updatePluginsRoutes([
    {
        path:"",
        children:[
            {
                path:"",
                redirectTo:"test",
                pathMatch:  'full',
            },
            {
                path:"test",
                component:  TestComponent
            }
        ]
    }
]);
...

6. Specification file version.json

To upload to the platform, your project must include a specification file, which is generated by a script provided by @natec/mef-dev-platform-connector.

To generate the specification file, execute the following command:

npm explore @natec/mef-dev-platform-connector -- npm run generate-version-file

This command will generate the environments folder and its contents, including a set of files containing information about the plugin build.

To ensure the generated file is included in the build output, you need to add the path to the new asset in the configuration file.

// angular.json
...
"architect": {
    "build": {
        "options": {
            ...
            "assets": [
                "src/favicon.ico",
                "src/assets",
                "src/version.json" // <---    
            ]
...

To modify the specification file before each build for publication, it is a good practice to set up npm scripts as shown in the example

The result of its operation can also be used within the application. Example.

7. Build and deploy

To publish a new version or create a new plugin, you can use the following options: CLI interface (automated) and manual mode.

We strongly recommend using the CLI interface as it helps speed up development.

CLI Publication

metadata.json

To publish using the CLI, you need to create a file called metadata.json in the root of the project. It contains basic information about the plugin. It is important to note that publication can not only push a new version but also register a new plugin. In the case of registering a new plugin, it is important to correctly define the parameters name and serviceType, and if necessary pluginMefName, as after registration, their values cannot be changed. Therefore, changing these parameters in the future (during version updates) will be impossible.

serviceType

It is important to understand the purpose of the serviceType field; it corresponds to the type of plugin. | Value | Description | |-|-| | "UI" | Plugin contains only a UI app, without a backend part | | "APIUI" | Plugin contains UI and backend application |

pluginMefName

Used only for registering APIUI type plugins. Later (after successful registration), it may not be used.

Below is an example of an existing file with explanations of the fields.

{
  "name": "Simple plugin example",      // Displaied name of plugin        
  "serviceType": "UI",                  // Only UI app 
  //"pluginMefName": "TestPlugin",      // Only APIUI or API app 
  "description": "Lorem ipsum",         // Short description of plugin functionary
  "dependencies": [],                   // Used for included previusly loaded backend plugin 
  "config":{
    "routesUI":[                        // Presaved routes, displayed in menu
      {
          "lang":"en",
          "routerLink":"test",
          "label":"test"
      }
    ]
  },
  "externalUrl": null,                  // Plugin external url
  "configuration": null                 // Plugin configuration
}

CLI Scripts

There are two scripts for automatic build and publication. For convenience, ready-made npm scripts are presented in this project:

"generate-version-file": "npm explore @natec/mef-dev-platform-connector -- npm run generate-version-file",
"build:plugin": "npm run generate-version-file && ng build --configuration production --output-hashing none --single-bundle",
"publish": "npm explore @natec/mef-dev-platform-connector -- npm run mef-dev-publish",

If the metadata.json file is correctly formed, after running the command

npm run publish

the plugin will be successfully published.

Useful links

The instructions for registering a plugin on the platform can be found in the following link