diff --git a/src/Umbraco.Web.UI.Client/libs/extensions-api/registry/extension.registry.ts b/src/Umbraco.Web.UI.Client/libs/extensions-api/registry/extension.registry.ts index c1279b91f7..7ced4c0dbf 100644 --- a/src/Umbraco.Web.UI.Client/libs/extensions-api/registry/extension.registry.ts +++ b/src/Umbraco.Web.UI.Client/libs/extensions-api/registry/extension.registry.ts @@ -70,6 +70,10 @@ export class UmbExtensionRegistry { this._extensions.next([...extensionsValues, manifest as ManifestTypes]); } + registerMany(manifests: Array): void { + manifests.forEach((manifest) => this.register(manifest)); + } + unregister(alias: string): void { const oldExtensionsValues = this._extensions.getValue(); const newExtensionsValues = oldExtensionsValues.filter((extension) => extension.alias !== alias); diff --git a/src/Umbraco.Web.UI.Client/libs/extensions-registry/entry-point-extension-initializer.ts b/src/Umbraco.Web.UI.Client/libs/extensions-registry/entry-point-extension-initializer.ts index 1ab0d19abe..4f28cf050b 100644 --- a/src/Umbraco.Web.UI.Client/libs/extensions-registry/entry-point-extension-initializer.ts +++ b/src/Umbraco.Web.UI.Client/libs/extensions-registry/entry-point-extension-initializer.ts @@ -3,26 +3,27 @@ import { hasInitExport, loadExtension, UmbExtensionRegistry } from '@umbraco-cms import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller'; export class UmbEntryPointExtensionInitializer { - #rootHost; + #host; #extensionRegistry; + #entryPointMap = new Map(); - constructor(rootHost: UmbControllerHostElement, extensionRegistry: UmbExtensionRegistry) { - this.#rootHost = rootHost; + constructor(host: UmbControllerHostElement, extensionRegistry: UmbExtensionRegistry) { + this.#host = host; this.#extensionRegistry = extensionRegistry; - // TODO: change entrypoint extension to be entryPoint: - extensionRegistry.extensionsOfType('entrypoint').subscribe((entryPoints) => { + extensionRegistry.extensionsOfType('entryPoint').subscribe((entryPoints) => { entryPoints.forEach((entryPoint) => { + if (this.#entryPointMap.has(entryPoint.alias)) return; + this.#entryPointMap.set(entryPoint.alias, entryPoint); this.instantiateEntryPoint(entryPoint); }); }); } - instantiateEntryPoint(manifest: ManifestEntrypoint) { - loadExtension(manifest).then((js) => { - // If the extension has an onInit export, be sure to run that or else let the module handle itself - if (hasInitExport(js)) { - js.onInit(this.#rootHost, this.#extensionRegistry); - } - }); + async instantiateEntryPoint(manifest: ManifestEntrypoint) { + const js = await loadExtension(manifest); + // If the extension has an onInit export, be sure to run that or else let the module handle itself + if (hasInitExport(js)) { + js.onInit(this.#host, this.#extensionRegistry); + } } } diff --git a/src/Umbraco.Web.UI.Client/libs/extensions-registry/models.ts b/src/Umbraco.Web.UI.Client/libs/extensions-registry/models.ts index 4434d79ab4..7e336f7d1d 100644 --- a/src/Umbraco.Web.UI.Client/libs/extensions-registry/models.ts +++ b/src/Umbraco.Web.UI.Client/libs/extensions-registry/models.ts @@ -234,7 +234,7 @@ export interface ManifestWithMeta extends ManifestBase { * You could have custom logic to decide which extensions to load/register by using extensionRegistry */ export interface ManifestEntrypoint extends ManifestBase { - type: 'entrypoint'; + type: 'entryPoint'; /** * The file location of the javascript file to load in the backoffice diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index 116be1ac07..65545cf51d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -1,40 +1,30 @@ import { defineElement } from '@umbraco-ui/uui-base/lib/registration'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html } from 'lit'; - -import { UmbCurrentUserStore, UMB_CURRENT_USER_STORE_CONTEXT_TOKEN } from './users/current-user/current-user.store'; -import { - UmbCurrentUserHistoryStore, - UMB_CURRENT_USER_HISTORY_STORE_CONTEXT_TOKEN, -} from './users/current-user/current-user-history.store'; - +import { UmbStoreExtensionInitializer } from '../core/store-extension-initializer'; import { UmbBackofficeContext, UMB_BACKOFFICE_CONTEXT_TOKEN, } from './shared/components/backoffice-frame/backoffice.context'; -import { UmbThemeContext } from './themes/theme.context'; -import { - UMB_APP_LANGUAGE_CONTEXT_TOKEN, - UmbAppLanguageContext, -} from './settings/languages/app-language-select/app-language.context'; -import { UmbServerExtensionController } from './packages/repository/server-extension.controller'; +import { UmbExtensionInitializer } from './packages/repository/server-extension.controller'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; -import { createExtensionClass, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; import { UmbEntryPointExtensionInitializer } from '@umbraco-cms/backoffice/extensions-registry'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -// Domains -import './settings'; -import './documents'; -import './media'; -import './members'; -import './translation'; -import './users'; -import './packages'; -import './search'; -import './templating'; -import './shared'; +const CORE_PACKAGES = [ + import('./shared/umbraco-package'), + import('./settings/umbraco-package'), + import('./documents/umbraco-package'), + import('./media/umbraco-package'), + import('./members/umbraco-package'), + import('./translation/umbraco-package'), + import('./users/umbraco-package'), + import('./packages/umbraco-package'), + import('./search/umbraco-package'), + import('./templating/umbraco-package'), +]; @defineElement('umb-backoffice') export class UmbBackofficeElement extends UmbLitElement { @@ -58,23 +48,12 @@ export class UmbBackofficeElement extends UmbLitElement { constructor() { super(); - - new UmbEntryPointExtensionInitializer(this, umbExtensionsRegistry); - this.provideContext(UMB_MODAL_CONTEXT_TOKEN, new UmbModalContext(this)); this.provideContext(UMB_NOTIFICATION_CONTEXT_TOKEN, new UmbNotificationContext()); - this.provideContext(UMB_CURRENT_USER_STORE_CONTEXT_TOKEN, new UmbCurrentUserStore()); - this.provideContext(UMB_APP_LANGUAGE_CONTEXT_TOKEN, new UmbAppLanguageContext(this)); this.provideContext(UMB_BACKOFFICE_CONTEXT_TOKEN, new UmbBackofficeContext()); - new UmbThemeContext(this); - new UmbServerExtensionController(this, umbExtensionsRegistry); - this.provideContext(UMB_CURRENT_USER_HISTORY_STORE_CONTEXT_TOKEN, new UmbCurrentUserHistoryStore()); - - // Register All Stores - // TODO: can we use kinds here so we don't have to hardcode the types? - this.observe(umbExtensionsRegistry.extensionsOfTypes(['store', 'treeStore', 'itemStore']), (stores) => { - stores.forEach((store) => createExtensionClass(store, [this])); - }); + new UmbEntryPointExtensionInitializer(this, umbExtensionsRegistry); + new UmbStoreExtensionInitializer(this); + new UmbExtensionInitializer(this, umbExtensionsRegistry, CORE_PACKAGES); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/index.ts index 96b85feed0..482ad3dab6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/index.ts @@ -4,9 +4,7 @@ import { manifests as contentMenuManifest } from './menu.manifests'; import { manifests as documentBlueprintManifests } from './document-blueprints/manifests'; import { manifests as documentTypeManifests } from './document-types/manifests'; import { manifests as documentManifests } from './documents/manifests'; - -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; -import { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; +import type { UmbEntrypointOnInit } from '@umbraco-cms/backoffice/extensions-api'; export const manifests = [ ...dashboardManifests, @@ -17,8 +15,6 @@ export const manifests = [ ...documentManifests, ]; -const registerExtensions = (manifests: Array) => { - manifests.forEach((manifest) => umbExtensionsRegistry.register(manifest)); +export const onInit: UmbEntrypointOnInit = (_host, extensionRegistry) => { + extensionRegistry.registerMany(manifests); }; - -registerExtensions(manifests); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/umbraco-package.ts new file mode 100644 index 0000000000..af3c9d6830 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/umbraco-package.ts @@ -0,0 +1,10 @@ +export const name = 'Umbraco.Core.DocumentManagement'; +export const version = '0.0.1'; +export const extensions = [ + { + name: 'Document Management Entry Point', + alias: 'Umb.EntryPoint.DocumentManagement', + type: 'entryPoint', + loader: () => import('./index'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/index.ts index c6eb537f80..644c7d1b88 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/index.ts @@ -2,14 +2,10 @@ import { manifests as mediaSectionManifests } from './section.manifests'; import { manifests as mediaMenuManifests } from './menu.manifests'; import { manifests as mediaManifests } from './media/manifests'; import { manifests as mediaTypesManifests } from './media-types/manifests'; - -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; -import { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; +import type { UmbEntrypointOnInit } from '@umbraco-cms/backoffice/extensions-api'; export const manifests = [...mediaSectionManifests, ...mediaMenuManifests, ...mediaManifests, ...mediaTypesManifests]; -const registerExtensions = (manifests: Array) => { - manifests.forEach((manifest) => umbExtensionsRegistry.register(manifest)); +export const onInit: UmbEntrypointOnInit = (_host, extensionRegistry) => { + extensionRegistry.registerMany(manifests); }; - -registerExtensions(manifests); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/umbraco-package.ts new file mode 100644 index 0000000000..f60335274e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/umbraco-package.ts @@ -0,0 +1,10 @@ +export const name = 'Umbraco.Core.MediaManagement'; +export const version = '0.0.1'; +export const extensions = [ + { + name: 'Media Management Entry Point', + alias: 'Umb.EntryPoint.MediaManagement', + type: 'entryPoint', + loader: () => import('./index'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/index.ts index ec7c105679..9b0ee2983f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/index.ts @@ -3,9 +3,7 @@ import { manifests as menuSectionManifests } from './menu.manifests'; import { manifests as memberGroupManifests } from './member-groups/manifests'; import { manifests as memberTypeManifests } from './member-types/manifests'; import { manifests as memberManifests } from './members/manifests'; - -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; -import { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; +import type { UmbEntrypointOnInit } from '@umbraco-cms/backoffice/extensions-api'; export const manifests = [ ...memberSectionManifests, @@ -15,8 +13,6 @@ export const manifests = [ ...memberManifests, ]; -const registerExtensions = (manifests: Array) => { - manifests.forEach((manifest) => umbExtensionsRegistry.register(manifest)); +export const onInit: UmbEntrypointOnInit = (_host, extensionRegistry) => { + extensionRegistry.registerMany(manifests); }; - -registerExtensions(manifests); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/umbraco-package.ts new file mode 100644 index 0000000000..25102a156d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/umbraco-package.ts @@ -0,0 +1,10 @@ +export const name = 'Umbraco.Core.MemberManagement'; +export const version = '0.0.1'; +export const extensions = [ + { + name: 'Member Management Entry Point', + alias: 'Umb.EntryPoint.MemberManagement', + type: 'entryPoint', + loader: () => import('./index'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/packages/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/packages/index.ts index 41064c5222..aedfb23948 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/packages/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/packages/index.ts @@ -2,9 +2,7 @@ import { manifests as repositoryManifests } from './repository/manifests'; import { manifests as packageBuilderManifests } from './package-builder/manifests'; import { manifests as packageRepoManifests } from './package-repo/manifests'; import { manifests as packageSectionManifests } from './package-section/manifests'; - -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; -import { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; +import type { UmbEntrypointOnInit } from '@umbraco-cms/backoffice/extensions-api'; export const manifests = [ ...repositoryManifests, @@ -13,8 +11,6 @@ export const manifests = [ ...packageSectionManifests, ]; -const registerExtensions = (manifests: Array) => { - manifests.forEach((manifest) => umbExtensionsRegistry.register(manifest)); +export const onInit: UmbEntrypointOnInit = (_host, extensionRegistry) => { + extensionRegistry.registerMany(manifests); }; - -registerExtensions(manifests); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/packages/repository/server-extension.controller.ts b/src/Umbraco.Web.UI.Client/src/backoffice/packages/repository/server-extension.controller.ts index c3f33ced28..aa3807e7dd 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/packages/repository/server-extension.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/packages/repository/server-extension.controller.ts @@ -3,19 +3,28 @@ import { UmbPackageRepository } from './package.repository'; import { UmbController, UmbControllerHostElement } from '@umbraco-cms/backoffice/controller'; import { UmbExtensionRegistry } from '@umbraco-cms/backoffice/extensions-api'; -export class UmbServerExtensionController extends UmbController { +export class UmbExtensionInitializer extends UmbController { #host: UmbControllerHostElement; + #extensionRegistry: UmbExtensionRegistry; #unobserve = new Subject(); #repository: UmbPackageRepository; + #localPackages: Array>; - constructor(host: UmbControllerHostElement, private readonly extensionRegistry: UmbExtensionRegistry) { - super(host, UmbServerExtensionController.name); + constructor( + host: UmbControllerHostElement, + extensionRegistry: UmbExtensionRegistry, + localPackages: Array> + ) { + super(host, UmbExtensionInitializer.name); this.#host = host; + this.#extensionRegistry = extensionRegistry; this.#repository = new UmbPackageRepository(host); + this.#localPackages = localPackages; } hostConnected(): void { - this.#loadPackages(); + this.#loadLocalPackages(); + this.#loadServerPackages(); } hostDisconnected(): void { @@ -23,7 +32,14 @@ export class UmbServerExtensionController extends UmbController { this.#unobserve.complete(); } - async #loadPackages() { + async #loadLocalPackages() { + this.#localPackages.forEach(async (packageImport) => { + const packageModule = await packageImport; + this.#extensionRegistry.registerMany(packageModule.extensions); + }); + } + + async #loadServerPackages() { const extensions$ = await this.#repository.extensions(); extensions$ @@ -31,10 +47,6 @@ export class UmbServerExtensionController extends UmbController { // If the app breaks then stop the request takeUntil(this.#unobserve) ) - .subscribe((extensions) => { - extensions.forEach((extension) => { - this.extensionRegistry.register(extension); - }); - }); + .subscribe((extensions) => this.#extensionRegistry.registerMany(extensions)); } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/packages/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/backoffice/packages/umbraco-package.ts new file mode 100644 index 0000000000..7a92b4bf38 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/packages/umbraco-package.ts @@ -0,0 +1,10 @@ +export const name = 'Umbraco.Core.PackageManagement'; +export const version = '0.0.1'; +export const extensions = [ + { + name: 'Package Management Entry Point', + alias: 'Umb.EntryPoint.PackageManagement', + type: 'entryPoint', + loader: () => import('./index'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/search/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/search/index.ts index 040b21d817..49613bb9ed 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/search/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/search/index.ts @@ -1,12 +1,8 @@ import { manifests as searchManifests } from '../search/manifests'; - -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; -import { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; +import type { UmbEntrypointOnInit } from '@umbraco-cms/backoffice/extensions-api'; export const manifests = [...searchManifests]; -const registerExtensions = (manifests: Array) => { - manifests.forEach((manifest) => umbExtensionsRegistry.register(manifest)); +export const onInit: UmbEntrypointOnInit = (_host, extensionRegistry) => { + extensionRegistry.registerMany(manifests); }; - -registerExtensions(manifests); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/search/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/backoffice/search/umbraco-package.ts new file mode 100644 index 0000000000..2efaba5d15 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/search/umbraco-package.ts @@ -0,0 +1,10 @@ +export const name = 'Umbraco.Core.Search'; +export const version = '0.0.1'; +export const extensions = [ + { + name: 'Search Entry Point', + alias: 'Umb.EntryPoint.Search', + type: 'entryPoint', + loader: () => import('./index'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/index.ts index c86644f739..90fbaf506b 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/index.ts @@ -1,3 +1,4 @@ +import { UmbThemeContext } from '../themes/theme.context'; import { manifests as settingsSectionManifests } from './section.manifests'; import { manifests as settingsMenuManifests } from './menu.manifests'; import { manifests as dashboardManifests } from './dashboards/manifests'; @@ -7,11 +8,12 @@ import { manifests as extensionManifests } from './extensions/manifests'; import { manifests as cultureManifests } from './cultures/manifests'; import { manifests as languageManifests } from './languages/manifests'; import { manifests as logviewerManifests } from './logviewer/manifests'; - -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; -import { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; - -import './data-types/components'; +import { + UmbAppLanguageContext, + UMB_APP_LANGUAGE_CONTEXT_TOKEN, +} from './languages/app-language-select/app-language.context'; +import { UmbContextProviderController } from '@umbraco-cms/backoffice/context-api'; +import type { UmbEntrypointOnInit } from '@umbraco-cms/backoffice/extensions-api'; export const manifests = [ ...settingsSectionManifests, @@ -25,8 +27,8 @@ export const manifests = [ ...relationTypeManifests, ]; -const registerExtensions = (manifests: Array) => { - manifests.forEach((manifest) => umbExtensionsRegistry.register(manifest)); +export const onInit: UmbEntrypointOnInit = (host, extensionRegistry) => { + extensionRegistry.registerMany(manifests); + new UmbContextProviderController(host, UMB_APP_LANGUAGE_CONTEXT_TOKEN, new UmbAppLanguageContext(host)); + new UmbThemeContext(host); }; - -registerExtensions(manifests); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/section.manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/section.manifests.ts index 6c45267c2b..f23e645e16 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/section.manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/section.manifests.ts @@ -19,7 +19,7 @@ const menuSectionSidebarApp: ManifestSectionSidebarAppMenuKind = { kind: 'menu', alias: 'Umb.SectionSidebarMenu.Settings', name: 'Settings Section Sidebar Menu', - weight: 100, + weight: 200, meta: { label: 'Settings', menu: 'Umb.Menu.Settings', diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/umbraco-package.ts new file mode 100644 index 0000000000..12e375af3e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/umbraco-package.ts @@ -0,0 +1,10 @@ +export const name = 'Umbraco.Core.Settings'; +export const version = '0.0.1'; +export const extensions = [ + { + name: 'Settings Entry Point', + alias: 'Umb.EntryPoint.Settings', + type: 'entryPoint', + loader: () => import('./index'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/index.ts index 758856fe7c..a04af35230 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/index.ts @@ -2,9 +2,10 @@ import { manifests as componentManifests } from './components'; import { manifests as propertyActionManifests } from './property-actions/manifests'; import { manifests as propertyEditorManifests } from './property-editors/manifests'; import { manifests as modalManifests } from './modals/manifests'; - -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; -import { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; +import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; +import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; +import { UmbContextProviderController } from '@umbraco-cms/backoffice/context-api'; +import type { UmbEntrypointOnInit } from '@umbraco-cms/backoffice/extensions-api'; export const manifests = [ ...componentManifests, @@ -13,8 +14,9 @@ export const manifests = [ ...modalManifests, ]; -const registerExtensions = (manifests: Array) => { - manifests.forEach((manifest) => umbExtensionsRegistry.register(manifest)); -}; +export const onInit: UmbEntrypointOnInit = (host, extensionRegistry) => { + extensionRegistry.registerMany(manifests); -registerExtensions(manifests); + new UmbContextProviderController(host, UMB_MODAL_CONTEXT_TOKEN, new UmbModalContext(host)); + new UmbContextProviderController(host, UMB_NOTIFICATION_CONTEXT_TOKEN, new UmbNotificationContext()); +}; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/umbraco-package.ts new file mode 100644 index 0000000000..7b77239dc3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/umbraco-package.ts @@ -0,0 +1,10 @@ +export const name = 'Umbraco.Core'; +export const version = '0.0.1'; +export const extensions = [ + { + name: 'Core Entry Point', + alias: 'Umb.EntryPoint.Core', + type: 'entryPoint', + loader: () => import('./index'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/index.ts index 27ba7af32b..05598373d2 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/index.ts @@ -1,15 +1,12 @@ import { manifests as menuManifests } from './menu.manifests'; import { manifests as templateManifests } from './templates/manifests'; import { manifests as stylesheetManifests } from './stylesheets/manifests'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; -import { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; +import type { UmbEntrypointOnInit } from '@umbraco-cms/backoffice/extensions-api'; import './components'; export const manifests = [...menuManifests, ...templateManifests, ...stylesheetManifests]; -const registerExtensions = (manifests: Array) => { - manifests.forEach((manifest) => umbExtensionsRegistry.register(manifest)); +export const onInit: UmbEntrypointOnInit = (_host, extensionRegistry) => { + extensionRegistry.registerMany(manifests); }; - -registerExtensions(manifests); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/umbraco-package.ts new file mode 100644 index 0000000000..b0ee024d06 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/umbraco-package.ts @@ -0,0 +1,10 @@ +export const name = 'Umbraco.Core.Templating'; +export const version = '0.0.1'; +export const extensions = [ + { + name: 'Templating Entry Point', + alias: 'Umb.EntryPoint.Templating', + type: 'entryPoint', + loader: () => import('./index'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/translation/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/translation/index.ts index 9d5a22448b..d6912d1aee 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/translation/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/translation/index.ts @@ -1,12 +1,9 @@ import { manifests as translationSectionManifests } from './section.manifest'; import { manifests as dictionaryManifests } from './dictionary/manifests'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; +import { UmbEntrypointOnInit } from '@umbraco-cms/backoffice/extensions-api'; export const manifests = [...translationSectionManifests, ...dictionaryManifests]; -const registerExtensions = (manifests: Array) => { - manifests.forEach((manifest) => umbExtensionsRegistry.register(manifest)); +export const onInit: UmbEntrypointOnInit = (_host, extensionRegistry) => { + extensionRegistry.registerMany(manifests); }; - -registerExtensions(manifests); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/translation/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/backoffice/translation/umbraco-package.ts new file mode 100644 index 0000000000..ff271b5e32 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/translation/umbraco-package.ts @@ -0,0 +1,10 @@ +export const name = 'Umbraco.Core.TranslationManagement'; +export const version = '0.0.1'; +export const extensions = [ + { + name: 'Translation Entry Point', + alias: 'Umb.EntryPoint.Translation', + type: 'entryPoint', + loader: () => import('./index'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/users/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/users/index.ts index dfabd9ec4c..4886cd3909 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/users/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/users/index.ts @@ -3,13 +3,23 @@ import { manifests as userManifests } from './users/manifests'; import { manifests as userSectionManifests } from './user-section/manifests'; import { manifests as currentUserManifests } from './current-user/manifests'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; -import { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; +import { UmbCurrentUserStore, UMB_CURRENT_USER_STORE_CONTEXT_TOKEN } from './current-user/current-user.store'; +import { + UmbCurrentUserHistoryStore, + UMB_CURRENT_USER_HISTORY_STORE_CONTEXT_TOKEN, +} from './current-user/current-user-history.store'; +import { UmbEntrypointOnInit } from '@umbraco-cms/backoffice/extensions-api'; +import { UmbContextProviderController } from '@umbraco-cms/backoffice/context-api'; export const manifests = [...userGroupManifests, ...userManifests, ...userSectionManifests, ...currentUserManifests]; -const registerExtensions = (manifests: Array) => { - manifests.forEach((manifest) => umbExtensionsRegistry.register(manifest)); -}; +export const onInit: UmbEntrypointOnInit = (host, extensionRegistry) => { + extensionRegistry.registerMany(manifests); -registerExtensions(manifests); + new UmbContextProviderController(host, UMB_CURRENT_USER_STORE_CONTEXT_TOKEN, new UmbCurrentUserStore()); + new UmbContextProviderController( + host, + UMB_CURRENT_USER_HISTORY_STORE_CONTEXT_TOKEN, + new UmbCurrentUserHistoryStore() + ); +}; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/users/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/backoffice/users/umbraco-package.ts new file mode 100644 index 0000000000..9c89b478c0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/users/umbraco-package.ts @@ -0,0 +1,10 @@ +export const name = 'Umbraco.Core.UserManagement'; +export const version = '0.0.1'; +export const extensions = [ + { + name: 'User Management Entry Point', + alias: 'Umb.EntryPoint.UserManagement', + type: 'entryPoint', + loader: () => import('./index'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/manifests.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/manifests.handlers.ts index 3f92603754..62d186c1c1 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/manifests.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/manifests.handlers.ts @@ -42,7 +42,7 @@ export const manifestDevelopmentHandler = rest.get(umbracoPath('/package/manifes { extensions: [ { - type: 'entrypoint', + type: 'entryPoint', name: 'My Custom Entry Point', alias: 'My.Entrypoint.Custom', js: '/App_Plugins/custom-entrypoint.js', diff --git a/src/Umbraco.Web.UI.Client/src/core/store-extension-initializer.ts b/src/Umbraco.Web.UI.Client/src/core/store-extension-initializer.ts new file mode 100644 index 0000000000..13f834652d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/store-extension-initializer.ts @@ -0,0 +1,27 @@ +import { createExtensionClass, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; +import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller'; +import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; + +export class UmbStoreExtensionInitializer { + public host: UmbControllerHostElement; + #storeMap = new Map(); + + constructor(host: UmbControllerHostElement) { + this.host = host; + + new UmbObserverController( + this.host, + umbExtensionsRegistry.extensionsOfTypes(['store', 'treeStore', 'itemStore']), + (stores) => { + if (!stores) return; + + stores.forEach((store) => { + if (this.#storeMap.has(store.alias)) return; + + // Instantiate and provide stores. Stores are self providing when the class is instantiated. + this.#storeMap.set(store.alias, createExtensionClass(store, [this.host])); + }); + } + ); + } +}