How to create a web component that meets all the requirements for publication - noi-techpark/odh-docs GitHub Wiki

This how to guide will aid you in the process of creating a valid web-component that has all the requisites necessary to be uploaded on the Open Data Hub Store.

Create

Prerequisites

To build the project, the following must have been installed in your local machine:

  • Node 12/ NPM 6
  • Webpack
  • Docker

Start from the web-component boilerplate

You'll have to start from the boilerplate made available by the noi-tech park on GitHub here. Before beginning check out how to contribute to the Noi GitHUb here.

  • Fork the repository
  • Checkout a topic branch from the development branch.
  • Then ask the customer care ([email protected]) for a repository for your project, that will be the repository to which you'll make the pull request to.

In the boilerplate it's integrated an hello world webcomponent ready to use. If you have the prerequisites installed to run the hello world you'll have to just use these three commands in the powershell terminal:

  • npm run build
  • cp .env.example .env
  • docker-compose up

Then in your browser in localhost:8999 you'll see the hello world component in the ODH webcomponent store.

Modify the file wcs-manifest.json

  • To register with the web components hub a wcs-manifest.json file must be in your repository's root directory. A manifest file should look like this:

    {
    + "title": "TODO: Title of your webcomponent",
    + "description": "TODO: Description of your webcomponent",
    + "descriptionAbstract": "TODO: Small description of your webcomponent",
    "license": "AGPL-3.0-or-later",
    "copyrightHolders": [
        {
        "name": "NOI",
        "email": "[email protected]",
        "organization": "NOI S.p.A",
        "organizationUrl": "https://noi.bz.it"
        }
    ],
    + "authors": [
        {
        "name": "your-name-or-company",
        "email": "...",
        "organization": "...",
        "organizationUrl": "..."
        }
    ],
    
    //these files will be used by the docker
    
    + "image": null, 
    //A screenshot of the webcomponent that will be used as a thumbnail in the webcomponent store front-page. The filename should be “wcs-logo.png” and it should be placed in the image tag of the wcs-manifest.json like “image”: “wcs-logo.png”
    
    "searchTags": [],
    "dist": {
        "basePath": "dist", // folder where the bundle js generated from webpack will be 
        "files": [
    +   "app.min.js" //file js generated from the webpack NOTE: Change the file name to yours
        ],
        "scripts": [ //this section is optional
        {
            "file": "odh-this-repos-name-without-webcomp.min.js",
            "parameter": ""
        }
        ]
    },
    "configuration": {
    +    "tagName": "name of your webcomp tag",
        "options": []
    }
    }
  • Adjust the general parts like title, description, … etc

    Remember to add your wcs-logo in image. This will be the thumbnail displayed in the store

  • The configuration section of the manifest is needed for the configurator to know what options to include. Here are some examples of what a configuration may include:

    Example of the configuration section
    "configuration": {
        "tagName": "map-widget",
        "options": [
        {
            "key": "singleSelect",
            "type": "select",
            "label": "a single select",
            "options": {
            "values": ["optionA", "optionB"],
            "default": "optionA"
            }
        },
        {
            "key": "multiselectField",
            "type": "multiselect",
            "required": true,
            "options": {
            "label": "a multiselect field",
            "values": ["optionA","optionB","optionC"],
            "default": []
            }
        },
        {
            "key": "sample-A",
            "type": "text",
            "required": false,
            "options": {
            "default": "Test String"
            }
        },
        {
            "key": "sample-B",
            "type": "textarea",
            "required": false,
            "options": {
            "default": "A multi-\nLine Text"
            }
        },
        {
            "key": "sample-C",
            "type": "number",
            "required": false,
            "options": {
            "default": "342",
            "min": 0,
            "max": 600,
            "step": 1
            }
        },
        {
            "key": "sample-D",
            "type": "number",
            "required": false,
            "options": {
            "default": "34.2",
            "min": 0,
            "max": 60.04,
            "step": 0.01
            }
        },
        {
            "key": "booleanField",
            "type": "bool",
            "required": false,
            "options": {
            "label": "a boolean field",
            "default": false"
            }
        },
        {
            "key": "sample-F",
            "type": "object",
            "required": false,
            "options": {
            "default": {}
            }
        }
        ]
    }
    

Test the wcs-manifest.json with the online test tool Validator

Create in SRC folder

In the SRC folder you should create all the js files necessary for your webcomponent.

In our example you can find a simple webcomponent made using HTMLElement,taken directly from the hello world example that you can find in the webcomp boilerplate

Example of a simple js file with HTMLElement
```diff
class HelloWorld extends HTMLElement {
    constructor() {
        super();

        // We need an encapsulation of our component to not 
        // interfer with the host, nor be vulnerable to outside 
        // changes --> Solution = SHADOW DOM
        this.shadow = this.attachShadow(
            {mode: "open"}    // Set mode to "open", to have access to 
                            // the shadow dom from inside this component
        );
    }

    // Attributes we care about getting values from
    // Static, because all HelloWorld instances have the same
    //   observed attribute names
    static get observedAttributes() {
        return ['title'];
    }

    // Override from HTMLElement 
    // Do not use setters here, because you might end up with an endless loop
    attributeChangedCallback(propName, oldValue, newValue) {
        console.log(`Changing "${propName}" from "${oldValue}" to "${newValue}"`);
        if (propName === "title") {
            this.render();
        }
    }

    // We should better use such getters and setters and not
    // internal variables for that to avoid the risk of an
    // endless loop and to have attributes in the html tag and
    // Javascript properties always in-sync.
    get title() {
        return this.getAttribute("title");
    }

    set title(newTitle) {
        this.setAttribute("title", newTitle)
    }

    // Triggers when the element is added to the document *and*
    // becomes part of the page itself (not just a child of a detached DOM)
    connectedCallback() {
        this.render();
    }

    render() {
        this.shadow.innerHTML = `
            <style> 
                h1 {
                    color: black; 
                } 
            </style>
            <h1>
                ${this.title}
            </h1>
        `;
    }
}

// Register our first Custom Element named <hello-world>
customElements.define('hello-world', HelloWorld);

```

