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 1074fa85c4..5ab41fbf8f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -12,7 +12,6 @@ import './components/extension-slot/extension-slot.element'; import './sections/shared/section-main/section-main.element'; import './sections/shared/section-sidebar/section-sidebar.element'; import './sections/shared/section.element'; -import './trees/shared/tree-base.element'; import './trees/shared/tree.element'; import { defineElement } from '@umbraco-ui/uui-base/lib/registration'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/manifests.ts new file mode 100644 index 0000000000..687d1e0477 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/manifests.ts @@ -0,0 +1,45 @@ +import type { ManifestTree, ManifestTreeItemAction } from '@umbraco-cms/models'; + +const treeAlias = 'Umb.Tree.DataTypes'; + +const tree: ManifestTree = { + type: 'tree', + alias: treeAlias, + name: 'Data Types Tree', + weight: 100, + meta: { + label: 'Data Types', + icon: 'umb:folder', + sections: ['Umb.Section.Settings'], + storeContextAlias: 'umbDataTypeStore', + }, +}; + +const treeItemActions: Array = [ + { + type: 'treeItemAction', + alias: 'Umb.TreeItemAction.DataType.Create', + name: 'Tree Item Action Create', + loader: () => import('./actions/create/action-data-type-create.element'), + weight: 200, + meta: { + trees: [treeAlias], + label: 'Create', + icon: 'umb:add', + }, + }, + { + type: 'treeItemAction', + alias: 'Umb.TreeItemAction.DataType.Delete', + name: 'Tree Item Action Delete', + loader: () => import('./actions/delete/action-data-type-delete.element'), + weight: 100, + meta: { + trees: [treeAlias], + label: 'Delete', + icon: 'umb:delete', + }, + }, +]; + +export const manifests = [tree, ...treeItemActions]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.element.ts deleted file mode 100644 index 30b35c231e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.element.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { html } from 'lit'; -import { customElement } from 'lit/decorators.js'; -import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; -import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; -import type { ManifestTreeItemAction } from '@umbraco-cms/models'; - -import '../shared/tree-navigator.element'; -import { UmbDataTypesStore } from 'src/core/stores/data-types/data-types.store'; - -@customElement('umb-tree-data-types') -export class UmbTreeDataTypesElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { - constructor() { - super(); - - this._registerTreeItemActions(); - - // TODO: how do we best expose the tree api to the tree navigator element? - this.consumeContext('umbDataTypeStore', (dataTypeStore: UmbDataTypesStore) => { - this.provideContext('umbTreeStore', dataTypeStore); - }); - } - - private _registerTreeItemActions() { - const dashboards: Array = [ - { - type: 'treeItemAction', - alias: 'Umb.TreeItemAction.DataType.Create', - name: 'Tree Item Action Create', - loader: () => import('./actions/create/action-data-type-create.element'), - weight: 200, - meta: { - trees: ['Umb.Tree.DataTypes'], - label: 'Create', - icon: 'umb:add', - }, - }, - { - type: 'treeItemAction', - alias: 'Umb.TreeItemAction.DataType.Delete', - name: 'Tree Item Action Delete', - loader: () => import('./actions/delete/action-data-type-delete.element'), - weight: 100, - meta: { - trees: ['Umb.Tree.DataTypes'], - label: 'Delete', - icon: 'umb:delete', - }, - }, - ]; - - dashboards.forEach((dashboard) => { - if (umbExtensionsRegistry.isRegistered(dashboard.alias)) return; - umbExtensionsRegistry.register(dashboard); - }); - } - - render() { - return html``; - } -} - -export default UmbTreeDataTypesElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-tree-data-types': UmbTreeDataTypesElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/manifests.ts new file mode 100644 index 0000000000..0c3b08cae3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/manifests.ts @@ -0,0 +1,18 @@ +import type { ManifestTree } from '@umbraco-cms/extensions-registry'; + +const treeAlias = 'Umb.Tree.DocumentTypes'; + +const tree: ManifestTree = { + type: 'tree', + alias: treeAlias, + name: 'Document Types Tree', + weight: 400, + meta: { + label: 'Document Types', + icon: 'umb:folder', + sections: ['Umb.Section.Settings'], + storeContextAlias: 'umbDocumentTypeStore', + }, +}; + +export const manifests = [tree]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.element.ts deleted file mode 100644 index 37de6c57ec..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.element.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { html } from 'lit'; -import { customElement } from 'lit/decorators.js'; -import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; - -import '../shared/tree-navigator.element'; -import { UmbDocumentTypeStore } from 'src/core/stores/document-type/document-type.store'; - -@customElement('umb-tree-document-types') -export class UmbTreeDocumentTypes extends UmbContextConsumerMixin(UmbContextProviderMixin(UmbTreeBase)) { - constructor() { - super(); - - // TODO: how do we best expose the tree api to the tree navigator element? - this.consumeContext('umbDocumentTypeStore', (store: UmbDocumentTypeStore) => { - this.provideContext('umbTreeStore', store); - }); - } - - render() { - return html``; - } -} - -export default UmbTreeDocumentTypes; - -declare global { - interface HTMLElementTagNameMap { - 'umb-tree-document-types': UmbTreeDocumentTypes; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/manifests.ts new file mode 100644 index 0000000000..61a9436b9e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/manifests.ts @@ -0,0 +1,57 @@ +import type { ManifestTree, ManifestTreeItemAction } from '@umbraco-cms/models'; + +const treeAlias = 'Umb.Tree.Documents'; + +const tree: ManifestTree = { + type: 'tree', + alias: treeAlias, + name: 'Documents Tree', + weight: 100, + meta: { + label: 'Documents', + icon: 'umb:folder', + sections: ['Umb.Section.Content'], + storeContextAlias: 'umbDocumentStore', + }, +}; + +const treeItemActions: Array = [ + { + type: 'treeItemAction', + alias: 'Umb.TreeItemAction.Document.Create', + name: 'Document Tree Item Action Create', + loader: () => import('./actions/action-document-create.element'), + weight: 100, + meta: { + trees: [treeAlias], + label: 'Create', + icon: 'add', + }, + }, + { + type: 'treeItemAction', + alias: 'Umb.TreeItemAction.Document.Delete', + name: 'Document Tree Item Action Delete', + loader: () => import('./actions/action-document-delete.element'), + weight: 100, + meta: { + trees: [treeAlias], + label: 'Delete', + icon: 'delete', + }, + }, + { + type: 'treeItemAction', + alias: 'Umb.TreeItemAction.Document.Paged', + name: 'Document Tree Item Action Paged', + loader: () => import('./actions/action-document-paged.element'), + weight: 100, + meta: { + trees: [treeAlias], + label: 'Paged', + icon: 'favorite', + }, + }, +]; + +export const manifests = [tree, ...treeItemActions]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts deleted file mode 100644 index 1f0ec6bd92..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { html } from 'lit'; -import { customElement } from 'lit/decorators.js'; -import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; -import type { ManifestTreeItemAction } from '@umbraco-cms/models'; -import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; -import { UmbDocumentStore } from 'src/core/stores/document/document.store'; - -import '../shared/tree-navigator.element'; -@customElement('umb-tree-documents') -export class UmbTreeDocumentsElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { - constructor() { - super(); - - this._registerTreeItemActions(); - - // TODO: how do we best expose the tree api to the tree navigator element? - this.consumeContext('umbDocumentStore', (store: UmbDocumentStore) => { - this.provideContext('umbTreeStore', store); - }); - } - - private _registerTreeItemActions() { - const dashboards: Array = [ - { - type: 'treeItemAction', - alias: 'Umb.TreeItemAction.Document.Create', - name: 'Document Tree Item Action Create', - loader: () => import('./actions/action-document-create.element'), - weight: 100, - meta: { - trees: ['Umb.Tree.Documents'], - label: 'Create', - icon: 'add', - }, - }, - { - type: 'treeItemAction', - alias: 'Umb.TreeItemAction.Document.Delete', - name: 'Document Tree Item Action Delete', - loader: () => import('./actions/action-document-delete.element'), - weight: 100, - meta: { - trees: ['Umb.Tree.Documents'], - label: 'Delete', - icon: 'delete', - }, - }, - { - type: 'treeItemAction', - alias: 'Umb.TreeItemAction.Document.Paged', - name: 'Document Tree Item Action Paged', - loader: () => import('./actions/action-document-paged.element'), - weight: 100, - meta: { - trees: ['Umb.Tree.Documents'], - label: 'Paged', - icon: 'favorite', - }, - }, - ]; - - dashboards.forEach((dashboard) => { - if (umbExtensionsRegistry.isRegistered(dashboard.alias)) return; - umbExtensionsRegistry.register(dashboard); - }); - } - - render() { - return html``; - } -} - -export default UmbTreeDocumentsElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-tree-documents': UmbTreeDocumentsElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/manifests.ts new file mode 100644 index 0000000000..4671ec9b04 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/manifests.ts @@ -0,0 +1,18 @@ +import { ManifestTree } from '@umbraco-cms/extensions-registry'; + +const treeAlias = 'Umb.Tree.Extensions'; + +const tree: ManifestTree = { + type: 'tree', + alias: treeAlias, + name: 'Extensions Tree', + weight: 500, + meta: { + label: 'Extensions', + icon: 'umb:favorite', + sections: ['Umb.Section.Settings'], + rootNodeEntityType: 'extension-root', // TODO: how do we want to handle 'single node trees'. Trees without any children but still needs to open an workspace? Currently an workspace is chosen based on the entity type. The tree root node doesn't have one, so we need to tell which workspace to use. + }, +}; + +export const manifests = [tree]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/languages/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/languages/manifests.ts new file mode 100644 index 0000000000..bc091d0d89 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/languages/manifests.ts @@ -0,0 +1,18 @@ +import type { ManifestTree } from '@umbraco-cms/models'; + +const treeAlias = 'Umb.Tree.Languages'; + +const tree: ManifestTree = { + type: 'tree', + alias: treeAlias, + name: 'Languages Tree', + weight: 100, + meta: { + label: 'Languages', + icon: 'umb:globe', + sections: ['Umb.Section.Settings'], + rootNodeEntityType: 'language-root', // TODO: how do we want to handle 'single node trees'. Trees without any children but still needs to open an workspace? Currently an workspace is chosen based on the entity type. The tree root node doesn't have one, so we need to tell which workspace to use. + }, +}; + +export const manifests = [tree]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts index ce68c92407..1e794d3f9c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts @@ -1,112 +1,23 @@ -import type { ManifestTree } from '@umbraco-cms/models'; +import { manifests as dataTypeTreeManifests } from './data-types/manifests'; +import { manifests as documentTypeTreeManifests } from './document-types/manifests'; +import { manifests as documentTreeManifests } from './documents/manifests'; +import { manifests as extensionTreeManifests } from './extensions/manifests'; +import { manifests as languageTreeManifests } from './languages/manifests'; +import { manifests as mediaTreeManifests } from './media/manifests'; +import { manifests as mediaTypeTreeManifests } from './media-types/manifests'; +import { manifests as memberGroupTreeManifests } from './member-groups/manifests'; +import { manifests as memberTypesTreeManifests } from './member-types/manifests'; -export const manifests: Array = [ - { - type: 'tree', - alias: 'Umb.Tree.Extensions', - name: 'Extensions Tree', - weight: 500, - meta: { - label: 'Extensions', - icon: 'umb:favorite', - sections: ['Umb.Section.Settings'], - rootNodeEntityType: 'extension-root', // TODO: how do we want to handle 'single node trees'. Trees without any children but still needs to open an workspace? Currently an workspace is chosen based on the entity type. The tree root node doesn't have one, so we need to tell which workspace to use. - }, - }, - { - type: 'tree', - alias: 'Umb.Tree.DocumentTypes', - name: 'Document Types Tree', - loader: () => import('./document-types/tree-document-types.element'), - weight: 400, - meta: { - label: 'Document Types', - icon: 'umb:folder', - sections: ['Umb.Section.Settings'], - }, - }, - { - type: 'tree', - alias: 'Umb.Tree.MediaTypes', - name: 'Media Types Tree', - loader: () => import('./media-types/tree-media-types.element'), - weight: 300, - meta: { - label: 'Media Types', - icon: 'umb:folder', - sections: ['Umb.Section.Settings'], - }, - }, - { - type: 'tree', - alias: 'Umb.Tree.MemberTypes', - name: 'Member Types Tree', - loader: () => import('./member-types/tree-member-types.element'), - weight: 200, - meta: { - label: 'Member Types', - icon: 'umb:folder', - sections: ['Umb.Section.Settings'], - }, - }, - { - type: 'tree', - alias: 'Umb.Tree.DataTypes', - name: 'Data Types Tree', - loader: () => import('./data-types/tree-data-types.element'), - weight: 100, - meta: { - label: 'Data Types', - icon: 'umb:folder', - sections: ['Umb.Section.Settings'], - }, - }, - { - type: 'tree', - alias: 'Umb.Tree.MemberGroups', - name: 'Member Groups Tree', - loader: () => import('./member-groups/tree-member-groups.element'), - weight: 1, - meta: { - label: 'Member Groups', - icon: 'umb:folder', - sections: ['Umb.Section.Members'], - }, - }, - { - type: 'tree', - alias: 'Umb.Tree.Media', - name: 'Media Tree', - loader: () => import('./media/tree-media.element'), - weight: 100, - meta: { - label: 'Media', - icon: 'umb:folder', - sections: ['Umb.Section.Media'], - }, - }, - { - type: 'tree', - alias: 'Umb.Tree.Documents', - name: 'Documents Tree', - loader: () => import('./documents/tree-documents.element'), - weight: 100, - meta: { - label: 'Documents', - icon: 'umb:folder', - sections: ['Umb.Section.Content'], - }, - }, - { - type: 'tree', - alias: 'Umb.Tree.Languages', - name: 'Languages Tree', - weight: 100, - meta: { - label: 'Languages', - icon: 'umb:globe', - sections: ['Umb.Section.Settings'], - rootNodeEntityType: 'language-root', // TODO: how do we want to handle 'single node trees'. Trees without any children but still needs to open an workspace? Currently an workspace is chosen based on the entity type. The tree root node doesn't have one, so we need to tell which workspace to use. - }, - }, +import type { ManifestTree, ManifestTreeItemAction } from '@umbraco-cms/models'; + +export const manifests: Array = [ + ...dataTypeTreeManifests, + ...documentTypeTreeManifests, + ...documentTreeManifests, + ...extensionTreeManifests, + ...languageTreeManifests, + ...mediaTreeManifests, + ...mediaTypeTreeManifests, + ...memberGroupTreeManifests, + ...memberTypesTreeManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media-types/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media-types/manifests.ts new file mode 100644 index 0000000000..5e1e7630b3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media-types/manifests.ts @@ -0,0 +1,20 @@ +import type { ManifestTree, ManifestTreeItemAction } from '@umbraco-cms/models'; + +const treeAlias = 'Umb.Tree.MemberTypes'; + +const tree: ManifestTree = { + type: 'tree', + alias: treeAlias, + name: 'Member Types Tree', + weight: 200, + meta: { + label: 'Member Types', + icon: 'umb:folder', + sections: ['Umb.Section.Settings'], + storeContextAlias: 'umbMemberTypeStore', + }, +}; + +const treeItemActions: Array = []; + +export const manifests = [tree, ...treeItemActions]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media-types/tree-media-types.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media-types/tree-media-types.element.ts deleted file mode 100644 index 38487fc0be..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media-types/tree-media-types.element.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { html } from 'lit'; -import { customElement } from 'lit/decorators.js'; -import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; -import { UmbMediaTypeStore } from 'src/core/stores/media-type/media-type.store'; - -import '../shared/tree-navigator.element'; - -@customElement('umb-tree-media-types') -export class UmbTreeMediaTypes extends UmbContextConsumerMixin(UmbContextProviderMixin(UmbTreeBase)) { - constructor() { - super(); - - // TODO: how do we best expose the tree api to the tree navigator element? - this.consumeContext('umbMediaTypeStore', (store: UmbMediaTypeStore) => { - this.provideContext('umbTreeStore', store); - }); - } - - render() { - return html``; - } -} - -export default UmbTreeMediaTypes; - -declare global { - interface HTMLElementTagNameMap { - 'umb-tree-media-types': UmbTreeMediaTypes; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/manifests.ts new file mode 100644 index 0000000000..78bae1f6bb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/manifests.ts @@ -0,0 +1,20 @@ +import type { ManifestTree, ManifestTreeItemAction } from '@umbraco-cms/models'; + +const treeAlias = 'Umb.Tree.Media'; + +const tree: ManifestTree = { + type: 'tree', + alias: treeAlias, + name: 'Media Tree', + weight: 100, + meta: { + label: 'Media', + icon: 'umb:folder', + sections: ['Umb.Section.Media'], + storeContextAlias: 'umbMediaStore', + }, +}; + +const treeItemActions: Array = []; + +export const manifests = [tree, ...treeItemActions]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.element.ts deleted file mode 100644 index 79f0ed7230..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.element.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { html } from 'lit'; -import { customElement } from 'lit/decorators.js'; -import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; -import { UmbMediaStore } from 'src/core/stores/media/media.store'; - -import '../shared/tree-navigator.element'; - -@customElement('umb-tree-media') -export class UmbTreeMediaElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { - constructor() { - super(); - - // TODO: how do we best expose the tree api to the tree navigator element? - this.consumeContext('umbMediaStore', (store: UmbMediaStore) => { - this.provideContext('umbTreeStore', store); - }); - } - - render() { - return html``; - } -} - -export default UmbTreeMediaElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-tree-media': UmbTreeMediaElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/manifests.ts new file mode 100644 index 0000000000..6a2c0086f6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/manifests.ts @@ -0,0 +1,20 @@ +import type { ManifestTree, ManifestTreeItemAction } from '@umbraco-cms/models'; + +const treeAlias = 'Umb.Tree.MemberGroups'; + +const tree: ManifestTree = { + type: 'tree', + alias: treeAlias, + name: 'Member Groups Tree', + weight: 1, + meta: { + label: 'Member Groups', + icon: 'umb:folder', + sections: ['Umb.Section.Members'], + storeContextAlias: 'umbMemberGroupStore', + }, +}; + +const treeItemActions: Array = []; + +export const manifests = [tree, ...treeItemActions]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.element.ts deleted file mode 100644 index 54dfe6ed5d..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.element.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { html } from 'lit'; -import { customElement } from 'lit/decorators.js'; -import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; -import { UmbMemberGroupStore } from 'src/core/stores/member-group/member-group.store'; -import '../shared/tree-navigator.element'; - -@customElement('umb-tree-member-groups') -export class UmbTreeMemberGroups extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { - constructor() { - super(); - - // TODO: how do we best expose the tree api to the tree navigator element? - this.consumeContext('umbMemberGroupStore', (store: UmbMemberGroupStore) => { - this.provideContext('umbTreeStore', store); - }); - } - - render() { - return html``; - } -} - -export default UmbTreeMemberGroups; - -declare global { - interface HTMLElementTagNameMap { - 'umb-tree-member-groups': UmbTreeMemberGroups; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-types/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-types/manifests.ts new file mode 100644 index 0000000000..5e1e7630b3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-types/manifests.ts @@ -0,0 +1,20 @@ +import type { ManifestTree, ManifestTreeItemAction } from '@umbraco-cms/models'; + +const treeAlias = 'Umb.Tree.MemberTypes'; + +const tree: ManifestTree = { + type: 'tree', + alias: treeAlias, + name: 'Member Types Tree', + weight: 200, + meta: { + label: 'Member Types', + icon: 'umb:folder', + sections: ['Umb.Section.Settings'], + storeContextAlias: 'umbMemberTypeStore', + }, +}; + +const treeItemActions: Array = []; + +export const manifests = [tree, ...treeItemActions]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-types/tree-member-types.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-types/tree-member-types.element.ts deleted file mode 100644 index 7feb2b3a8d..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-types/tree-member-types.element.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { html } from 'lit'; -import { customElement } from 'lit/decorators.js'; -import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; -import { UmbMemberTypeStore } from 'src/core/stores/member-type/member-type.store'; - -import '../shared/tree-navigator.element'; - -@customElement('umb-tree-member-types') -export class UmbTreeMemberTypes extends UmbContextConsumerMixin(UmbContextProviderMixin(UmbTreeBase)) { - constructor() { - super(); - - // TODO: how do we best expose the tree api to the tree navigator element? - this.consumeContext('umbMemberTypeStore', (store: UmbMemberTypeStore) => { - this.provideContext('umbTreeStore', store); - }); - } - - render() { - return html``; - } -} - -export default UmbTreeMemberTypes; - -declare global { - interface HTMLElementTagNameMap { - 'umb-tree-member-types': UmbTreeMemberTypes; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts deleted file mode 100644 index 366b11e608..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { LitElement } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; -import type { ManifestTree } from '@umbraco-cms/models'; - -@customElement('umb-tree-base') -export class UmbTreeBase extends LitElement { - @property({ type: Object, attribute: false }) - tree?: ManifestTree; -} - -declare global { - interface HTMLElementTagNameMap { - 'umb-tree-base': UmbTreeBase; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-extension.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-extension.element.ts index 6495b11e93..3b3416b4be 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-extension.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-extension.element.ts @@ -4,6 +4,7 @@ import { customElement, property, state } from 'lit/decorators.js'; import { createExtensionElement } from '@umbraco-cms/extensions-api'; import type { ManifestTree } from '@umbraco-cms/models'; +import './tree-navigator.element'; import './context-menu/tree-context-menu-page-action-list.element'; import './context-menu/tree-context-menu-page.service'; import './context-menu/tree-context-menu.service'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts index 045a57cb34..6387f07d1c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts @@ -39,7 +39,7 @@ export class UmbTreeItem extends UmbContextConsumerMixin(UmbObserverMixin(LitEle private _isActive = false; private _treeContext?: UmbTreeContextBase; - private _treeStore?: UmbDataStore; + private _store?: UmbDataStore; private _sectionContext?: UmbSectionContext; private _treeContextMenuService?: UmbTreeContextMenuService; @@ -52,8 +52,8 @@ export class UmbTreeItem extends UmbContextConsumerMixin(UmbObserverMixin(LitEle this._observeIsSelected(); }); - this.consumeContext('umbTreeStore', (store: UmbDataStore) => { - this._treeStore = store; + this.consumeContext('umbStore', (store: UmbDataStore) => { + this._store = store; }); this.consumeContext('umbSectionContext', (sectionContext: UmbSectionContext) => { @@ -131,11 +131,11 @@ export class UmbTreeItem extends UmbContextConsumerMixin(UmbObserverMixin(LitEle } private _observeChildren() { - if (!this._treeStore?.getTreeItemChildren) return; + if (!this._store?.getTreeItemChildren) return; this._loading = true; - this.observe(this._treeStore.getTreeItemChildren(this.treeItem.key), (childItems) => { + this.observe(this._store.getTreeItemChildren(this.treeItem.key), (childItems) => { if (childItems?.length === 0) return; this._childItems = childItems; this._loading = false; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts index 3da760a192..dab153e4e1 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts @@ -1,22 +1,32 @@ import { css, html, LitElement } from 'lit'; import { repeat } from 'lit/directives/repeat.js'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, state } from 'lit/decorators.js'; +import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit-html/directives/if-defined.js'; import { UmbSectionContext } from '../../sections/section.context'; import { UmbTreeContext } from '../tree.context'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; -import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import type { Entity, ManifestSection, ManifestTree } from '@umbraco-cms/models'; import { UmbDataStore } from 'src/core/stores/store'; import './tree-item.element'; -import { UmbDocumentTypeStore } from '@umbraco-cms/stores/document-type/document-type.store'; @customElement('umb-tree-navigator') -export class UmbTreeNavigator extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { +export class UmbTreeNavigator extends UmbContextConsumerMixin(UmbContextProviderMixin(UmbObserverMixin(LitElement))) { static styles = [UUITextStyles, css``]; + private _storeContextAlias = ''; + @property({ attribute: 'store-context-alias' }) + public get storeContextAlias() { + return this._storeContextAlias; + } + + public set storeContextAlias(value) { + this._storeContextAlias = value; + this._provideStoreContext(); + } + @state() private _loading = true; @@ -29,14 +39,14 @@ export class UmbTreeNavigator extends UmbContextConsumerMixin(UmbObserverMixin(L @state() private _href?: string; - private _treeStore?: UmbDataStore; + private _store?: UmbDataStore; private _sectionContext?: UmbSectionContext; constructor() { super(); - this.consumeContext('umbTreeStore', (treeStore) => { - this._treeStore = treeStore; + this.consumeContext('umbStore', (store) => { + this._store = store; }); this.consumeContext('umbTreeContext', (treeContext: UmbTreeContext) => { @@ -49,16 +59,25 @@ export class UmbTreeNavigator extends UmbContextConsumerMixin(UmbObserverMixin(L }); } + private _provideStoreContext() { + if (!this._storeContextAlias) return; + + this.consumeContext(this._storeContextAlias, (store) => { + this._store = store; + this.provideContext('umbStore', store); + }); + } + private _onShowRoot() { this._observeTreeRoot(); } private _observeTreeRoot() { - if (!this._treeStore?.getTreeRoot) return; + if (!this._store?.getTreeRoot) return; this._loading = true; - this.observe(this._treeStore.getTreeRoot(), (rootItems) => { + this.observe(this._store.getTreeRoot(), (rootItems) => { if (rootItems?.length === 0) return; this._items = rootItems; this._loading = false; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree.element.ts index 45e8ffcff1..97ef443bc0 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree.element.ts @@ -7,6 +7,7 @@ import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import type { ManifestTree } from '@umbraco-cms/models'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; +import { UmbDataStore } from '@umbraco-cms/stores/store'; @customElement('umb-tree') export class UmbTreeElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbObserverMixin(LitElement))) { @@ -68,8 +69,14 @@ export class UmbTreeElement extends UmbContextProviderMixin(UmbContextConsumerMi .extensionsOfType('tree') .pipe(map((trees) => trees.find((tree) => tree.alias === this.alias))), (tree) => { + if (this._tree?.alias === tree.alias) return; + this._tree = tree; this._provideTreeContext(); + + if (this._tree.meta.storeContextAlias) { + this._provideStore(); + } } ); } @@ -84,6 +91,14 @@ export class UmbTreeElement extends UmbContextProviderMixin(UmbContextConsumerMi this.provideContext('umbTreeContext', this._treeContext); } + private _provideStore() { + if (!this._tree?.meta.storeContextAlias) return; + + this.consumeContext(this._tree.meta.storeContextAlias, (store: UmbDataStore) => + this.provideContext('umbStore', store) + ); + } + private _observeSelection() { if (!this._treeContext) return; diff --git a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/tree.models.ts b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/tree.models.ts index 5795dcd3ff..52c4ef5413 100644 --- a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/tree.models.ts +++ b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/tree.models.ts @@ -10,4 +10,5 @@ export interface MetaTree { icon: string; sections: Array; rootNodeEntityType?: string; + storeContextAlias?: string; } diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.element.ts index 5f7ba6148e..1051bf71a8 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.element.ts @@ -8,7 +8,6 @@ export interface UmbModalContentPickerData { selection: Array; } -import '../../../../../backoffice/trees/documents/tree-documents.element'; import { UmbTreeElement } from '../../../../../backoffice/trees/shared/tree.element'; // TODO: make use of UmbPickerLayoutBase