Vue.js Add-ons🔗
The Masterportal offers a mechanism to inject your own developments into the sources, without them becoming a part of the Masterportal repository. See setting up the development environment for more information.
An add-on in itself is identically programmed as a native module is. For an example, see Tutorial 01: Creating a new module (Scale Switcher). However, an add-on lives in another repository and thus allows separate management.
All add-ons to be added are placed in the folder addons
found at Masterportal root level. Any number of such add-ons may be configured in a portal's config.js. Add-ons may bring their own package.json
file to specify further dependencies.
Please adhere to the following structure, in this example adding a tool (MyAddon1) and a GFI theme (MyGfiTheme):
Add-on folder structure🔗
File system example🔗
Only files related to add-ons must be placed in the addons
folder.
addons
|-- myAddon1
| index.js
| |-- components
| | |-- MyAddOn1.vue
| | |-- ...
| |-- store
| | |-- actionsMyAddOn1.js
| | |-- gettersMyAddOn1.js
| | |-- indexMyAddOn1.js
| | |-- mutationsMyAddOn1.js
| | |-- MyAddOn1.js // the equivalent of index.js
| |
| |-- locales
| | |-- de
| | | |-- additional.json
| | |-- en
| | | |-- additional.json
| |
| |-- doc
| | |-- config.json.md
| |
| |-- tests
| | |-- unit
| | | |-- components
| | | | |-- MyAddOn1.spec.js
| | | |-- store
| | | | |-- actionsMyAddOn1.spec.js
| | | | |-- gettersMyAddOn1.spec.js
| | | | |-- mutationsMyAddOn1.spec.js
| |
| |-- package.json
|-- myGfiTheme
| index.js
| |-- components
| | |-- MyGfiTheme.vue
| | |-- ...
| |-- locales
| | |-- de
| | | |-- additional.json
| | |-- en
| | | |-- additional.json
| |
| |-- doc
| | |-- config.json.md
| |
| |-- tests
| | |-- unit
| | | |-- components
| | | | |-- MyGfiTheme.spec.js
| |
| |-- package.json
|-- myGFIThemesFolder
| |-- myGFISubFolder
| | index.js
| | |-- components
| | | |-- MyGfiTheme.vue
| | | |-- ...
| | |-- locales
| | | |-- de
| | | | |-- additional.json
| | | |-- en
| | | | |-- additional.json
| | |
| | |-- doc
| | | |-- config.json.md
| | |
| | |-- tests
| | | |-- unit
| | | | |-- components
| | | | | |-- MyGfiTheme.spec.js
| | |
| | |-- package.json
|-- myControl
| index.js
| |-- components
| | |-- MyControl.vue
| | |-- ...
| |-- locales
| | |-- de
| | | |-- additional.json
| | |-- en
| | | |-- additional.json
| |
| |-- doc
| | |-- config.json.md
| |
| |-- tests
| | |-- unit
| | | |-- components
| | | | |-- MyControl.spec.js
| |
| |-- package.json
|-- myControlFolder
| |-- myControlSubFolder
| | index.js
| | |-- components
| | | |-- MyControl.vue
| | | |-- ...
| | |-- locales
| | | |-- de
| | | | |-- additional.json
| | | |-- en
| | | | |-- additional.json
| | |
| | |-- doc
| | | |-- config.json.md
| | |
| | |-- tests
| | | |-- unit
| | | | |-- components
| | | | | |-- MyControl.spec.js
| | |
| | |-- package.json
|-- mySearchInterface
| index.js
| js
| |-- mySearchInterfaceSearch.js
| |
| |-- tests
| | |-- unit
| | | |-- js
| | | | |-- mySearchInterfaceSearch.spec.js
| |
The entry point of each add-on must be a file named index.js
on add-on folder root level.
Configuration file🔗
Within the add-ons folder, a configuration file addonsConf.json
must exist. This file is to contain JSON that has the add-on's name as key; i.e., an add-on in addons/myAddOn1
would have myAddOn1
as key.
addonsConf.json
example🔗
Matching the example above, this would be a fitting configuration.
This types of add-ons are supported:
* Tools ("type": "tool"
)
* GFI themes ("type": "gfiTheme"
)
* Controls ("type": "control"
)
* Javascript ("type": "javascript"
)
* SearchInterface ("type": "searchInterface"
)
All entries to the addonsConf.json
defined by an object are expected to be written in Vue or pure javascript.
By default, an add-on's key is the name of its folder. By using the parameter path
you may specify any other path. This way, you may group multiple add-ons in a folder.
{
"myAddOn1": {
"type": "tool"
},
"myGfiTheme": {
"type": "gfiTheme"
},
"anotherGFITheme": {
"type": "gfiTheme",
"path": "myGFIThemesFolder/myGFISubFolder"
}
},
"myControl": {
"type": "control"
},
"anotherControl": {
"type": "control",
"path": "myControlFolder/myControlSubFolder"
},
"myJavascript": {
"type": "javascript"
},
"mySearchInterface": {
"type": "searchInterface"
},
}
Only files related to add-ons
may end up in this folder.
For additional required dependencies not included in the Masterportal, add a separate minimal package.json
file.
{
"name": "exampleAddon",
"version": "1.0.0",
"description": "I'm an example! I can say hello world.",
"dependencies": {
"hello": "^0.3.2"
}
}
Add-on example🔗
Create files🔗
The add-on example shall have the name VueAddOn with entry point file index.js
. The component VueAddOn.vue
is placed in the folder components
. From this, the following file structure results:
myMasterPortalFolder/
addons/
vueAddOn/
index.js
components/
VueAddOn.vue
store
VueAddOn.js
devtools/
doc/
[...]
Example store🔗
// myMasterPortalFolder/addons/VueAddon/store/VueAddon.js
import GenericTool from "../../../src/modules/tools/indexTools";
import composeModules from "../../../src/app-store/utils/composeModules";
import getters from "./gettersVueAddon";
import mutations from "./mutationsVueAddon";
import actions from "./actionsVueAddon";
import state from "./stateVueAddon";
export default composeModules([GenericTool, {
namespaced: true, // mandatory
state,
mutations,
actions,
getters
}]);
The contents state
, mutations
, actions
, and getters
may be placed in separate files or can alternatively be written directly to the store file. Please mind that setting namespaced: true
is mandatory.
// myMasterPortalFolder/addons/vueAddon/components/VueAddon.vue
<script>
import Tool from "../../../src/modules/tools/Tool.vue";
import {mapGetters, mapActions, mapMutations} from "vuex";
import getters from "../store/gettersVueAddon";
import mutations from "../store/mutationsVueAddon";
export default {
name: "VueAddon",
components: {
Tool
},
computed: {
...mapGetters("Tools/VueAddon", Object.keys(getters))
},
/**
* Put initialize here if mounting occurs after config parsing
* @returns {void}
*/
mounted () {
this.initialize();
},
methods: {
...mapActions("Tools/VueAddon", [
"initialize"
]),
...mapMutations("Tools/VueAddon", Object.keys(mutations))
}
};
</script>
<template lang="html">
<Tool
:title="$t(name)"
:icon="icon"
:active="active"
:render-to-window="renderToWindow"
:resizable-window="resizableWindow"
:deactivateGFI="deactivateGFI"
>
<template v-slot:toolBody>
<div
v-if="active"
id="vue-addon"
>
{{ $t("additional:modules.tools.vueAddon.content") }}
</div>
</template>
</Tool>
</template>
Writing the index.js
file🔗
Within the index.js
file, all components (Vue components, store, translations, ...) are aggregated and exported via a single entry point.
Theoretically, the entry point may be configured within the addonsConf.json
file arbitrarily. However, it is required to be index.js
, since webpack will not load the module correctly else.
Please check that all components are imported correctly, and not in a .default
one level deeper in the object. This may e.g. happen if you use import * as VueAddonComponent from" ./components/VueAddon.vue ";
to import the component.
// myMasterPortalFolder/addons/vueAddon/index.js
import VueAddonComponent from "./components/VueAddon.vue";
import VueAddonStore from "./store/VueAddon";
import deLocale from "./locales/de/additional.json";
import enLocale from "./locales/en/additional.json";
export default {
component: VueAddonComponent,
store: VueAddonStore,
locales: {
de: deLocale,
en: enLocale
}
};
Creating the addonsConf.json
🔗
Activate the add-on example in the portal's config.js
🔗
Configure the add-on example as tool in the portal's config.json
for it to appear in the menu🔗
// myMasterPortalFolder/config.json
...
"tools": {
"name": "Tools",
"icon": "bi-wrench",
"children": {
"vueAddon": {
"name": "translate#additional:modules.tools.vueAddon.title",
"icon": "bi-list-ul"
},
index.js for pure javascript🔗
// myMasterPortalFolder/addons/myJavascript/index.js
import myJavascript from "./myJavascript";
import mySecondJavascript from "./mySecondJavascript";
import deLocale from "./locales/de/additional.json";
import enLocale from "./locales/en/additional.json";
export default {
myJavascript,
mySecondJavascript,
locales: {
de: deLocale,
en: enLocale
}
};
Write JSDoc🔗
For this, create a file namespaces.js
in the jsdoc
folder and add Addons
as @memberof
.
In the file model.js
, @memberOf
must be prefixed with Addons.
for this to work correctly.