Test the webcomponent

To test the webcomponent you use Webpack and Docker.

Installing Webpack

Webpack is used to compile JavaScript modules. Here you can find more information.

Basic Setup

  • initialize npm
    npm init -y
  • install Webpack Locally
  • install the webpack-cli (the tool used to run webpack on the command line)
    npm install webpack webpack-cli --save-dev

Creating a bundle

To test the webcomponent on docker you'll have first to bundle all your files and assets (ex: CSS, Images, Fonts) in a single JS file.
You can also see here the guide provided by Webapack on how to bundle assets.
This file will be generated from webpack in the dist folder and it is the one you'll have to recall in the wcs-manifest.json.

This is an example on how to create a simple bundle without assets (to learn how to bundle assets please follow this guide here)

  • Create a folder called dist
  • Create a webpack.config.js file
const path = require('path');

module.exports = {
  entry: './src/index.js', // your js file to bundle
  output: {
    filename: 'main.js', //file name that you should put in the wcs-manifest.json.
    path: path.resolve(__dirname, 'dist'), 
  },
};
  • Run the build
    npx webpack --config webpack.config.js

    NOTE: If a webpack.config.js is present, the webpack command picks it up by default. We use the --config option here only to show that you can pass a configuration of any name. This will be useful for more complex configurations that need to be split into multiple files.

Modify the Package.json

  • Adjust the general parts like name, description, …

Given it's not particularly fun to run a local copy of webpack from the CLI, we can set up a little shortcut. Let's adjust our package.json by adding an npm script: - Adjust the scripts “npm run start”, “npm run build”, “npm run lint” and “npm run test”

Example: If you use webpack the file might be:

  "name": "webcomponent-demo",
  "version": "1.0.0",
  "private": true,
  "scripts": {
+  "build": "webpack"
  }

Now the npm run build command can be used in place of the npx command we used earlier. Note that within scripts we can reference locally installed npm packages by name the same way we did with npx. This convention is the standard in most npm-based projects because it allows all contributors to use the same set of common scripts.

Installing Docker

Now that you have the single js file created by the webpack you can use docker to run the file and see the resulting webcomp on docker. But first you'll have to install it.
Install Docker (with Docker Compose) locally on your machine.

The docker containers

In the file docker-compose.yml you can see all the containers that will open on docker:
The first one called: app is the one that will show your webcomponent, all the other below are the necessary container for the open data hub Webcomponent store. These containers are there for the last step of testing if your new webcomp will be visible in the store.

START:

  • Create a .env file:
    cp .env.example .env
  • [Optional] Adjust port numbers in .env if they have conflicts with services already running on your machine
  • Start the store with:
    docker-compose up -d
  • Update the docker using the scripts commands of the webpack
    ex : npm run build

    This command in our example will re-bundle your files and update the view on docker

  • Wait until the containers are running. You can check the current state with:
    docker-compose logs --tail 500 -f
  • Access webcomponent running in separated docker in your browser on:
    localhost:8998
  • Access the store in your browser on:
    localhost:8999

Publish a new version of your webcomponent

  • Increase version number WC_VERSION in your .env file
  • Then run: docker-compose up wcstore-cli

Stop the docker containers

  • docker-compose stop

Delete your webcomponents from the store

  • [sudo] rm -f workspace
  • docker-compose rm -f -v postgres

Test if your webcomp will run in the webcomp store

The last step is to test if your web component will run on the Open Data Hub webcomponent store. This is a very important step, because we will not accept web components that won't work on our store. For the docker commands please consult the paragraph above.

Test in a local docker instance of the webcomponent store

If you want to test the webcomponent on a local instance of the webcomponent store to make sure that it will run correctly also on the real store. You can also access the webcomponent running in a simple separated docker container outside of the store.

For accessing the webcomponent in a separated docker in the browser you will need a server (e.g. webpack dev-server) that is hosting a page which includes the webcomponent tag, as well as the script defining it. This page needs to be hosted on port 8080 as specified in your docker-compose file.

Final requirements for submission

  • One single js file
  • Assets like css or images need to be lazy loaded or bundled into the single js file with https://webpack.js.org/
  • A screenshot of the webcomponent that will be used as a thumbnail in the webcomponent store front-page. The filename should be “wcs-logo.png” and it should be placed in the image tag of the wcs-manifest.json like “image”: “wcs-logo.png” -The webcomponent should be visible and work in the ODH Webcomponent store (docker test) -Delete the containers of the ODH store in the docker-compose.yml file (every container except app- the first one)

Last Steps

  • Create a pull request against the development branch (A more detailed description on how to contribute on the the Noi-techpark GitHub can be found here)
  • Finally, to publish check out this how to guide here

Support

For support, please contact [email protected].

⚠️ **GitHub.com Fallback** ⚠️