load extension function

This commit is contained in:
Niels Lyngsø
2022-06-01 09:01:54 +02:00
parent 3d02659026
commit f995539f0c
6 changed files with 81 additions and 20 deletions

View File

@@ -3,11 +3,15 @@ import { BehaviorSubject, map, Observable } from 'rxjs';
// TODO: how do we want to type extensions?
export type UmbExtensionType = 'startUp' | 'section' | 'propertyEditorUI' | 'dashboard';
export type UmbExtensionManifestJSModel = {
elementName?: string;
}
export type UmbExtensionManifestBase = {
//type: string;
alias: string;
name: string;
js?: string | (() => Promise<unknown>);
js?: string | (() => Promise<UmbExtensionManifestJSModel>);
elementName?: string;
//meta: undefined;
}

View File

@@ -0,0 +1,30 @@
import { UmbExtensionManifest, UmbExtensionManifestJSModel } from './extension.registry';
export function loadExtension(manifest: UmbExtensionManifest): Promise<UmbExtensionManifestJSModel> | Promise<null> | null {
if (typeof manifest.js === 'function') {
return manifest.js() as Promise<UmbExtensionManifestJSModel>;
}
// TODO: verify if this is acceptable solution.
if (typeof manifest.js === 'string') {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script .type = 'text/javascript';
//script.charset = 'utf-8';
script.async = true;
script.src = manifest.js as string;
script.onload = function () {
resolve(null);
};
script.onerror = function () {
reject(new Error(`Script load error for ${manifest.js}`))
};
document.body.appendChild(script);
}) as Promise<null>;
}
console.log('-- Extension does not have any referenced JS')
return Promise.resolve(null);
}

View File

@@ -94,6 +94,17 @@ const registerInternalManifests = async () => {
group: 'common',
}
},
{
type: 'propertyEditorUI',
alias: 'External.PropertyEditorUI.Test',
name: 'Text',
elementName: 'external-property-editor-test', //Gets the element name from JS file.
js: '/src/property-editors/external-property-editor-test.js',
meta: {
icon: 'document',
group: 'common',
}
},
{
type: 'propertyEditorUI',
alias: 'Umb.PropertyEditorUI.Textarea',

View File

@@ -6,6 +6,7 @@ import { UmbDataTypeStore } from '../core/stores/data-type.store';
import { mergeMap, Subscription, map, switchMap } from 'rxjs';
import { DataTypeEntity } from '../mocks/data/content.data';
import { UmbExtensionManifest, UmbExtensionRegistry } from '../core/extension';
import { loadExtension } from '../core/extension/load-extension.function';
@customElement('umb-node-property-data-type')
class UmbNodePropertyDataType extends UmbContextConsumerMixin(LitElement) {
@@ -96,28 +97,30 @@ class UmbNodePropertyDataType extends UmbContextConsumerMixin(LitElement) {
const oldValue = this._element;
if (typeof _propertyEditorUI.js === 'function') {
this._element = _propertyEditorUI.js();
// TODO: Niels: I guess this is not the element returned but a Promise of loading the JS, which hopefully exports the Class or maybe an ElementName prop?
}
if (typeof _propertyEditorUI.js === 'string') {
// const loadJsPromise = (() => import(_propertyEditorUI.js as string))();
// TODO: show a loader until JS is loaded?
}
loadExtension(_propertyEditorUI)?.then(js => {
if (_propertyEditorUI.elementName) {
this._element = document.createElement(_propertyEditorUI.elementName);
}
// TODO: something with JS
console.log('ext js', js);
// IF we got a JS file loaded, we can use its elementName prop.
const elementName = _propertyEditorUI.elementName || js?.elementName;
// TODO: Set/Parse Data-Type-UI-configuration
if (elementName) {
this._element = document.createElement(elementName);
}
// TODO: Set/Parse Data-Type-UI-configuration
if(oldValue) {
oldValue.removeEventListener('property-editor-change', this._onPropertyEditorChange);
}
this._element.addEventListener('property-editor-change', this._onPropertyEditorChange);
this._element.value = this.value;// Be aware its duplicated code
this.requestUpdate('element', oldValue);
}).catch(() => {
// TODO: loading JS failed so we should do some nice UI. (This does only happen if extension has a js prop, otherwise we concluded that no source was needed resolved the load.)
});
if(oldValue) {
oldValue.removeEventListener('property-editor-change', this._onPropertyEditorChange);
}
this._element.addEventListener('property-editor-change', this._onPropertyEditorChange);
this._element.value = this.value;// Be aware its duplicated code
this.requestUpdate('element', oldValue);
}
private _onPropertyEditorChange = ( e:CustomEvent) => {

View File

@@ -0,0 +1,11 @@
class ExternalPropertyEditorTest extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'}); // sets and returns 'this.shadowRoot'
const wrapper = document.createElement('span');
wrapper.textContent = 'hello world';
this.shadowRoot.append(wrapper);
}
}
customElements.define('external-property-editor-test', ExternalPropertyEditorTest);

View File

@@ -26,6 +26,8 @@ class UmbPropertyEditorText extends LitElement {
}
}
export const elementName = 'umb-property-editor-text';
declare global {
interface HTMLElementTagNameMap {
'umb-property-editor-text': UmbPropertyEditorText;