Merge branch 'main' into feature/tree-create-routes
This commit is contained in:
@@ -4,7 +4,7 @@ import { customElement, state } from 'lit/decorators.js';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import { UmbModalService } from '../../../../../../core/modal';
|
||||
import { UmbWorkspaceDataTypeContext } from '../../workspace-data-type.context';
|
||||
import type { DataTypeDetails, ManifestPropertyEditorUI } from '@umbraco-cms/models';
|
||||
import type { DataTypeDetails } from '@umbraco-cms/models';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry';
|
||||
|
||||
import '../../../../../shared/property-editors/shared/property-editor-config/property-editor-config.element';
|
||||
@@ -78,15 +78,15 @@ export class UmbWorkspaceViewDataTypeEditElement extends UmbLitElement {
|
||||
if (!propertyEditorUIAlias) return;
|
||||
|
||||
this.observe(
|
||||
umbExtensionsRegistry.getByAlias<ManifestPropertyEditorUI>(propertyEditorUIAlias),
|
||||
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUI', propertyEditorUIAlias),
|
||||
(propertyEditorUI) => {
|
||||
// TODO: show error. We have stored a PropertyEditorUIAlias and can't find the PropertyEditorUI in the registry.
|
||||
if (!propertyEditorUI) return;
|
||||
|
||||
this._propertyEditorUIName = propertyEditorUI?.meta.label ?? propertyEditorUI?.name ?? '';
|
||||
this._propertyEditorUIAlias = propertyEditorUI?.alias ?? '';
|
||||
this._propertyEditorUIIcon = propertyEditorUI?.meta?.icon ?? '';
|
||||
this._propertyEditorModelAlias = propertyEditorUI?.meta?.propertyEditorModel ?? '';
|
||||
this._propertyEditorUIIcon = propertyEditorUI?.meta.icon ?? '';
|
||||
this._propertyEditorModelAlias = propertyEditorUI?.meta.propertyEditorModel ?? '';
|
||||
|
||||
this._workspaceContext?.update({ propertyEditorModelAlias: this._propertyEditorModelAlias });
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@ import { html } from 'lit';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { isManifestElementNameType } from '@umbraco-cms/extensions-api';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry';
|
||||
import type { ManifestTypes } from '@umbraco-cms/models';
|
||||
import type { ManifestBase } from '@umbraco-cms/models';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
|
||||
@customElement('umb-extension-root-workspace')
|
||||
export class UmbExtensionRootWorkspaceElement extends UmbLitElement {
|
||||
@state()
|
||||
private _extensions?: Array<ManifestTypes> = undefined;
|
||||
private _extensions?: Array<ManifestBase> = undefined;
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
|
||||
@@ -135,14 +135,12 @@ export class UmbEntityPropertyElement extends UmbLitElement {
|
||||
|
||||
private _observePropertyEditorUI() {
|
||||
this.propertyEditorUIObserver?.destroy();
|
||||
this.propertyEditorUIObserver = new UmbObserverController(this, umbExtensionsRegistry.getByAlias(this.propertyEditorUIAlias), (manifest) => {
|
||||
if (manifest?.type === 'propertyEditorUI') {
|
||||
this._gotData(manifest);
|
||||
}
|
||||
this.propertyEditorUIObserver = this.observe(umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUI', this.propertyEditorUIAlias), (manifest) => {
|
||||
this._gotEditor(manifest);
|
||||
});
|
||||
}
|
||||
|
||||
private _gotData(propertyEditorUIManifest?: ManifestPropertyEditorUI) {
|
||||
private _gotEditor(propertyEditorUIManifest?: ManifestPropertyEditorUI | null) {
|
||||
if (!propertyEditorUIManifest) {
|
||||
// TODO: if dataTypeKey didn't exist in store, we should do some nice UI.
|
||||
return;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { nothing } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { map } from 'rxjs';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
import { ManifestBase, ManifestTypes, umbExtensionsRegistry } from '@umbraco-cms/extensions-registry';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry';
|
||||
import { createExtensionElement } from '@umbraco-cms/extensions-api';
|
||||
import { isManifestElementableType } from 'src/core/extensions-api/is-manifest-elementable-type.function';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
@@ -40,7 +40,7 @@ export class UmbExtensionSlotElement extends UmbLitElement {
|
||||
umbExtensionsRegistry
|
||||
?.extensionsOfType(this.type)
|
||||
.pipe(map((extensions) => extensions.filter(this.filter))),
|
||||
async (extensions: ManifestTypes[]) => {
|
||||
async (extensions) => {
|
||||
|
||||
const oldLength = this._extensions.length;
|
||||
this._extensions = this._extensions.filter(current => extensions.find(incoming => incoming.alias === current.alias));
|
||||
@@ -48,7 +48,7 @@ export class UmbExtensionSlotElement extends UmbLitElement {
|
||||
this.requestUpdate('_extensions');
|
||||
}
|
||||
|
||||
extensions.forEach(async (extension: ManifestTypes) => {
|
||||
extensions.forEach(async (extension) => {
|
||||
|
||||
const hasExt = this._extensions.find(x => x.alias === extension.alias);
|
||||
if(!hasExt) {
|
||||
|
||||
@@ -58,27 +58,23 @@ export class UmbPropertyEditorConfigElement extends UmbLitElement {
|
||||
private _observePropertyEditorUIConfig() {
|
||||
if (!this._propertyEditorUIAlias) return;
|
||||
|
||||
this.observe(umbExtensionsRegistry.getByAlias(this.propertyEditorUIAlias), (manifest) => {
|
||||
if (manifest?.type === 'propertyEditorUI') {
|
||||
this._observePropertyEditorModelConfig(manifest.meta.propertyEditorModel);
|
||||
this._propertyEditorUIConfigProperties = manifest?.meta.config?.properties || [];
|
||||
this._propertyEditorUIConfigDefaultData = manifest?.meta.config?.defaultData || [];
|
||||
this._mergeConfigProperties();
|
||||
this._mergeConfigDefaultData();
|
||||
}
|
||||
this.observe(umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUI', this.propertyEditorUIAlias), (manifest) => {
|
||||
this._observePropertyEditorModelConfig(manifest?.meta.propertyEditorModel);
|
||||
this._propertyEditorUIConfigProperties = manifest?.meta.config?.properties || [];
|
||||
this._propertyEditorUIConfigDefaultData = manifest?.meta.config?.defaultData || [];
|
||||
this._mergeConfigProperties();
|
||||
this._mergeConfigDefaultData();
|
||||
});
|
||||
}
|
||||
|
||||
private _observePropertyEditorModelConfig(propertyEditorModelAlias?: string) {
|
||||
if (!propertyEditorModelAlias) return;
|
||||
|
||||
this.observe(umbExtensionsRegistry.getByAlias(propertyEditorModelAlias), (manifest) => {
|
||||
if (manifest?.type === 'propertyEditorModel') {
|
||||
this._propertyEditorModelConfigProperties = manifest?.meta.config?.properties || [];
|
||||
this._propertyEditorModelConfigDefaultData = manifest?.meta.config?.defaultData || [];
|
||||
this._mergeConfigProperties();
|
||||
this._mergeConfigDefaultData();
|
||||
}
|
||||
this.observe(umbExtensionsRegistry.getByTypeAndAlias('propertyEditorModel', propertyEditorModelAlias), (manifest) => {
|
||||
this._propertyEditorModelConfigProperties = manifest?.meta.config?.properties || [];
|
||||
this._propertyEditorModelConfigDefaultData = manifest?.meta.config?.defaultData || [];
|
||||
this._mergeConfigProperties();
|
||||
this._mergeConfigDefaultData();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { ManifestElementType } from '../models';
|
||||
import type { ManifestElement } from '../models';
|
||||
import { hasDefaultExport } from './has-default-export.function';
|
||||
import { isManifestElementNameType } from './is-manifest-element-name-type.function';
|
||||
import { loadExtension } from './load-extension.function';
|
||||
|
||||
export async function createExtensionElement(manifest: ManifestElementType): Promise<HTMLElement | undefined> {
|
||||
export async function createExtensionElement(manifest: ManifestElement): Promise<HTMLElement | undefined> {
|
||||
|
||||
//TODO: Write tests for these extension options:
|
||||
const js = await loadExtension(manifest);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { ManifestElementType, ManifestElementWithElementName } from '../models';
|
||||
import type { ManifestElement, ManifestElementWithElementName } from '../models';
|
||||
|
||||
export function isManifestElementNameType(manifest: unknown): manifest is ManifestElementWithElementName {
|
||||
return (
|
||||
typeof manifest === 'object' && manifest !== null && (manifest as ManifestElementType).elementName !== undefined
|
||||
typeof manifest === 'object' && manifest !== null && (manifest as ManifestElement).elementName !== undefined
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { ManifestElementType, ManifestTypes } from "../extensions-registry/models";
|
||||
import type { ManifestElement, ManifestBase } from "../extensions-registry/models";
|
||||
import { isManifestElementNameType } from "./is-manifest-element-name-type.function";
|
||||
import { isManifestJSType } from "./is-manifest-js-type.function";
|
||||
import { isManifestLoaderType } from "./is-manifest-loader-type.function";
|
||||
|
||||
export function isManifestElementableType(manifest: ManifestTypes): manifest is ManifestElementType {
|
||||
export function isManifestElementableType(manifest: ManifestBase): manifest is ManifestElement {
|
||||
return isManifestElementNameType(manifest) || isManifestLoaderType(manifest) || isManifestJSType(manifest);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ManifestTypes } from "../extensions-registry/models";
|
||||
import type { ManifestBase } from "../extensions-registry/models";
|
||||
import { ManifestJSType } from "./load-extension.function";
|
||||
|
||||
export function isManifestJSType(manifest: ManifestTypes): manifest is ManifestJSType {
|
||||
export function isManifestJSType(manifest: ManifestBase): manifest is ManifestJSType {
|
||||
return (manifest as ManifestJSType).js !== undefined;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ManifestTypes } from "../extensions-registry/models";
|
||||
import type { ManifestBase } from "../extensions-registry/models";
|
||||
import { ManifestLoaderType } from "./load-extension.function";
|
||||
|
||||
export function isManifestLoaderType(manifest: ManifestTypes): manifest is ManifestLoaderType {
|
||||
export function isManifestLoaderType(manifest: ManifestBase): manifest is ManifestLoaderType {
|
||||
return typeof (manifest as ManifestLoaderType).loader === 'function';
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { ManifestTypes } from '../models';
|
||||
import type { ManifestElement } from '../models';
|
||||
import { isManifestJSType } from './is-manifest-js-type.function';
|
||||
import { isManifestLoaderType } from './is-manifest-loader-type.function';
|
||||
|
||||
export type ManifestLoaderType = ManifestTypes & { loader: () => Promise<object | HTMLElement> };
|
||||
export type ManifestJSType = ManifestTypes & { js: string };
|
||||
export type ManifestLoaderType = ManifestElement & { loader: () => Promise<object | HTMLElement> };
|
||||
export type ManifestJSType = ManifestElement & { js: string };
|
||||
|
||||
export async function loadExtension(manifest: ManifestTypes): Promise<object | HTMLElement | null> {
|
||||
export async function loadExtension(manifest: ManifestElement): Promise<object | HTMLElement | null> {
|
||||
try {
|
||||
if (isManifestLoaderType(manifest)) {
|
||||
return manifest.loader();
|
||||
|
||||
@@ -1,30 +1,16 @@
|
||||
import { BehaviorSubject, map, Observable } from 'rxjs';
|
||||
import type {
|
||||
ManifestTypes,
|
||||
ManifestDashboard,
|
||||
ManifestWorkspaceView,
|
||||
ManifestEntrypoint,
|
||||
ManifestPropertyAction,
|
||||
ManifestPropertyEditorUI,
|
||||
ManifestPropertyEditorModel,
|
||||
ManifestSection,
|
||||
ManifestSectionView,
|
||||
ManifestTree,
|
||||
ManifestTreeItemAction,
|
||||
ManifestWorkspace,
|
||||
ManifestWorkspaceAction,
|
||||
ManifestCustom,
|
||||
ManifestPackageView,
|
||||
ManifestExternalLoginProvider,
|
||||
ManifestHeaderApp,
|
||||
ManifestCollectionView,
|
||||
ManifestCollectionBulkAction,
|
||||
ManifestTypeMap,
|
||||
ManifestBase
|
||||
} from '../../models';
|
||||
import { hasDefaultExport } from '../has-default-export.function';
|
||||
import { loadExtension } from '../load-extension.function';
|
||||
|
||||
type SpecificManifestTypeOrManifestBase<T extends keyof ManifestTypeMap | string> = T extends keyof ManifestTypeMap ? ManifestTypeMap[T] : ManifestBase;
|
||||
|
||||
export class UmbExtensionRegistry {
|
||||
private _extensions = new BehaviorSubject<Array<ManifestTypes>>([]);
|
||||
private _extensions = new BehaviorSubject<Array<ManifestBase>>([]);
|
||||
public readonly extensions = this._extensions.asObservable();
|
||||
|
||||
register(manifest: ManifestTypes & { loader?: () => Promise<object | HTMLElement> }): void {
|
||||
@@ -70,43 +56,27 @@ export class UmbExtensionRegistry {
|
||||
}
|
||||
|
||||
|
||||
getByAlias<T = ManifestTypes>(alias: string): Observable<T | null> {
|
||||
getByAlias(alias: string) {
|
||||
// TODO: make pipes prettier/simpler/reuseable
|
||||
return this.extensions.pipe(map((dataTypes) => dataTypes.find((extension) => extension.alias === alias) || null)) as Observable<T | null>;
|
||||
return this.extensions.pipe(map((dataTypes) => dataTypes.find((extension) => extension.alias === alias) || null));
|
||||
}
|
||||
|
||||
getByTypeAndAlias<Key extends keyof ManifestTypeMap>(type: Key, alias: string) {
|
||||
return this.extensionsOfType(type).pipe(map((extensions) => extensions.find((extension) => extension.alias === alias) || null));
|
||||
}
|
||||
|
||||
// TODO: implement unregister of extension
|
||||
|
||||
// Typings concept, need to put all core types to get a good array return type for the provided type...
|
||||
extensionsOfType(type: 'headerApp'): Observable<Array<ManifestHeaderApp>>;
|
||||
extensionsOfType(type: 'section'): Observable<Array<ManifestSection>>;
|
||||
extensionsOfType(type: 'sectionView'): Observable<Array<ManifestSectionView>>;
|
||||
extensionsOfType<T = ManifestTree>(type: 'tree'): Observable<Array<T>>;
|
||||
extensionsOfType(type: 'workspace'): Observable<Array<ManifestWorkspace>>;
|
||||
extensionsOfType(type: 'treeItemAction'): Observable<Array<ManifestTreeItemAction>>;
|
||||
extensionsOfType(type: 'dashboard'): Observable<Array<ManifestDashboard>>;
|
||||
extensionsOfType(type: 'dashboardCollection'): Observable<Array<ManifestDashboard>>;
|
||||
extensionsOfType(type: 'workspaceView'): Observable<Array<ManifestWorkspaceView>>;
|
||||
extensionsOfType(type: 'workspaceAction'): Observable<Array<ManifestWorkspaceAction>>;
|
||||
extensionsOfType(type: 'propertyEditorUI'): Observable<Array<ManifestPropertyEditorUI>>;
|
||||
extensionsOfType(type: 'propertyEditorModel'): Observable<Array<ManifestPropertyEditorModel>>;
|
||||
extensionsOfType(type: 'propertyAction'): Observable<Array<ManifestPropertyAction>>;
|
||||
extensionsOfType(type: 'packageView'): Observable<Array<ManifestPackageView>>;
|
||||
extensionsOfType(type: 'entrypoint'): Observable<Array<ManifestEntrypoint>>;
|
||||
extensionsOfType(type: 'custom'): Observable<Array<ManifestCustom>>;
|
||||
extensionsOfType(type: 'externalLoginProvider'): Observable<Array<ManifestExternalLoginProvider>>;
|
||||
extensionsOfType(type: 'collectionView'): Observable<Array<ManifestCollectionView>>;
|
||||
extensionsOfType(type: 'collectionBulkAction'): Observable<Array<ManifestCollectionBulkAction>>;
|
||||
extensionsOfType<T extends ManifestTypes>(type: string): Observable<Array<T>>;
|
||||
extensionsOfType(type: string): Observable<Array<ManifestTypes>> {
|
||||
|
||||
extensionsOfType<Key extends keyof ManifestTypeMap | string, T = SpecificManifestTypeOrManifestBase<Key>>(type: Key) {
|
||||
return this.extensions.pipe(
|
||||
map((exts) => exts.filter((ext) => ext.type === type).sort((a, b) => (b.weight || 0) - (a.weight || 0)))
|
||||
);
|
||||
) as Observable<Array<T>>;
|
||||
}
|
||||
|
||||
extensionsOfTypes<ExtensionType = ManifestTypes>(types: string[]): Observable<Array<ExtensionType>> {
|
||||
extensionsOfTypes<ExtensionType = ManifestBase>(types: string[]): Observable<Array<ExtensionType>> {
|
||||
return this.extensions.pipe(
|
||||
map((exts) => exts.filter((ext) => (types.indexOf(ext.type) !== -1)).sort((a, b) => (b.weight || 0) - (a.weight || 0)))
|
||||
) as Observable<Array<ExtensionType>>;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ export * from './collection-bulk-action.models';
|
||||
export * from './collection-view.models';
|
||||
|
||||
export type ManifestTypes =
|
||||
| ManifestCustom
|
||||
| ManifestHeaderApp
|
||||
| ManifestSection
|
||||
| ManifestSectionView
|
||||
@@ -55,48 +56,16 @@ export type ManifestTypes =
|
||||
| ManifestPackageView
|
||||
| ManifestExternalLoginProvider
|
||||
| ManifestEntrypoint
|
||||
| ManifestCustom
|
||||
| ManifestCollectionBulkAction
|
||||
| ManifestCollectionView;
|
||||
|
||||
export type ManifestStandardTypes =
|
||||
| 'headerApp'
|
||||
| 'section'
|
||||
| 'sectionView'
|
||||
| 'tree'
|
||||
| 'workspace'
|
||||
| 'workspaceAction'
|
||||
| 'workspaceView'
|
||||
| 'workspaceViewCollection'
|
||||
| 'treeItemAction'
|
||||
| 'propertyEditorUI'
|
||||
| 'propertyEditorModel'
|
||||
| 'dashboard'
|
||||
| 'dashboardCollection'
|
||||
| 'userDashboard'
|
||||
| 'propertyAction'
|
||||
| 'packageView'
|
||||
| 'entrypoint'
|
||||
| 'externalLoginProvider'
|
||||
| 'collectionBulkAction'
|
||||
| 'collectionView';
|
||||
export type ManifestStandardTypes = ManifestTypes['type'];
|
||||
|
||||
export type ManifestTypeMap = {
|
||||
[Manifest in ManifestTypes as Manifest['type']]: Manifest;
|
||||
};
|
||||
|
||||
|
||||
export type ManifestElementType =
|
||||
| ManifestSection
|
||||
| ManifestSectionView
|
||||
| ManifestTree
|
||||
| ManifestTreeItemAction
|
||||
| ManifestWorkspace
|
||||
| ManifestWorkspaceView
|
||||
| ManifestPropertyAction
|
||||
| ManifestPropertyEditorUI
|
||||
| ManifestDashboard
|
||||
| ManifestUserDashboard
|
||||
| ManifestWorkspaceAction
|
||||
| ManifestPackageView
|
||||
| ManifestExternalLoginProvider
|
||||
| ManifestCollectionBulkAction
|
||||
| ManifestCollectionView;
|
||||
|
||||
export interface ManifestBase {
|
||||
type: string;
|
||||
|
||||
Reference in New Issue
Block a user