From 109156306b08921cde379eb4ff1c439485382691 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 14 Mar 2023 09:54:45 +0100 Subject: [PATCH 001/114] init --- .../document-type-workspace.element.ts | 16 +- .../document-types/workspace/manifests.ts | 41 ++++- ...space-view-document-type-design.element.ts | 140 +++++++++++++++++- ...-view-document-type-permissions.element.ts | 61 ++++++++ 4 files changed, 245 insertions(+), 13 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/document-type-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/document-type-workspace.element.ts index 5e5a660c77..e2b78bd80a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/document-type-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/document-type-workspace.element.ts @@ -15,9 +15,6 @@ export class UmbDocumentTypeWorkspaceElement extends UmbLitElement implements Um UUITextStyles, css` :host { - display: block; - width: 100%; - height: 100%; } #header { @@ -110,7 +107,18 @@ export class UmbDocumentTypeWorkspaceElement extends UmbLitElement implements Um -
Keyboard Shortcuts
+
+ + Keyboard Shortcuts + + ALT + + + shift + + + k + + +
`; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/manifests.ts index 114efb3e7e..c1b374e2fa 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/manifests.ts @@ -22,7 +22,46 @@ const workspaceViews: Array = [ workspaces: ['Umb.Workspace.DocumentType'], label: 'Design', pathname: 'design', - icon: 'edit', + icon: 'umb:document-dashed-line', + }, + }, + { + type: 'workspaceView', + alias: 'Umb.WorkspaceView.DocumentType.ListView', + name: 'Document Type Workspace Permissions ListView', + loader: () => import('./views/permissions/workspace-view-document-type-permissions.element'), + weight: 100, + meta: { + workspaces: ['Umb.Workspace.DocumentType'], + label: 'List View', + pathname: 'listview', + icon: 'umb:list', + }, + }, + { + type: 'workspaceView', + alias: 'Umb.WorkspaceView.DocumentType.Permissions', + name: 'Document Type Workspace Permissions View', + loader: () => import('./views/permissions/workspace-view-document-type-permissions.element'), + weight: 100, + meta: { + workspaces: ['Umb.Workspace.DocumentType'], + label: 'Permissions', + pathname: 'permissions', + icon: 'umb:keychain', + }, + }, + { + type: 'workspaceView', + alias: 'Umb.WorkspaceView.DocumentType.Templates', + name: 'Document Type Workspace Permissions View', + loader: () => import('./views/permissions/workspace-view-document-type-permissions.element'), + weight: 100, + meta: { + workspaces: ['Umb.Workspace.DocumentType'], + label: 'Templates', + pathname: 'templates', + icon: 'umb:layout', }, }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts index 3e48456f2d..4ecb16f4f3 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts @@ -1,6 +1,8 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, state } from 'lit/decorators.js'; +import { customElement, query, state } from 'lit/decorators.js'; +import { UUIInputElement, UUIInputEvent } from '@umbraco-ui/uui'; +import { repeat } from 'lit/directives/repeat.js'; import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; import { UmbLitElement } from '@umbraco-cms/element'; import type { DocumentTypeModel } from '@umbraco-cms/backend-api'; @@ -13,8 +15,66 @@ export class UmbWorkspaceViewDocumentTypeDesignElement extends UmbLitElement { css` :host { display: block; - margin: var(--uui-size-space-6); - padding: var(--uui-size-space-6); + } + + /** Tab group */ + + #workspace-tab-bar { + padding: 0 var(--uui-size-layout-1); + display: flex; + align-items: center; + justify-content: space-between; + background-color: var(--uui-color-surface); + flex-wrap: nowrap; + } + .tab-actions { + display: flex; + gap: var(--uui-size-space-4); + } + .tab-actions uui-button uui-icon { + padding-right: calc(-1 * var(--uui-size-space-4)); + } + + uui-tab { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + } + + uui-tab .trash { + display: flex; + align-items: stretch; + } + + uui-tab uui-input { + flex-grow: 1; + } + + uui-input:not(:focus) { + border: 1px solid transparent; + } + + uui-input:not(:hover, :focus) .trash { + opacity: 0; + } + + /** Property Group Wrapper */ + + #wrapper { + margin: var(--uui-size-layout-1); + } + + #add-group { + margin-top: var(--uui-size-layout-1); + width: 100%; + } + + .group-headline { + display: flex; + gap: var(--uui-size-space-4); + } + .group-headline uui-input { + flex-grow: 1; } `, ]; @@ -24,6 +84,12 @@ export class UmbWorkspaceViewDocumentTypeDesignElement extends UmbLitElement { private _workspaceContext?: UmbWorkspaceDocumentTypeContext; + @state() + private _tabs: any[] = []; + + @query('uui-tab-group') + private _tabgroup?: HTMLElement; + constructor() { super(); @@ -43,12 +109,70 @@ export class UmbWorkspaceViewDocumentTypeDesignElement extends UmbLitElement { } render() { - return html` Design of ${this._documentType?.name} - -
- + //this._documentType?.name + return html` +
+ ${this.renderTabBar()} +
+ + + Compositions + + + + Recorder +
- `; +
+
+ +
+ + +
+ +
+ Add group +
+ `; + } + + #remove(index: number) { + this._tabs.splice(index, 1); + this.requestUpdate(); + } + async #addTab() { + this._tabs = [...this._tabs, { name: 'Test' }]; + } + + renderTabBar() { + return html` + ${repeat( + this._tabs, + (tab) => tab.name, + (tab, index) => { + //TODO: Should these tabs be part of routing? + return html` +
+ + + + + +
+
`; + } + )} + + + Add tab + +
`; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts new file mode 100644 index 0000000000..5e9b13ddea --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts @@ -0,0 +1,61 @@ +import { css, html } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, state } from 'lit/decorators.js'; +import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; +import { UmbLitElement } from '@umbraco-cms/element'; +import type { DocumentTypeModel } from '@umbraco-cms/backend-api'; +import '../../../../../shared/property-creator/property-creator.element.ts'; + +@customElement('umb-workspace-view-document-type-permissions') +export class UmbWorkspaceViewDocumentTypePermissionsElement extends UmbLitElement { + static styles = [ + UUITextStyles, + css` + :host { + display: block; + margin: var(--uui-size-space-6); + padding: var(--uui-size-space-6); + } + `, + ]; + + @state() + _documentType?: DocumentTypeModel; + + private _workspaceContext?: UmbWorkspaceDocumentTypeContext; + + constructor() { + super(); + + // TODO: Figure out if this is the best way to consume the context or if it can be strongly typed with an UmbContextToken + this.consumeContext('umbWorkspaceContext', (documentTypeContext) => { + this._workspaceContext = documentTypeContext; + this._observeDocumentType(); + }); + } + + private _observeDocumentType() { + if (!this._workspaceContext) return; + + this.observe(this._workspaceContext.data, (documentType) => { + this._documentType = documentType; + }); + } + + render() { + return html` Permissions of ${this._documentType?.name} + +
+ +
+
`; + } +} + +export default UmbWorkspaceViewDocumentTypePermissionsElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-workspace-view-document-type-permissions': UmbWorkspaceViewDocumentTypePermissionsElement; + } +} From 21ad34ee09689ac2e5dd7e75197b71eeac3821d0 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Wed, 15 Mar 2023 14:51:43 +0100 Subject: [PATCH 002/114] template cards --- .../template-card-list.element.ts | 109 ++++++++++++ .../template-cards/template-card.element.ts | 168 ++++++++++++++++++ .../template-cards/template-card.stories.ts | 40 +++++ 3 files changed, 317 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card-list.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.stories.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card-list.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card-list.element.ts new file mode 100644 index 0000000000..784586eefb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card-list.element.ts @@ -0,0 +1,109 @@ +import { css, html } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property } from 'lit/decorators.js'; +import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; +import { repeat } from 'lit/directives/repeat.js'; +import { UmbLitElement } from '@umbraco-cms/element'; +import './template-card.element'; +import UmbTemplateCardElement from './template-card.element'; + +export interface TemplateModel { + name: string; + key: string; +} + +@customElement('umb-template-card-list') +export class UmbTemplateCardListElement extends FormControlMixin(UmbLitElement) { + static styles = [ + UUITextStyles, + css` + :host { + box-sizing: border-box; + display: flex; + align-items: stretch; + gap: var(--uui-size-space-4); + min-height: 180px; + } + `, + ]; + + @property({ type: Array }) + templates: TemplateModel[] = [ + { + name: 'Named template', + key: '123', + }, + { + name: 'Named template 2', + key: '456', + }, + ]; + + private _selected?: number; + + private _templateCardElements: UmbTemplateCardElement[] = []; + + protected getFormElement() { + return undefined; + } + + #changeSelectedState(e: UmbTemplateCardElement) { + const newValue = e.value; + this._templateCardElements.forEach((el, index) => { + if ((el.value as string) === newValue) { + el.selected = true; + this._selected = index; + } else { + el.selected = false; + } + }); + this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true })); + } + + #delete(e: Event) { + const key = (e.target as UmbTemplateCardElement).value; + const i = this.templates.findIndex((x) => x.key === key); + this.templates.splice(i, 1); + this.templates = [...this.templates]; + } + + #openTemplate(e: Event) { + console.log(e.target); + const key = (e.target as UmbTemplateCardElement).value; + console.log('open', key); + } + + #openTemplatePicker() { + console.log('template picker'); + } + + #slotchange(e: Event) { + this._templateCardElements.forEach((el) => { + el.removeEventListener('selected', (e) => this.#changeSelectedState(e.target as UmbTemplateCardElement)); + el.removeEventListener('open', (e) => this.#openTemplate(e)); + }); + + this._templateCardElements = (e.target as HTMLSlotElement) + .assignedElements({ flatten: true }) + .filter((el) => el instanceof UmbTemplateCardElement) as UmbTemplateCardElement[]; + + if (this._templateCardElements.length === 0) return; + + this._templateCardElements.forEach((el) => { + el.addEventListener('selected', (e) => this.#changeSelectedState(e.target as UmbTemplateCardElement)); + el.addEventListener('open', (e) => this.#openTemplate(e)); + }); + } + + render() { + return html` `; + } +} + +export default UmbTemplateCardListElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-template-card-list': UmbTemplateCardListElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.element.ts new file mode 100644 index 0000000000..7015da267f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.element.ts @@ -0,0 +1,168 @@ +import { css, html } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property } from 'lit/decorators.js'; +import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; +import { UmbLitElement } from '@umbraco-cms/element'; + +/** + * @element umb-template-card + * @description wrap inside a umb-template-card-list + * @slot actions + * @fires open + * @fires selected + * + * + */ + +@customElement('umb-template-card') +export class UmbTemplateCardElement extends FormControlMixin(UmbLitElement) { + static styles = [ + UUITextStyles, + css` + :host { + box-sizing: border-box; + display: contents; + position: relative; + + height: 100%; + border: 1px solid red; + margin: auto; + } + + #card { + box-sizing: border-box; + width: 100%; + max-width: 180px; + //width: 200px; + position: relative; + display: flex; + flex-direction: column; + align-items: stretch; + border-radius: var(--uui-border-radius); + border: 1px solid var(--uui-color-divider-emphasis); + background-color: var(--uui-color-background); + padding: var(--uui-size-space-4); + } + + :host([selected]) #card { + border: 1px solid var(--uui-color-selected); + outline: 1px solid var(--uui-color-selected); + } + + #bottom { + margin-top: auto; + } + + slot[name='actions'] { + position: absolute; + top: var(--uui-size-4); + right: var(--uui-size-4); + display: flex; + justify-content: right; + + opacity: 0; + transition: opacity 120ms; + } + + :host(:focus) slot[name='actions'], + :host(:focus-within) slot[name='actions'], + :host(:hover) slot[name='actions'] { + opacity: 1; + } + + #open-part { + border: none; + outline: none; + background: none; + text-align: center; + display: flex; + flex-direction: column; + font-weight: 700; + align-items: center; + cursor: pointer; + flex-grow: 1; + } + + #open-part, + #card { + gap: var(--uui-size-space-2); + } + + #open-part strong { + flex-grow: 1; + display: flex; + align-items: center; + } + + :host([disabled]) #open-part { + pointer-events: none; + } + + #open-part:focus-visible, + #open-part:focus-visible uui-icon, + #open-part:hover, + #open-part:hover uui-icon { + text-decoration: underline; + color: var(--uui-color-interactive-emphasis); + } + + #open-part uui-icon { + font-size: var(--uui-size-20); + color: var(--uui-color-divider-emphasis); + } + `, + ]; + + @property({ type: String }) + name = ''; + + @property({ type: Boolean, reflect: true }) + selected = false; + + _key = ''; + @property({ type: String }) + public set key(newKey: string) { + this._key = newKey; + super.value = newKey; + } + public get key() { + return this._key; + } + + protected getFormElement() { + return undefined; + } + + #setSelection(e: KeyboardEvent) { + e.preventDefault(); + e.stopPropagation(); + //this.selected = true; + this.dispatchEvent(new CustomEvent('selected', { bubbles: true, composed: true })); + } + #openTemplate(e: KeyboardEvent) { + e.preventDefault(); + e.stopPropagation(); + this.dispatchEvent(new CustomEvent('open', { bubbles: true, composed: true })); + } + + render() { + return html`
+ + + + ${this.selected ? '(Default template)' : 'Set default'} + +
`; + } +} + +export default UmbTemplateCardElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-template-card': UmbTemplateCardElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.stories.ts new file mode 100644 index 0000000000..464e9bc44b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.stories.ts @@ -0,0 +1,40 @@ +import { Meta, StoryObj } from '@storybook/web-components'; +import { html } from 'lit'; +import './template-card.element'; +import type { UmbTemplateCardElement } from './template-card.element'; + +const meta: Meta = { + title: 'Components/Template Card', + component: 'umb-template-card', +}; + +export default meta; +type Story = StoryObj; + +export const Overview: Story = { + args: { + name: 'Template with a name ', + }, +}; + +export const Default: Story = { + args: { + name: 'Just a template', + }, +}; + +export const LongName: Story = { + args: { + name: 'Another template that someone gave a way way too long name without really thinking twice about it', + }, +}; + +export const TemplateCardList: Story = { + render: () => html`
+ + + + +
`, +}; From 5d1623cecd37957253218763006e9c927e28ed59 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Wed, 15 Mar 2023 14:52:04 +0100 Subject: [PATCH 003/114] tabs --- .../document-types/workspace/manifests.ts | 4 +- ...ace-view-document-type-listview.element.ts | 49 +++++++++++ ...-view-document-type-permissions.element.ts | 55 ++++++++++-- ...ce-view-document-type-templates.element.ts | 86 +++++++++++++++++++ .../src/backoffice/shared/components/index.ts | 4 + 5 files changed, 188 insertions(+), 10 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/manifests.ts index c1b374e2fa..16ee325068 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/manifests.ts @@ -29,7 +29,7 @@ const workspaceViews: Array = [ type: 'workspaceView', alias: 'Umb.WorkspaceView.DocumentType.ListView', name: 'Document Type Workspace Permissions ListView', - loader: () => import('./views/permissions/workspace-view-document-type-permissions.element'), + loader: () => import('./views/listview/workspace-view-document-type-listview.element'), weight: 100, meta: { workspaces: ['Umb.Workspace.DocumentType'], @@ -55,7 +55,7 @@ const workspaceViews: Array = [ type: 'workspaceView', alias: 'Umb.WorkspaceView.DocumentType.Templates', name: 'Document Type Workspace Permissions View', - loader: () => import('./views/permissions/workspace-view-document-type-permissions.element'), + loader: () => import('./views/templates/workspace-view-document-type-templates.element'), weight: 100, meta: { workspaces: ['Umb.Workspace.DocumentType'], diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts new file mode 100644 index 0000000000..31221d76b2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts @@ -0,0 +1,49 @@ +import { css, html } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, query, state } from 'lit/decorators.js'; +import { repeat } from 'lit/directives/repeat.js'; +import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; +import { UmbLitElement } from '@umbraco-cms/element'; +import type { DocumentTypeModel } from '@umbraco-cms/backend-api'; +import '../../../../../shared/property-creator/property-creator.element.ts'; + +@customElement('umb-workspace-view-document-type-listview') +export class UmbWorkspaceViewDocumentTypeListviewElement extends UmbLitElement { + static styles = [UUITextStyles, css``]; + + @state() + _documentType?: DocumentTypeModel; + + private _workspaceContext?: UmbWorkspaceDocumentTypeContext; + + constructor() { + super(); + + // TODO: Figure out if this is the best way to consume the context or if it can be strongly typed with an UmbContextToken + this.consumeContext('umbWorkspaceContext', (documentTypeContext) => { + this._workspaceContext = documentTypeContext; + this._observeDocumentType(); + }); + } + + private _observeDocumentType() { + if (!this._workspaceContext) return; + + this.observe(this._workspaceContext.data, (documentType) => { + this._documentType = documentType; + }); + } + + render() { + //this._documentType?.name + return html` Listview `; + } +} + +export default UmbWorkspaceViewDocumentTypeListviewElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-workspace-view-document-type-listview': UmbWorkspaceViewDocumentTypeListviewElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts index 5e9b13ddea..c01cf2038d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts @@ -13,8 +13,15 @@ export class UmbWorkspaceViewDocumentTypePermissionsElement extends UmbLitElemen css` :host { display: block; - margin: var(--uui-size-space-6); - padding: var(--uui-size-space-6); + margin: var(--uui-size-layout-1); + } + uui-label, + umb-property-editor-ui-number { + display: block; + } + + uui-toggle { + display: flex; } `, ]; @@ -43,12 +50,44 @@ export class UmbWorkspaceViewDocumentTypePermissionsElement extends UmbLitElemen } render() { - return html` Permissions of ${this._documentType?.name} - -
- -
-
`; + return html` + + +
Allow editors to create content of this type in the root of the content tree.
+
+
+ +
+ Allow content of the specified types to be created underneath content of this type. +
+
+ +
+
+ +
Allow editors to create content of different languages.
+
+
+ +
+ An Element Type is meant to be used for instance in Nested Content, and not in the tree.
+ A Document Type cannot be changed to an Element Type once it has been used to create one or more content + items. +
+
+
+ +
Allow overriding the global history cleanup settings.
+
+ + Keep all versions newer than days + + Keep latest version per day for days + +
+
+
+ `; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts new file mode 100644 index 0000000000..56e6a2cf47 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts @@ -0,0 +1,86 @@ +import { css, html } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, query, state } from 'lit/decorators.js'; +import { repeat } from 'lit/directives/repeat.js'; +import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; +import { UmbLitElement } from '@umbraco-cms/element'; +import type { DocumentTypeModel } from '@umbraco-cms/backend-api'; +import '../../../../../shared/property-creator/property-creator.element.ts'; + +@customElement('umb-workspace-view-document-type-templates') +export class UmbWorkspaceViewDocumentTypeTemplatesElement extends UmbLitElement { + static styles = [ + UUITextStyles, + css` + :host { + display: block; + margin: var(--uui-size-layout-1); + } + + #templates { + text-align: center; + } + + #template-card-wrapper { + display: flex; + gap: var(--uui-size-space-4); + align-items: stretch; + } + + umb-workspace-property-layout { + border-top: 1px solid var(--uui-color-border); + } + umb-workspace-property-layout:first-child { + padding-top: 0; + border: none; + } + `, + ]; + + @state() + _documentType?: DocumentTypeModel; + + private _workspaceContext?: UmbWorkspaceDocumentTypeContext; + + constructor() { + super(); + + // TODO: Figure out if this is the best way to consume the context or if it can be strongly typed with an UmbContextToken + this.consumeContext('umbWorkspaceContext', (documentTypeContext) => { + this._workspaceContext = documentTypeContext; + this._observeDocumentType(); + }); + } + + private _observeDocumentType() { + if (!this._workspaceContext) return; + + this.observe(this._workspaceContext.data, (documentType) => { + this._documentType = documentType; + }); + } + + render() { + return html` + +
Choose which templates editors are allowed to use on content of this type
+
+ + + + + +
+
+ +
`; + } +} + +export default UmbWorkspaceViewDocumentTypeTemplatesElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-workspace-view-document-type-templates': UmbWorkspaceViewDocumentTypeTemplatesElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts index 04c03284f7..c7b94c2d90 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts @@ -21,6 +21,7 @@ import './input-checkbox-list/input-checkbox-list.element'; import './input-color-picker/input-color-picker.element'; import './input-culture-select/input-culture-select.element'; import './input-document-picker/input-document-picker.element'; +import './input-document-type-picker/input-document-type-picker.element'; import './input-eye-dropper/input-eye-dropper.element'; import './input-language-picker/input-language-picker.element'; import './input-media-picker/input-media-picker.element'; @@ -46,4 +47,7 @@ import './workspace/workspace-layout/workspace-layout.element'; import './workspace/workspace-footer-layout/workspace-footer-layout.element'; +import './template-cards/template-card.element'; +import './template-cards/template-card-list.element'; + export const manifests = [...debugManifests]; From fc24e6c0d3f8f94901467c19f4a429ebc129c110 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Wed, 15 Mar 2023 14:52:09 +0100 Subject: [PATCH 004/114] picker --- .../input-document-type-picker.element.ts | 182 ++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts new file mode 100644 index 0000000000..96dd248079 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts @@ -0,0 +1,182 @@ +import { css, html, nothing } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property, state } from 'lit/decorators.js'; +import { ifDefined } from 'lit-html/directives/if-defined.js'; +import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; +import { UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN } from '../../../documents/documents/repository/document.tree.store'; +import { UmbDocumentTypeTreeStore } from '../../../documents/document-types/repository/document-type.tree.store'; +import { UMB_CONFIRM_MODAL_TOKEN } from '../../modals/confirm'; +import { UMB_DOCUMENT_PICKER_MODAL_TOKEN } from '../../../documents/documents/modals/document-picker'; +import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/modal'; +import { UmbLitElement } from '@umbraco-cms/element'; +import type { DocumentTypeTreeItemModel, FolderTreeItemModel } from '@umbraco-cms/backend-api'; +import type { UmbObserverController } from '@umbraco-cms/observable-api'; + +@customElement('umb-input-document-type-picker') +export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitElement) { + static styles = [ + UUITextStyles, + css` + #add-button { + width: 100%; + } + `, + ]; + /** + * This is a minimum amount of selected items in this input. + * @type {number} + * @attr + * @default undefined + */ + @property({ type: Number }) + min?: number; + + /** + * Min validation message. + * @type {boolean} + * @attr + * @default + */ + @property({ type: String, attribute: 'min-message' }) + minMessage = 'This field need more items'; + + /** + * This is a maximum amount of selected items in this input. + * @type {number} + * @attr + * @default undefined + */ + @property({ type: Number }) + max?: number; + + /** + * Max validation message. + * @type {boolean} + * @attr + * @default + */ + @property({ type: String, attribute: 'min-message' }) + maxMessage = 'This field exceeds the allowed amount of items'; + + // TODO: do we need both selectedKeys and value? If we just use value we follow the same pattern as native form controls. + private _selectedKeys: Array = []; + public get selectedKeys(): Array { + return this._selectedKeys; + } + public set selectedKeys(keys: Array) { + this._selectedKeys = keys; + super.value = keys.join(','); + this._observePickedDocuments(); + } + + @property() + public set value(keysString: string) { + if (keysString !== this._value) { + this.selectedKeys = keysString.split(/[ ,]+/); + } + } + + @state() + private _items?: Array; + + private _modalContext?: UmbModalContext; + private _documentStore?: UmbDocumentTypeTreeStore; + private _pickedItemsObserver?: UmbObserverController; + + constructor() { + super(); + + this.addValidator( + 'rangeUnderflow', + () => this.minMessage, + () => !!this.min && this._selectedKeys.length < this.min + ); + this.addValidator( + 'rangeOverflow', + () => this.maxMessage, + () => !!this.max && this._selectedKeys.length > this.max + ); + + this.consumeContext(UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN, (instance) => { + this._documentStore = instance; + this._observePickedDocuments(); + }); + this.consumeContext(UMB_MODAL_CONTEXT_TOKEN, (instance) => { + this._modalContext = instance; + }); + } + + protected getFormElement() { + return undefined; + } + + private _observePickedDocuments() { + this._pickedItemsObserver?.destroy(); + + if (!this._documentStore) return; + + // TODO: consider changing this to the list data endpoint when it is available + this._pickedItemsObserver = this.observe(this._documentStore.items(this._selectedKeys), (items) => { + this._items = items; + }); + } + + private _openPicker() { + // We send a shallow copy(good enough as its just an array of keys) of our this._selectedKeys, as we don't want the modal to manipulate our data: + const modalHandler = this._modalContext?.open(UMB_DOCUMENT_PICKER_MODAL_TOKEN, { + multiple: this.max === 1 ? false : true, + selection: [...this._selectedKeys], + }); + + modalHandler?.onSubmit().then(({ selection }: any) => { + this._setSelection(selection); + }); + } + + private async _removeItem(item: FolderTreeItemModel) { + const modalHandler = this._modalContext?.open(UMB_CONFIRM_MODAL_TOKEN, { + color: 'danger', + headline: `Remove ${item.name}?`, + content: 'Are you sure you want to remove this item', + confirmLabel: 'Remove', + }); + + await modalHandler?.onSubmit(); + const newSelection = this._selectedKeys.filter((value) => value !== item.key); + this._setSelection(newSelection); + } + + private _setSelection(newSelection: Array) { + this.selectedKeys = newSelection; + this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true })); + } + + render() { + return html` + ${this._items?.map((item) => this._renderItem(item))} + Add + `; + } + + private _renderItem(item: FolderTreeItemModel) { + // TODO: remove when we have a way to handle trashed items + const tempItem = item as FolderTreeItemModel & { isTrashed: boolean }; + + return html` + + ${tempItem.isTrashed ? html` Trashed ` : nothing} + + this._removeItem(item)} label="Remove document ${item.name}">Remove + + + `; + } +} + +export default UmbInputDocumentTypePickerElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-input-document-type-picker': UmbInputDocumentTypePickerElement; + } +} From 50efb4158480842147eb3f0db88ab01acdf840af Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Wed, 22 Mar 2023 10:31:06 +0100 Subject: [PATCH 005/114] workspaces --- ...-view-document-type-permissions.element.ts | 3 +- ...ce-view-document-type-templates.element.ts | 29 ++- .../document-type-picker-modal.element.ts | 103 +++++++++ .../document-type-picker-modal.stories.ts | 26 +++ .../modals/document-type-picker/index.ts | 18 ++ .../documents/documents/modals/manifests.ts | 6 + .../src/backoffice/shared/components/index.ts | 5 +- .../input-document-type-picker.element.ts | 92 +++----- .../input-template-picker.element.ts | 211 ++++++++++++++++++ .../template-card-list.element.ts | 1 + .../template-card.element.ts | 15 +- .../template-card.stories.ts | 0 12 files changed, 432 insertions(+), 77 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.stories.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts rename src/Umbraco.Web.UI.Client/src/backoffice/shared/components/{template-cards => template-card}/template-card-list.element.ts (99%) rename src/Umbraco.Web.UI.Client/src/backoffice/shared/components/{template-cards => template-card}/template-card.element.ts (90%) rename src/Umbraco.Web.UI.Client/src/backoffice/shared/components/{template-cards => template-card}/template-card.stories.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts index c01cf2038d..f15ede2561 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts @@ -61,7 +61,8 @@ export class UmbWorkspaceViewDocumentTypePermissionsElement extends UmbLitElemen Allow content of the specified types to be created underneath content of this type.
- +
diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts index 56e6a2cf47..361d8a7ecb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts @@ -1,8 +1,8 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, query, state } from 'lit/decorators.js'; -import { repeat } from 'lit/directives/repeat.js'; +import { customElement, property, state } from 'lit/decorators.js'; import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; +import { UmbTemplateCardListElement } from '../../../../../shared/components/template-card/template-card-list.element'; import { UmbLitElement } from '@umbraco-cms/element'; import type { DocumentTypeModel } from '@umbraco-cms/backend-api'; import '../../../../../shared/property-creator/property-creator.element.ts'; @@ -37,9 +37,18 @@ export class UmbWorkspaceViewDocumentTypeTemplatesElement extends UmbLitElement `, ]; + @property() + defaultTemplateKey?: string = '123'; + @state() _documentType?: DocumentTypeModel; + @state() + _templates = [ + { key: '123', name: 'Blog Post Page' }, + { key: '456', name: 'Blog Entry Page' }, + ]; + private _workspaceContext?: UmbWorkspaceDocumentTypeContext; constructor() { @@ -60,17 +69,21 @@ export class UmbWorkspaceViewDocumentTypeTemplatesElement extends UmbLitElement }); } + #changeDefaultTemplate(e: CustomEvent) { + this.defaultTemplateKey = (e.target as UmbTemplateCardListElement).value as string; + console.log('default template key', this.defaultTemplateKey); + } + + #removeTemplate(key: string) { + console.log('remove template', key); + } + render() { return html`
Choose which templates editors are allowed to use on content of this type
- - - - - -
+
`; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.element.ts new file mode 100644 index 0000000000..1854ccf003 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.element.ts @@ -0,0 +1,103 @@ +import { css, html } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, state } from 'lit/decorators.js'; +import type { UmbTreeElement } from '../../../../shared/components/tree/tree.element'; +import { UmbDocumentTypePickerModalData, UmbDocumentTypePickerModalResult } from '.'; +import { UmbModalBaseElement } from '@umbraco-cms/modal'; + +// TODO: make use of UmbPickerLayoutBase +@customElement('umb-document-type-picker-modal') +export class UmbDocumentTypePickerModalElement extends UmbModalBaseElement< + UmbDocumentTypePickerModalData, + UmbDocumentTypePickerModalResult +> { + static styles = [ + UUITextStyles, + css` + h3 { + margin-left: var(--uui-size-space-5); + margin-right: var(--uui-size-space-5); + } + + uui-input { + width: 100%; + } + + hr { + border: none; + border-bottom: 1px solid var(--uui-color-divider); + margin: 16px 0; + } + + #content-list { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-3); + } + + .content-item { + cursor: pointer; + } + + .content-item.selected { + background-color: var(--uui-color-selected); + color: var(--uui-color-selected-contrast); + } + `, + ]; + + @state() + _selection: Array = []; + + @state() + _multiple = true; + + connectedCallback() { + super.connectedCallback(); + this._selection = this.data?.selection ?? []; + this._multiple = this.data?.multiple ?? true; + } + + private _handleSelectionChange(e: CustomEvent) { + e.stopPropagation(); + const element = e.target as UmbTreeElement; + //TODO: Should multiple property be implemented here or be passed down into umb-tree? + this._selection = this._multiple ? element.selection : [element.selection[element.selection.length - 1]]; + } + + private _submit() { + this.modalHandler?.submit({ selection: this._selection }); + } + + private _close() { + this.modalHandler?.reject(); + } + + render() { + return html` + + + +
+ +
+
+ + +
+
+ `; + } +} + +export default UmbDocumentTypePickerModalElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-document-type-picker-modal': UmbDocumentTypePickerModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.stories.ts new file mode 100644 index 0000000000..fead1b4ac9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.stories.ts @@ -0,0 +1,26 @@ +import '../../../../shared/components/body-layout/body-layout.element'; +import './document-type-picker-modal.element'; + +import { Meta, Story } from '@storybook/web-components'; +import { html } from 'lit'; + +import type { UmbDocumentTypePickerModalElement } from './document-type-picker-modal.element'; +import type { UmbDocumentTypePickerModalData } from './index'; + +export default { + title: 'API/Modals/Layouts/Content Picker', + component: 'umb-document-picker-modal', + id: 'umb-document-picker-modal', +} as Meta; + +const data: UmbDocumentTypePickerModalData = { + multiple: true, + selection: [], +}; + +export const Overview: Story = () => html` + + +`; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/index.ts new file mode 100644 index 0000000000..c7e6efe767 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/index.ts @@ -0,0 +1,18 @@ +import { UmbModalToken } from '@umbraco-cms/modal'; + +export interface UmbDocumentTypePickerModalData { + multiple?: boolean; + selection?: Array; +} + +export interface UmbDocumentTypePickerModalResult { + selection: Array; +} + +export const UMB_DOCUMENT_TYPE_PICKER_MODAL_TOKEN = new UmbModalToken< + UmbDocumentTypePickerModalData, + UmbDocumentTypePickerModalResult +>('Umb.Modal.DocumentTypePicker', { + type: 'sidebar', + size: 'small', +}); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/manifests.ts index dcaf83f082..693b20895f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/manifests.ts @@ -7,6 +7,12 @@ const modals: Array = [ name: 'Document Picker Modal', loader: () => import('./document-picker/document-picker-modal.element'), }, + { + type: 'modal', + alias: 'Umb.Modal.DocumentTypePicker', + name: 'Document Type Picker Modal', + loader: () => import('./document-type-picker/document-type-picker-modal.element'), + }, ]; export const manifests = [...modals]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts index c7b94c2d90..1eb453e684 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts @@ -28,6 +28,7 @@ import './input-media-picker/input-media-picker.element'; import './input-multi-url-picker/input-multi-url-picker.element'; import './input-slider/input-slider.element'; import './input-toggle/input-toggle.element'; +import './input-template-picker/input-template-picker.element'; import './property-type-based-property/property-type-based-property.element'; import './ref-property-editor-ui/ref-property-editor-ui.element'; import './section/section-main/section-main.element'; @@ -47,7 +48,7 @@ import './workspace/workspace-layout/workspace-layout.element'; import './workspace/workspace-footer-layout/workspace-footer-layout.element'; -import './template-cards/template-card.element'; -import './template-cards/template-card-list.element'; +import './template-card/template-card.element'; +import './template-card/template-card-list.element'; export const manifests = [...debugManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts index 96dd248079..029db1e806 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts @@ -3,13 +3,15 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit-html/directives/if-defined.js'; import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; -import { UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN } from '../../../documents/documents/repository/document.tree.store'; -import { UmbDocumentTypeTreeStore } from '../../../documents/document-types/repository/document-type.tree.store'; +import { + UmbDocumentTypeTreeStore, + UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN, +} from '../../../documents/document-types/repository/document-type.tree.store'; import { UMB_CONFIRM_MODAL_TOKEN } from '../../modals/confirm'; -import { UMB_DOCUMENT_PICKER_MODAL_TOKEN } from '../../../documents/documents/modals/document-picker'; +import { UMB_DOCUMENT_TYPE_PICKER_MODAL_TOKEN } from '../../../documents/documents/modals/document-type-picker'; import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/modal'; import { UmbLitElement } from '@umbraco-cms/element'; -import type { DocumentTypeTreeItemModel, FolderTreeItemModel } from '@umbraco-cms/backend-api'; +import type { DocumentTypeModel, DocumentTypeTreeItemModel, FolderTreeItemModel } from '@umbraco-cms/backend-api'; import type { UmbObserverController } from '@umbraco-cms/observable-api'; @customElement('umb-input-document-type-picker') @@ -20,43 +22,16 @@ export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitEl #add-button { width: 100%; } + + #current-node { + background-color: var(--uui-color-surface-alt); + } + + #wrapper-nodes { + margin-left: var(--uui-size-space-6); + } `, ]; - /** - * This is a minimum amount of selected items in this input. - * @type {number} - * @attr - * @default undefined - */ - @property({ type: Number }) - min?: number; - - /** - * Min validation message. - * @type {boolean} - * @attr - * @default - */ - @property({ type: String, attribute: 'min-message' }) - minMessage = 'This field need more items'; - - /** - * This is a maximum amount of selected items in this input. - * @type {number} - * @attr - * @default undefined - */ - @property({ type: Number }) - max?: number; - - /** - * Max validation message. - * @type {boolean} - * @attr - * @default - */ - @property({ type: String, attribute: 'min-message' }) - maxMessage = 'This field exceeds the allowed amount of items'; // TODO: do we need both selectedKeys and value? If we just use value we follow the same pattern as native form controls. private _selectedKeys: Array = []; @@ -76,29 +51,20 @@ export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitEl } } + @property() + currentDocumentType?: DocumentTypeModel; + @state() private _items?: Array; private _modalContext?: UmbModalContext; - private _documentStore?: UmbDocumentTypeTreeStore; + private _documentTypeStore?: UmbDocumentTypeTreeStore; private _pickedItemsObserver?: UmbObserverController; constructor() { super(); - - this.addValidator( - 'rangeUnderflow', - () => this.minMessage, - () => !!this.min && this._selectedKeys.length < this.min - ); - this.addValidator( - 'rangeOverflow', - () => this.maxMessage, - () => !!this.max && this._selectedKeys.length > this.max - ); - - this.consumeContext(UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN, (instance) => { - this._documentStore = instance; + this.consumeContext(UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN, (instance) => { + this._documentTypeStore = instance; this._observePickedDocuments(); }); this.consumeContext(UMB_MODAL_CONTEXT_TOKEN, (instance) => { @@ -113,18 +79,18 @@ export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitEl private _observePickedDocuments() { this._pickedItemsObserver?.destroy(); - if (!this._documentStore) return; + if (!this._documentTypeStore) return; // TODO: consider changing this to the list data endpoint when it is available - this._pickedItemsObserver = this.observe(this._documentStore.items(this._selectedKeys), (items) => { + this._pickedItemsObserver = this.observe(this._documentTypeStore.items(this._selectedKeys), (items) => { this._items = items; }); } private _openPicker() { // We send a shallow copy(good enough as its just an array of keys) of our this._selectedKeys, as we don't want the modal to manipulate our data: - const modalHandler = this._modalContext?.open(UMB_DOCUMENT_PICKER_MODAL_TOKEN, { - multiple: this.max === 1 ? false : true, + const modalHandler = this._modalContext?.open(UMB_DOCUMENT_TYPE_PICKER_MODAL_TOKEN, { + multiple: true, selection: [...this._selectedKeys], }); @@ -153,8 +119,13 @@ export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitEl render() { return html` - ${this._items?.map((item) => this._renderItem(item))} - Add + + + +
+ ${this._items?.map((item) => this._renderItem(item))} + Add +
`; } @@ -164,6 +135,7 @@ export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitEl return html` + ${tempItem.isTrashed ? html` Trashed ` : nothing} this._removeItem(item)} label="Remove document ${item.name}">Remove diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts new file mode 100644 index 0000000000..f73d13ff09 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts @@ -0,0 +1,211 @@ +import { css, html } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property, queryAll, state } from 'lit/decorators.js'; +import { repeat } from 'lit/directives/repeat.js'; +import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; +import { UMB_CONFIRM_MODAL_TOKEN } from '../../modals/confirm'; +import { UmbTemplateCardElement } from '../template-card/template-card.element'; +import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/modal'; +import { UmbLitElement } from '@umbraco-cms/element'; +import { TemplateModel, TemplateResource } from '@umbraco-cms/backend-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/resources'; + +type DocTypTemplateModel = TemplateModel & { default: boolean }; + +@customElement('umb-input-template-picker') +export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElement) { + static styles = [ + UUITextStyles, + css` + #add-button { + width: 100%; + } + :host { + box-sizing: border-box; + display: flex; + gap: var(--uui-size-space-4); + flex-wrap: wrap; + } + + :host > * { + max-width: 180px; + min-width: 180px; + min-height: 150px; + } + + .fade-in { + animation: fadeIn 1s; + } + + @keyframes fadeIn { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } + } + `, + ]; + /** + * This is a minimum amount of selected items in this input. + * @type {number} + * @attr + * @default undefined + */ + @property({ type: Number }) + min?: number; + + /** + * Min validation message. + * @type {boolean} + * @attr + * @default + */ + @property({ type: String, attribute: 'min-message' }) + minMessage = 'This field need more items'; + + /** + * This is a maximum amount of selected items in this input. + * @type {number} + * @attr + * @default undefined + */ + @property({ type: Number }) + max?: number; + + /** + * Max validation message. + * @type {boolean} + * @attr + * @default + */ + @property({ type: String, attribute: 'min-message' }) + maxMessage = 'This field exceeds the allowed amount of items'; + + private _templates: Array = []; + public get templates(): Array { + return this._templates; + } + public set templates(newTemplates: Array) { + const keys = newTemplates.map((template) => template.key); + super.value = keys.join(','); + this._templates = newTemplates; + } + + @state() + private _items: Array = [ + { key: '2bf464b6-3aca-4388-b043-4eb439cc2643', name: 'Doc 1', default: false }, + { key: '9a84c0b3-03b4-4dd4-84ac-706740ac0f71', name: 'Test', default: true }, + ]; + + private _modalContext?: UmbModalContext; + //private _documentStore?: UmbDocumentTreeStore; + //private _pickedItemsObserver?: UmbObserverController; + + @queryAll('.template-card') + private _templateCardElements?: NodeListOf; + + constructor() { + super(); + + this.addValidator( + 'rangeUnderflow', + () => this.minMessage, + () => !!this.min && this._templates.length < this.min + ); + this.addValidator( + 'rangeOverflow', + () => this.maxMessage, + () => !!this.max && this._templates.length > this.max + ); + + this.consumeContext(UMB_MODAL_CONTEXT_TOKEN, (instance) => { + this._modalContext = instance; + }); + } + + connectedCallback(): void { + super.connectedCallback(); + this._items = this._items.sort((a, b) => b.default - a.default); + this.#setup(); + } + + async #setup() { + const templates = await tryExecuteAndNotify(this, TemplateResource.getTreeTemplateRoot({ skip: 0, take: 9999 })); + console.log(templates); + } + + protected getFormElement() { + return undefined; + } + + #openTemplatePickerModal() { + console.log('template picker modal'); + } + + #changeSelected() { + console.log('selected'); + } + + /** Clicking the template card buttons */ + + #changeDefault(e: CustomEvent) { + const key = (e.target as UmbTemplateCardElement).value; + + const oldDefault = this._items.find((x) => x.default === true); + const newDefault = this._items.find((x) => x.key === key); + + const items = this._items.map((item) => { + if (item.default === true) return { ...newDefault, default: true }; + if (item.key === key) return { ...oldDefault, default: false }; + return item; + }); + + this._items = items; + } + + #openTemplate(e: CustomEvent) { + const key = (e.target as UmbTemplateCardElement).value; + console.log('open', key); + } + + #removeTemplate(key: string) { + console.log('remove', key); + } + + render() { + return html` + ${repeat( + this._items, + (template) => template.default, + (template, index) => html`
+ + + + + +
` + )} + Add + `; + } +} + +export default UmbInputTemplatePickerElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-input-template-picker': UmbInputTemplatePickerElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card-list.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card-list.element.ts similarity index 99% rename from src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card-list.element.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card-list.element.ts index 784586eefb..a886ac8012 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card-list.element.ts @@ -57,6 +57,7 @@ export class UmbTemplateCardListElement extends FormControlMixin(UmbLitElement) el.selected = false; } }); + this.value = newValue; this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true })); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.element.ts similarity index 90% rename from src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.element.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.element.ts index 7015da267f..cbe43a0648 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.element.ts @@ -41,13 +41,16 @@ export class UmbTemplateCardElement extends FormControlMixin(UmbLitElement) { border-radius: var(--uui-border-radius); border: 1px solid var(--uui-color-divider-emphasis); background-color: var(--uui-color-background); - padding: var(--uui-size-space-4); + padding: var(--uui-size-4); } - :host([selected]) #card { + :host([default]) #card { border: 1px solid var(--uui-color-selected); outline: 1px solid var(--uui-color-selected); } + #card:has(uui-button:hover) { + border: 1px solid var(--uui-color-selected); + } #bottom { margin-top: auto; @@ -117,7 +120,7 @@ export class UmbTemplateCardElement extends FormControlMixin(UmbLitElement) { name = ''; @property({ type: Boolean, reflect: true }) - selected = false; + default = false; _key = ''; @property({ type: String }) @@ -137,7 +140,7 @@ export class UmbTemplateCardElement extends FormControlMixin(UmbLitElement) { e.preventDefault(); e.stopPropagation(); //this.selected = true; - this.dispatchEvent(new CustomEvent('selected', { bubbles: true, composed: true })); + this.dispatchEvent(new CustomEvent('default-change', { bubbles: true, composed: true })); } #openTemplate(e: KeyboardEvent) { e.preventDefault(); @@ -152,8 +155,8 @@ export class UmbTemplateCardElement extends FormControlMixin(UmbLitElement) { ${this.name.length ? this.name : 'Untitled template'} - - ${this.selected ? '(Default template)' : 'Set default'} + + ${this.default ? '(Default template)' : 'Set default'} `; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.stories.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-cards/template-card.stories.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.stories.ts From 2da9f57c04f2c8bbb4a6f56e868517fd1b480410 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Wed, 22 Mar 2023 10:50:05 +0100 Subject: [PATCH 006/114] fix breaking changes --- ...ce-view-document-type-templates.element.ts | 10 +- .../document-type-picker-modal.element.ts | 2 +- .../modals/document-type-picker/index.ts | 2 +- .../src/backoffice/shared/components/index.ts | 1 - .../input-document-type-picker.element.ts | 20 ++-- .../input-template-picker.element.ts | 28 ++--- .../template-card-list.element.ts | 110 ------------------ .../template-card/template-card.element.ts | 3 +- .../src/core/mocks/browser.ts | 2 +- 9 files changed, 26 insertions(+), 152 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card-list.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts index 361d8a7ecb..99fbdacaa7 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts @@ -1,10 +1,10 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, state } from 'lit/decorators.js'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; -import { UmbTemplateCardListElement } from '../../../../../shared/components/template-card/template-card-list.element'; -import { UmbLitElement } from '@umbraco-cms/element'; -import type { DocumentTypeModel } from '@umbraco-cms/backend-api'; + import '../../../../../shared/property-creator/property-creator.element.ts'; @customElement('umb-workspace-view-document-type-templates') @@ -41,7 +41,7 @@ export class UmbWorkspaceViewDocumentTypeTemplatesElement extends UmbLitElement defaultTemplateKey?: string = '123'; @state() - _documentType?: DocumentTypeModel; + _documentType?: DocumentTypeResponseModel; @state() _templates = [ @@ -70,7 +70,7 @@ export class UmbWorkspaceViewDocumentTypeTemplatesElement extends UmbLitElement } #changeDefaultTemplate(e: CustomEvent) { - this.defaultTemplateKey = (e.target as UmbTemplateCardListElement).value as string; + //this.defaultTemplateKey = (e.target as UmbTemplateCardElement).value as string; console.log('default template key', this.defaultTemplateKey); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.element.ts index 1854ccf003..ee3540f564 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.element.ts @@ -1,9 +1,9 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, state } from 'lit/decorators.js'; +import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; import type { UmbTreeElement } from '../../../../shared/components/tree/tree.element'; import { UmbDocumentTypePickerModalData, UmbDocumentTypePickerModalResult } from '.'; -import { UmbModalBaseElement } from '@umbraco-cms/modal'; // TODO: make use of UmbPickerLayoutBase @customElement('umb-document-type-picker-modal') diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/index.ts index c7e6efe767..8c7834fd28 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/index.ts @@ -1,4 +1,4 @@ -import { UmbModalToken } from '@umbraco-cms/modal'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbDocumentTypePickerModalData { multiple?: boolean; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts index b5f81dd933..56b4dddf34 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts @@ -51,6 +51,5 @@ import './workspace/workspace-layout/workspace-layout.element'; import './workspace/workspace-footer-layout/workspace-footer-layout.element'; import './template-card/template-card.element'; -import './template-card/template-card-list.element'; export const manifests = [...debugManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts index 029db1e806..6eb5872571 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts @@ -3,16 +3,16 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit-html/directives/if-defined.js'; import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { DocumentTypeResponseModel, EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; +import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; import { UmbDocumentTypeTreeStore, UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN, } from '../../../documents/document-types/repository/document-type.tree.store'; import { UMB_CONFIRM_MODAL_TOKEN } from '../../modals/confirm'; import { UMB_DOCUMENT_TYPE_PICKER_MODAL_TOKEN } from '../../../documents/documents/modals/document-type-picker'; -import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/modal'; -import { UmbLitElement } from '@umbraco-cms/element'; -import type { DocumentTypeModel, DocumentTypeTreeItemModel, FolderTreeItemModel } from '@umbraco-cms/backend-api'; -import type { UmbObserverController } from '@umbraco-cms/observable-api'; @customElement('umb-input-document-type-picker') export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitElement) { @@ -52,14 +52,14 @@ export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitEl } @property() - currentDocumentType?: DocumentTypeModel; + currentDocumentType?: DocumentTypeResponseModel; @state() - private _items?: Array; + private _items?: Array; private _modalContext?: UmbModalContext; private _documentTypeStore?: UmbDocumentTypeTreeStore; - private _pickedItemsObserver?: UmbObserverController; + private _pickedItemsObserver?: UmbObserverController; constructor() { super(); @@ -99,7 +99,7 @@ export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitEl }); } - private async _removeItem(item: FolderTreeItemModel) { + private async _removeItem(item: EntityTreeItemResponseModel) { const modalHandler = this._modalContext?.open(UMB_CONFIRM_MODAL_TOKEN, { color: 'danger', headline: `Remove ${item.name}?`, @@ -129,9 +129,9 @@ export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitEl `; } - private _renderItem(item: FolderTreeItemModel) { + private _renderItem(item: EntityTreeItemResponseModel) { // TODO: remove when we have a way to handle trashed items - const tempItem = item as FolderTreeItemModel & { isTrashed: boolean }; + const tempItem = item as EntityTreeItemResponseModel & { isTrashed: boolean }; return html` diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts index f73d13ff09..8311ae6099 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts @@ -3,14 +3,13 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, queryAll, state } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; + +import { TemplateResource } from '@umbraco-cms/backoffice/backend-api'; import { UMB_CONFIRM_MODAL_TOKEN } from '../../modals/confirm'; import { UmbTemplateCardElement } from '../template-card/template-card.element'; -import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/modal'; -import { UmbLitElement } from '@umbraco-cms/element'; -import { TemplateModel, TemplateResource } from '@umbraco-cms/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/resources'; - -type DocTypTemplateModel = TemplateModel & { default: boolean }; @customElement('umb-input-template-picker') export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElement) { @@ -83,16 +82,6 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen @property({ type: String, attribute: 'min-message' }) maxMessage = 'This field exceeds the allowed amount of items'; - private _templates: Array = []; - public get templates(): Array { - return this._templates; - } - public set templates(newTemplates: Array) { - const keys = newTemplates.map((template) => template.key); - super.value = keys.join(','); - this._templates = newTemplates; - } - @state() private _items: Array = [ { key: '2bf464b6-3aca-4388-b043-4eb439cc2643', name: 'Doc 1', default: false }, @@ -103,21 +92,18 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen //private _documentStore?: UmbDocumentTreeStore; //private _pickedItemsObserver?: UmbObserverController; - @queryAll('.template-card') - private _templateCardElements?: NodeListOf; - constructor() { super(); this.addValidator( 'rangeUnderflow', () => this.minMessage, - () => !!this.min && this._templates.length < this.min + () => !!this.min && this._items.length < this.min ); this.addValidator( 'rangeOverflow', () => this.maxMessage, - () => !!this.max && this._templates.length > this.max + () => !!this.max && this._items.length > this.max ); this.consumeContext(UMB_MODAL_CONTEXT_TOKEN, (instance) => { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card-list.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card-list.element.ts deleted file mode 100644 index a886ac8012..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card-list.element.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { css, html } from 'lit'; -import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, property } from 'lit/decorators.js'; -import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; -import { repeat } from 'lit/directives/repeat.js'; -import { UmbLitElement } from '@umbraco-cms/element'; -import './template-card.element'; -import UmbTemplateCardElement from './template-card.element'; - -export interface TemplateModel { - name: string; - key: string; -} - -@customElement('umb-template-card-list') -export class UmbTemplateCardListElement extends FormControlMixin(UmbLitElement) { - static styles = [ - UUITextStyles, - css` - :host { - box-sizing: border-box; - display: flex; - align-items: stretch; - gap: var(--uui-size-space-4); - min-height: 180px; - } - `, - ]; - - @property({ type: Array }) - templates: TemplateModel[] = [ - { - name: 'Named template', - key: '123', - }, - { - name: 'Named template 2', - key: '456', - }, - ]; - - private _selected?: number; - - private _templateCardElements: UmbTemplateCardElement[] = []; - - protected getFormElement() { - return undefined; - } - - #changeSelectedState(e: UmbTemplateCardElement) { - const newValue = e.value; - this._templateCardElements.forEach((el, index) => { - if ((el.value as string) === newValue) { - el.selected = true; - this._selected = index; - } else { - el.selected = false; - } - }); - this.value = newValue; - this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true })); - } - - #delete(e: Event) { - const key = (e.target as UmbTemplateCardElement).value; - const i = this.templates.findIndex((x) => x.key === key); - this.templates.splice(i, 1); - this.templates = [...this.templates]; - } - - #openTemplate(e: Event) { - console.log(e.target); - const key = (e.target as UmbTemplateCardElement).value; - console.log('open', key); - } - - #openTemplatePicker() { - console.log('template picker'); - } - - #slotchange(e: Event) { - this._templateCardElements.forEach((el) => { - el.removeEventListener('selected', (e) => this.#changeSelectedState(e.target as UmbTemplateCardElement)); - el.removeEventListener('open', (e) => this.#openTemplate(e)); - }); - - this._templateCardElements = (e.target as HTMLSlotElement) - .assignedElements({ flatten: true }) - .filter((el) => el instanceof UmbTemplateCardElement) as UmbTemplateCardElement[]; - - if (this._templateCardElements.length === 0) return; - - this._templateCardElements.forEach((el) => { - el.addEventListener('selected', (e) => this.#changeSelectedState(e.target as UmbTemplateCardElement)); - el.addEventListener('open', (e) => this.#openTemplate(e)); - }); - } - - render() { - return html` `; - } -} - -export default UmbTemplateCardListElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-template-card-list': UmbTemplateCardListElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.element.ts index cbe43a0648..c971f22dbb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.element.ts @@ -2,11 +2,10 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property } from 'lit/decorators.js'; import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; -import { UmbLitElement } from '@umbraco-cms/element'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; /** * @element umb-template-card - * @description wrap inside a umb-template-card-list * @slot actions * @fires open * @fires selected diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/browser.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/browser.ts index 980b6cbecf..030c9bd69a 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/browser.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/browser.ts @@ -1,6 +1,6 @@ import { MockedRequest, setupWorker } from 'msw'; -import { handlers } from './browser-handlers'; import { umbracoPath } from '@umbraco-cms/backoffice/utils'; +import { handlers } from './browser-handlers'; const worker = setupWorker(...handlers); From 1f78421699a87bb3cb40bf9b1b0f67ee93e32826 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Wed, 22 Mar 2023 11:05:27 +0100 Subject: [PATCH 007/114] more breaking changes fixes --- .../document-type-workspace-edit.element.ts | 13 ++++++++++++- .../document-types/workspace/manifests.ts | 18 ++++++++++++------ ...kspace-view-document-type-design.element.ts | 1 - ...pace-view-document-type-listview.element.ts | 11 +++++------ ...e-view-document-type-permissions.element.ts | 7 ++++--- 5 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/document-type-workspace-edit.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/document-type-workspace-edit.element.ts index 57d9095924..099a206e97 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/document-type-workspace-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/document-type-workspace-edit.element.ts @@ -106,7 +106,18 @@ export class UmbDocumentTypeWorkspaceEditElement extends UmbLitElement { -
Keyboard Shortcuts
+
+ + Keyboard Shortcuts + + ALT + + + shift + + + k + + +
`; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/manifests.ts index 4547fe7f3e..8854d3a53a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/manifests.ts @@ -27,19 +27,24 @@ const workspaceViews: Array = [ pathname: 'design', icon: 'umb:document-dashed-line', }, + conditions: { + workspaces: ['Umb.Workspace.DocumentType'], + }, }, { type: 'workspaceView', alias: 'Umb.WorkspaceView.DocumentType.ListView', - name: 'Document Type Workspace Permissions ListView', + name: 'Document Type Workspace List View', loader: () => import('./views/listview/workspace-view-document-type-listview.element'), weight: 100, meta: { - workspaces: ['Umb.Workspace.DocumentType'], - label: 'List View', + label: 'Listview', pathname: 'listview', icon: 'umb:list', }, + conditions: { + workspaces: ['Umb.Workspace.DocumentType'], + }, }, { type: 'workspaceView', @@ -48,20 +53,21 @@ const workspaceViews: Array = [ loader: () => import('./views/permissions/workspace-view-document-type-permissions.element'), weight: 100, meta: { - workspaces: ['Umb.Workspace.DocumentType'], label: 'Permissions', pathname: 'permissions', icon: 'umb:keychain', }, + conditions: { + workspaces: ['Umb.Workspace.DocumentType'], + }, }, { type: 'workspaceView', alias: 'Umb.WorkspaceView.DocumentType.Templates', - name: 'Document Type Workspace Permissions View', + name: 'Document Type Workspace Templates View', loader: () => import('./views/templates/workspace-view-document-type-templates.element'), weight: 100, meta: { - workspaces: ['Umb.Workspace.DocumentType'], label: 'Templates', pathname: 'templates', icon: 'umb:layout', diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts index c794b66b8c..2b50b0310e 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts @@ -14,7 +14,6 @@ export class UmbWorkspaceViewDocumentTypeDesignElement extends UmbLitElement { css` :host { display: block; - margin: var(--uui-size-layout-1); } #workspace-tab-bar { padding: 0 var(--uui-size-layout-1); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts index 31221d76b2..d5449abd95 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts @@ -1,18 +1,17 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, query, state } from 'lit/decorators.js'; -import { repeat } from 'lit/directives/repeat.js'; -import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; -import { UmbLitElement } from '@umbraco-cms/element'; -import type { DocumentTypeModel } from '@umbraco-cms/backend-api'; +import { customElement, state } from 'lit/decorators.js'; +import type { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; import '../../../../../shared/property-creator/property-creator.element.ts'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; @customElement('umb-workspace-view-document-type-listview') export class UmbWorkspaceViewDocumentTypeListviewElement extends UmbLitElement { static styles = [UUITextStyles, css``]; @state() - _documentType?: DocumentTypeModel; + _documentType?: DocumentTypeResponseModel; private _workspaceContext?: UmbWorkspaceDocumentTypeContext; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts index f15ede2561..8479c0bbd0 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts @@ -1,9 +1,10 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, state } from 'lit/decorators.js'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import type { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; -import { UmbLitElement } from '@umbraco-cms/element'; -import type { DocumentTypeModel } from '@umbraco-cms/backend-api'; + import '../../../../../shared/property-creator/property-creator.element.ts'; @customElement('umb-workspace-view-document-type-permissions') @@ -27,7 +28,7 @@ export class UmbWorkspaceViewDocumentTypePermissionsElement extends UmbLitElemen ]; @state() - _documentType?: DocumentTypeModel; + _documentType?: DocumentTypeResponseModel; private _workspaceContext?: UmbWorkspaceDocumentTypeContext; From e1e1b191c403e6c69b9bb180f9c18470d5d82c42 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 22 Mar 2023 15:18:25 +0100 Subject: [PATCH 008/114] add tree item extension point --- .../libs/extensions-registry/models.ts | 3 +++ .../libs/extensions-registry/tree-item.models.ts | 10 ++++++++++ 2 files changed, 13 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/libs/extensions-registry/tree-item.models.ts 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 871567b74d..615b0db9d1 100644 --- a/src/Umbraco.Web.UI.Client/libs/extensions-registry/models.ts +++ b/src/Umbraco.Web.UI.Client/libs/extensions-registry/models.ts @@ -16,6 +16,7 @@ import type { ManifestMenu } from './menu.models'; import type { ManifestMenuItem, ManifestMenuItemTreeKind } from './menu-item.models'; import type { ManifestTheme } from './theme.models'; import type { ManifestTree } from './tree.models'; +import type { ManifestTreeItem } from './tree-item.models'; import type { ManifestUserDashboard } from './user-dashboard.models'; import type { ManifestWorkspace } from './workspace.models'; import type { ManifestWorkspaceAction } from './workspace-action.models'; @@ -44,6 +45,7 @@ export * from './menu.models'; export * from './menu-item.models'; export * from './theme.models'; export * from './tree.models'; +export * from './tree-item.models'; export * from './user-dashboard.models'; export * from './workspace-action.models'; export * from './workspace-view-collection.models'; @@ -78,6 +80,7 @@ export type ManifestTypes = | ManifestMenuItemTreeKind | ManifestTheme | ManifestTree + | ManifestTreeItem | ManifestUserDashboard | ManifestWorkspace | ManifestWorkspaceAction diff --git a/src/Umbraco.Web.UI.Client/libs/extensions-registry/tree-item.models.ts b/src/Umbraco.Web.UI.Client/libs/extensions-registry/tree-item.models.ts new file mode 100644 index 0000000000..9231a8ae68 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/libs/extensions-registry/tree-item.models.ts @@ -0,0 +1,10 @@ +import type { ManifestElement } from './models'; + +export interface ManifestTreeItem extends ManifestElement { + type: 'treeItem'; + conditions: ConditionsTreeItem; +} + +export interface ConditionsTreeItem { + entityType: string; +} From cd32c72ad53f82a173c3ec75a92c6d725ff032cc Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 22 Mar 2023 15:36:32 +0100 Subject: [PATCH 009/114] add folder for tree-item component --- .../components/tree/tree-item.stories.ts | 27 ------------------- .../tree/{ => tree-item}/tree-item.element.ts | 6 ++--- .../tree/tree-item/tree-item.stories.ts | 27 +++++++++++++++++++ .../shared/components/tree/tree.element.ts | 2 +- 4 files changed, 31 insertions(+), 31 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.stories.ts rename src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/{ => tree-item}/tree-item.element.ts (97%) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.stories.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.stories.ts deleted file mode 100644 index 5b59cbde3b..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.stories.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Meta, StoryObj } from '@storybook/web-components'; -import './tree-item.element'; -import type { UmbTreeItem } from './tree-item.element' - -const meta: Meta = { - title: 'Components/Tree/Tree Item', - component: 'umb-tree-item', -}; - -export default meta; -type Story = StoryObj; - -export const Overview: Story = { - args: { - label: 'My Tree Item', - icon: 'umb:home', - hasChildren: false, - } -}; - -export const WithChildren: Story = { - args: { - label: 'My Tree Item', - icon: 'umb:home', - hasChildren: true, - } -}; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts similarity index 97% rename from src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.element.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts index 6f9eb57709..f6ae328ae6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts @@ -4,12 +4,12 @@ import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { map, Observable } from 'rxjs'; import { repeat } from 'lit/directives/repeat.js'; -import { UmbSectionContext, UMB_SECTION_CONTEXT_TOKEN } from '../section/section.context'; +import { UmbSectionContext, UMB_SECTION_CONTEXT_TOKEN } from '../../section/section.context'; import { UmbSectionSidebarContext, UMB_SECTION_SIDEBAR_CONTEXT_TOKEN, -} from '../section/section-sidebar/section-sidebar.context'; -import type { UmbTreeContextBase } from './tree.context'; +} from '../../section/section-sidebar/section-sidebar.context'; +import type { UmbTreeContextBase } from '../tree.context'; import type { Entity } from '@umbraco-cms/backoffice/models'; import type { UmbTreeStore } from '@umbraco-cms/backoffice/store'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.stories.ts new file mode 100644 index 0000000000..90962da327 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.stories.ts @@ -0,0 +1,27 @@ +import { Meta, StoryObj } from '@storybook/web-components'; +import './tree-item.element'; +import type { UmbTreeItem } from './tree-item.element'; + +const meta: Meta = { + title: 'Components/Tree/Tree Item', + component: 'umb-tree-item', +}; + +export default meta; +type Story = StoryObj; + +export const Overview: Story = { + args: { + label: 'My Tree Item', + icon: 'umb:home', + hasChildren: false, + }, +}; + +export const WithChildren: Story = { + args: { + label: 'My Tree Item', + icon: 'umb:home', + hasChildren: true, + }, +}; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts index e5e5d1c5a7..9d0629c8db 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts @@ -8,7 +8,7 @@ import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import './tree-item.element'; +import './tree-item/tree-item.element'; import './context-menu/tree-context-menu-page.service'; import './context-menu/tree-context-menu.service'; From ca31c16efbe3dc8479787c923bd75ff4ba4fb261 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 09:00:25 +0100 Subject: [PATCH 010/114] use tree kind for relation types menu item --- .../relation-types/menu-item/manifests.ts | 8 ++-- .../relation-types-menu-item.element.ts | 40 ------------------- 2 files changed, 4 insertions(+), 44 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/menu-item/relation-types-menu-item.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/menu-item/manifests.ts index 8138e8f9c9..1e6694da7d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/menu-item/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/menu-item/manifests.ts @@ -1,15 +1,15 @@ -import type { ManifestMenuItem } from '@umbraco-cms/backoffice/extensions-registry'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; -const menuItem: ManifestMenuItem = { +const menuItem: ManifestTypes = { type: 'menuItem', + kind: 'tree', alias: 'Umb.MenuItem.RelationTypes', name: 'Relation Types Menu Item', weight: 40, - loader: () => import('./relation-types-menu-item.element'), meta: { + treeAlias: 'Umb.Tree.RelationTypes', label: 'Relation Types', icon: 'umb:folder', - entityType: 'relation-type', }, conditions: { menus: ['Umb.Menu.Settings'], diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/menu-item/relation-types-menu-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/menu-item/relation-types-menu-item.element.ts deleted file mode 100644 index f9973b6dcb..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/menu-item/relation-types-menu-item.element.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { html, nothing } from 'lit'; -import { customElement, state } from 'lit/decorators.js'; -import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; - -@customElement('umb-relation-types-menu-item') -export class UmbRelationTypesMenuItemElement extends UmbLitElement { - @state() - private _renderTree = false; - - private _onShowChildren() { - this._renderTree = true; - } - - private _onHideChildren() { - this._renderTree = false; - } - - // TODO: check if root has children before settings the has-children attribute - // TODO: how do we want to cache the tree? (do we want to rerender every time the user opens the tree)? - // TODO: can we make this reusable? - render() { - return html` - ${this._renderTree ? html`` : nothing} - `; - } -} - -export default UmbRelationTypesMenuItemElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-relation-types-menu-item': UmbRelationTypesMenuItemElement; - } -} From 8edd96d23518408e883dee71b7482ef0f4cada17 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 09:18:54 +0100 Subject: [PATCH 011/114] remove these methods to force refactoring of them --- .../components/section/section.context.ts | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/section/section.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/section/section.context.ts index 66f502e948..2f90f58eca 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/section/section.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/section/section.context.ts @@ -13,16 +13,6 @@ export class UmbSectionContext { public readonly pathname = this.#manifestPathname.asObservable(); public readonly label = this.#manifestLabel.asObservable(); - /* - This was not used anywhere - private _activeTree = new BehaviorSubject(undefined); - public readonly activeTree = this._activeTree.asObservable(); - */ - - // TODO: what is the best context to put this in? - #activeTreeItem = new ObjectState(undefined); - public readonly activeTreeItem = this.#activeTreeItem.asObservable(); - constructor(manifest: ManifestSection) { this.setManifest(manifest); } @@ -32,17 +22,6 @@ export class UmbSectionContext { this.#manifestPathname.next(manifest?.meta?.pathname); this.#manifestLabel.next(manifest ? manifest.meta?.label || manifest.name : undefined); } - - /* - This was not used anywhere - public setActiveTree(tree: ManifestTree) { - this._activeTree.next(tree); - } - */ - - public setActiveTreeItem(item?: ActiveTreeItemType) { - this.#activeTreeItem.next(item); - } } export const UMB_SECTION_CONTEXT_TOKEN = new UmbContextToken('UmbSectionContext'); From 9dcc631ea3d35820dc9b858c3e7a283fe872df82 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 09:19:42 +0100 Subject: [PATCH 012/114] move most business logic from tree item element to a tree item context --- .../tree/tree-item/tree-item.context.ts | 136 +++++++++++ .../tree/tree-item/tree-item.element.ts | 230 ++++-------------- .../shared/components/tree/tree.element.ts | 21 +- 3 files changed, 196 insertions(+), 191 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.context.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.context.ts new file mode 100644 index 0000000000..d7c6b91b7e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.context.ts @@ -0,0 +1,136 @@ +import { map } from 'rxjs'; +import { + UmbSectionSidebarContext, + UMB_SECTION_SIDEBAR_CONTEXT_TOKEN, +} from '../../section/section-sidebar/section-sidebar.context'; +import { UmbSectionContext, UMB_SECTION_CONTEXT_TOKEN } from '../../section/section.context'; +import { UmbTreeContextBase } from '../tree.context'; +import { BooleanState, StringState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; +import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; +import { UmbContextConsumerController, UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; +import type { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; + +export class UmbTreeItemContextBase { + public host: UmbControllerHostInterface; + public treeItem: T; + public unique: string; + public type: string; + + #isLoading = new BooleanState(false); + isLoading = this.#isLoading.asObservable(); + + #isSelectable = new BooleanState(false); + isSelectable = this.#isSelectable.asObservable(); + + #isSelected = new BooleanState(false); + isSelected = this.#isSelected.asObservable(); + + #isActive = new BooleanState(false); + isActive = this.#isActive.asObservable(); + + #hasActions = new BooleanState(false); + hasActions = this.#hasActions.asObservable(); + + #path = new StringState(''); + path = this.#path.asObservable(); + + treeContext?: UmbTreeContextBase; + #sectionContext?: UmbSectionContext; + #sectionSidebarContext?: UmbSectionSidebarContext; + + constructor(host: UmbControllerHostInterface, treeItem: T, getUnique: (x: T) => string | null | undefined) { + this.host = host; + this.treeItem = treeItem; + + const unique = getUnique(this.treeItem); + if (!unique) throw new Error('Could not create tree item context, unique key is missing'); + this.unique = unique; + + if (!this.treeItem.type) throw new Error('Could not create tree item context, tree item type is missing'); + + this.type = this.treeItem.type; + + new UmbContextConsumerController(host, UMB_SECTION_CONTEXT_TOKEN, (instance) => { + this.#sectionContext = instance; + this.#observeSectionPath(); + }); + + new UmbContextConsumerController(host, UMB_SECTION_SIDEBAR_CONTEXT_TOKEN, (instance) => { + this.#sectionSidebarContext = instance; + }); + + new UmbContextConsumerController(host, 'umbTreeContext', (treeContext: UmbTreeContextBase) => { + this.treeContext = treeContext; + this.#observeIsSelectable(); + this.#observeIsSelected(); + }); + + this.#observeTreeItemActions(); + } + + public async requestChildren() { + // TODO: wait for tree context to be ready + this.#isLoading.next(true); + const response = await this.treeContext!.repository.requestTreeItemsOf(this.unique); + this.#isLoading.next(false); + return response; + } + + public toggleContextMenu() { + this.#sectionSidebarContext?.toggleContextMenu(this.type, this.unique, this.treeItem.name || ''); + } + + public select() { + this.treeContext?.select(this.unique); + } + + public deselect() { + this.treeContext?.deselect(this.unique); + } + + #observeIsSelectable() { + if (!this.treeContext) return; + new UmbObserverController(this.host, this.treeContext.selectable, (value) => this.#isSelectable.next(value)); + } + + #observeIsSelected() { + if (!this.treeContext) return; + + new UmbObserverController( + this.host, + this.treeContext.selection.pipe(map((selection) => selection.includes(this.unique))), + (isSelected) => { + this.#isSelected.next(isSelected); + } + ); + } + + #observeSectionPath() { + if (!this.#sectionContext) return; + + new UmbObserverController(this.host, this.#sectionContext.pathname, (pathname) => { + if (!pathname) return; + const path = this.#constructPath(pathname, this.type, this.unique); + this.#path.next(path); + }); + } + + #observeTreeItemActions() { + new UmbObserverController( + this.host, + umbExtensionsRegistry + .extensionsOfType('entityAction') + .pipe(map((actions) => actions.filter((action) => action.conditions.entityType === this.type))), + (actions) => { + this.#hasActions.next(actions.length > 0); + } + ); + } + + #constructPath(pathname: string, entityType: string, key: string) { + return `section/${pathname}/${entityType}/edit/${key}`; + } +} + +export const UMB_TREE_ITEM_CONTEXT_TOKEN = new UmbContextToken('UmbTreeItemContext'); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts index f6ae328ae6..0e86141d50 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts @@ -2,256 +2,122 @@ import { css, html, nothing } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; -import { map, Observable } from 'rxjs'; import { repeat } from 'lit/directives/repeat.js'; -import { UmbSectionContext, UMB_SECTION_CONTEXT_TOKEN } from '../../section/section.context'; -import { - UmbSectionSidebarContext, - UMB_SECTION_SIDEBAR_CONTEXT_TOKEN, -} from '../../section/section-sidebar/section-sidebar.context'; -import type { UmbTreeContextBase } from '../tree.context'; -import type { Entity } from '@umbraco-cms/backoffice/models'; -import type { UmbTreeStore } from '@umbraco-cms/backoffice/store'; +import { UmbTreeItemContextBase, UMB_TREE_ITEM_CONTEXT_TOKEN } from './tree-item.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; +import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; -// TODO: align menu items and tree items @customElement('umb-tree-item') export class UmbTreeItem extends UmbLitElement { static styles = [UUITextStyles, css``]; - @property({ type: String }) - key = ''; - - @property({ type: String }) - parentKey: string | null = null; - - @property({ type: String }) - label = ''; - - @property({ type: String }) - icon = ''; - - private _entityType = ''; - @property({ type: String }) - get entityType() { - return this._entityType; + private _item?: EntityTreeItemResponseModel; + @property({ type: Object, attribute: false }) + get item() { + return this._item; } - set entityType(newVal) { - const oldVal = this._entityType; - this._entityType = newVal; - this.requestUpdate('entityType', oldVal); - this._observeEntityActions(); + set item(newVal) { + const oldVal = this._item; + this._item = newVal; + this.requestUpdate('item', oldVal); } @property({ type: Boolean, attribute: 'has-children' }) hasChildren = false; @state() - private _childItems?: Entity[]; + private _childItems?: EntityTreeItemResponseModel[]; @state() private _href?: string; @state() - private _loading = false; + private _isLoading = false; @state() - private _selectable = false; + private _isSelectable = false; @state() - private _selected = false; - - @state() - private _isActive = false; + private _isSelected = false; @state() private _hasActions = false; - private _treeContext?: UmbTreeContextBase; - private _store?: UmbTreeStore; - private _sectionContext?: UmbSectionContext; - private _sectionSidebarContext?: UmbSectionSidebarContext; + #treeItemContext?: UmbTreeItemContextBase; constructor() { super(); - this.consumeContext('umbTreeContext', (treeContext: UmbTreeContextBase) => { - this._treeContext = treeContext; - this._observeSelectable(); - this._observeIsSelected(); - }); - - this.consumeContext('umbStore', (store: UmbTreeStore) => { - this._store = store; - }); - - this.consumeContext(UMB_SECTION_CONTEXT_TOKEN, (sectionContext) => { - this._sectionContext = sectionContext; - this._observeSection(); - this._observeActiveTreeItem(); - }); - - this.consumeContext(UMB_SECTION_SIDEBAR_CONTEXT_TOKEN, (instance) => { - this._sectionSidebarContext = instance; + this.consumeContext(UMB_TREE_ITEM_CONTEXT_TOKEN, (instance) => { + this.#treeItemContext = instance; + if (!this.#treeItemContext) return; + // TODO: investigate if we can make an observe decorator + this.observe(this.#treeItemContext.isLoading, (value) => (this._isLoading = value)); + this.observe(this.#treeItemContext.isSelectable, (value) => (this._isSelectable = value)); + this.observe(this.#treeItemContext.isSelected, (value) => (this._isSelected = value)); + this.observe(this.#treeItemContext.hasActions, (value) => (this._hasActions = value)); + this.observe(this.#treeItemContext.path, (value) => (this._href = value)); }); } connectedCallback(): void { super.connectedCallback(); - this.addEventListener('selected', this._handleSelectedItem); this.addEventListener('unselected', this._handleDeselectedItem); } private _handleSelectedItem(event: Event) { event.stopPropagation(); - this._treeContext?.select(this.key); + this.#treeItemContext?.select(); } private _handleDeselectedItem(event: Event) { event.stopPropagation(); - this._treeContext?.deselect(this.key); - } - - private _observeSection() { - if (!this._sectionContext) return; - - this.observe(this._sectionContext?.pathname, (pathname) => { - this._href = this._constructPath(pathname || '', this.entityType, this.key); - }); - } - - private _observeSelectable() { - if (!this._treeContext) return; - - this.observe(this._treeContext.selectable, (value) => { - this._selectable = value || false; - }); - } - - private _observeIsSelected() { - if (!this._treeContext) return; - - this.observe(this._treeContext.selection.pipe(map((keys) => keys?.includes(this.key))), (isSelected) => { - this._selected = isSelected || false; - }); - } - - private _observeActiveTreeItem() { - if (!this._sectionContext) return; - - this.observe(this._sectionContext?.activeTreeItem, (treeItem) => { - this._isActive = this.key === treeItem?.key; - }); - } - - private _observeEntityActions() { - // TODO: Stop previous observation, currently we can do this from the UmbElementMixin as its a new subscription when Actions or entityType has changed. - // Solution: store the current observation controller and if it existing then destroy it. - // TODO: as long as a tree consist of one entity type we don't have to observe this every time a new tree item is created. - // Solution: move this to the tree context and observe it once. - this.observe( - umbExtensionsRegistry - .extensionsOfType('entityAction') - .pipe(map((actions) => actions.filter((action) => action.conditions.entityType === this._entityType))), - (actions) => { - this._hasActions = actions.length > 0; - } - ); - } - - // TODO: how do we handle this? - private _constructPath(sectionPathname: string, type: string, key: string) { - return type ? `section/${sectionPathname}/workspace/${type}/edit/${key}` : undefined; + this.#treeItemContext?.deselect(); } // TODO: do we want to catch and emit a backoffice event here? private _onShowChildren() { if (this._childItems && this._childItems.length > 0) return; - this._observeChildren(); - this._observeRepositoryChildren(); + this.#observeChildren(); } - private async _observeRepositoryChildren() { - if (!this._treeContext?.requestChildrenOf) return; + async #observeChildren() { + if (!this.#treeItemContext?.requestChildren) return; - // TODO: add loading state - this._treeContext.requestChildrenOf(this.key); + const { asObservable } = await this.#treeItemContext.requestChildren(); + if (!asObservable) return; - this.observe(await this._treeContext.childrenOf(this.key), (childItems) => { - this._childItems = childItems as Entity[]; - }); - } - - // TODO: remove when repositories are in place - private _observeChildren() { - if (!this._store?.getTreeItemChildren) return; - - this._loading = true; - - // TODO: we should do something about these types, stop having our own version of Entity. - this.observe(this._store.getTreeItemChildren(this.key) as Observable, (childItems) => { + this.observe(asObservable(), (childItems) => { this._childItems = childItems; - this._loading = false; }); } private _openActions() { - if (!this._treeContext || !this._sectionContext) return; - - // This is out-commented as it was not used. only kept if someone need this later: - //this._sectionContext?.setActiveTree(this._treeContext?.tree); - - this._sectionContext?.setActiveTreeItem({ - key: this.key, - name: this.label, - icon: this.icon, - type: this.entityType, - hasChildren: this.hasChildren, - parentKey: this.parentKey, - }); - this._sectionSidebarContext?.toggleContextMenu(this.entityType, this.key, this.label); + this.#treeItemContext?.toggleContextMenu(); } render() { return html` - ${this._renderChildItems()} - - ${this._renderActions()} + label="${ifDefined(this.item?.name)}" + href="${ifDefined(this._href)}"> + ${this.#renderIcon()} ${this.#renderActions()} ${this.#renderChildItems()} `; } - private _renderChildItems() { - return html` - ${this._childItems - ? repeat( - this._childItems, - (item) => item.key, - (item) => - html`` - ) - : ''} - `; + #renderIcon() { + return html` ${this.item?.icon ? html` ` : nothing} `; } - private _renderActions() { + #renderActions() { return html` ${this._hasActions ? html` @@ -264,6 +130,18 @@ export class UmbTreeItem extends UmbLitElement { : nothing} `; } + + #renderChildItems() { + return html` + ${this._childItems + ? repeat( + this._childItems, + (item) => item.key, + (item) => html`` + ) + : ''} + `; + } } declare global { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts index 9d0629c8db..5514f84ce6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts @@ -3,10 +3,10 @@ import { customElement, property, state } from 'lit/decorators.js'; import { map } from 'rxjs'; import { repeat } from 'lit/directives/repeat.js'; import { UmbTreeContextBase } from './tree.context'; -import type { Entity } from '@umbraco-cms/backoffice/models'; import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; import './tree-item/tree-item.element'; import './context-menu/tree-context-menu-page.service'; @@ -54,10 +54,7 @@ export class UmbTreeElement extends UmbLitElement { private _tree?: ManifestTree; @state() - private _items: Entity[] = []; - - @state() - private _loading = true; + private _items: EntityTreeItemResponseModel[] = []; private _treeContext?: UmbTreeContextBase; @@ -101,7 +98,7 @@ export class UmbTreeElement extends UmbLitElement { this._treeContext.requestRootItems(); this.observe(await this._treeContext.rootItems(), (rootItems) => { - this._items = rootItems as Entity[]; + this._items = rootItems; }); } @@ -119,15 +116,9 @@ export class UmbTreeElement extends UmbLitElement { return html` ${repeat( this._items, - (item) => item.key, - (item) => - html`` + // TODO: add getUnique to a repository interface + (item, index) => index, + (item) => html`` )} `; } From 2dd44e1477e2f8cec18e6339bd414be5cd08a678 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 09:30:58 +0100 Subject: [PATCH 013/114] fix import order remove comment --- .../documents/repository/document.repository.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.repository.ts index dd7fc1789c..a3490cf3c5 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.repository.ts @@ -1,3 +1,7 @@ +import { UmbDocumentServerDataSource } from './sources/document.server.data'; +import { UmbDocumentStore, UMB_DOCUMENT_STORE_CONTEXT_TOKEN } from './document.store'; +import { UmbDocumentTreeStore, UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN } from './document.tree.store'; +import { DocumentTreeServerDataSource } from './sources/document.tree.server.data'; import type { RepositoryTreeDataSource, UmbTreeRepository, @@ -7,17 +11,9 @@ import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { ProblemDetailsModel, DocumentResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; -import { DocumentTreeServerDataSource } from './sources/document.tree.server.data'; -import { UmbDocumentTreeStore, UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN } from './document.tree.store'; -import { UmbDocumentStore, UMB_DOCUMENT_STORE_CONTEXT_TOKEN } from './document.store'; -import { UmbDocumentServerDataSource } from './sources/document.server.data'; type ItemType = DocumentResponseModel; -// Move to documentation / JSdoc -/* We need to create a new instance of the repository from within the element context. We want the notifications to be displayed in the right context. */ -// element -> context -> repository -> (store) -> data source -// All methods should be async and return a promise. Some methods might return an observable as part of the promise response. export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailRepository { #init!: Promise; From 6c01edafe8abf4a6c3843b3ff8da348c6f89a675 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 10:05:04 +0100 Subject: [PATCH 014/114] rename to tree-item-base --- .../documents/documents/tree/manifests.ts | 14 ++++- .../tree-item/document-tree-item.element.ts | 51 +++++++++++++++++++ .../tree-item-base.context.ts} | 0 .../tree-item-base.element.ts} | 10 ++-- .../tree-item-base.stories.ts} | 8 +-- .../shared/components/tree/tree.element.ts | 4 +- 6 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts rename src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/{tree-item/tree-item.context.ts => tree-item-base/tree-item-base.context.ts} (100%) rename src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/{tree-item/tree-item.element.ts => tree-item-base/tree-item-base.element.ts} (93%) rename src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/{tree-item/tree-item.stories.ts => tree-item-base/tree-item-base.stories.ts} (66%) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts index c1e6a79314..ee92e43e8d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts @@ -1,5 +1,5 @@ import { UmbDocumentRepository } from '../repository/document.repository'; -import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; +import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const treeAlias = 'Umb.Tree.Documents'; @@ -12,4 +12,14 @@ const tree: ManifestTree = { }, }; -export const manifests = [tree]; +const treeItem: ManifestTreeItem = { + type: 'treeItem', + alias: 'Umb.TreeItem.Document', + name: 'Document Tree Item', + loader: () => import('./tree-item/document-tree-item.element'), + conditions: { + entityType: 'document', + }, +}; + +export const manifests = [tree, treeItem]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts new file mode 100644 index 0000000000..d488839fde --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts @@ -0,0 +1,51 @@ +import { css, html, nothing } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property } from 'lit/decorators.js'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { DocumentTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; + +@customElement('umb-document-tree-item') +export class UmbDocumentTreeItemElement extends UmbLitElement { + static styles = [ + UUITextStyles, + css` + #label { + display: flex; + align-items: center; + } + + #status-symbol { + width: 6px; + height: 6px; + background-color: blue; + display: block; + border-radius: 3px; + margin-right: 10px; + } + `, + ]; + + @property({ type: Object, attribute: false }) + public item?: DocumentTreeItemResponseModel; + + render() { + if (!this.item) return nothing; + return html` + + +
+ + ${this.item?.name} +
+
+ `; + } +} + +export default UmbDocumentTreeItemElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-document-tree-item': UmbDocumentTreeItemElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.context.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts similarity index 93% rename from src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts index 0e86141d50..601bb816a4 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts @@ -3,12 +3,12 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { repeat } from 'lit/directives/repeat.js'; -import { UmbTreeItemContextBase, UMB_TREE_ITEM_CONTEXT_TOKEN } from './tree-item.context'; +import { UmbTreeItemContextBase, UMB_TREE_ITEM_CONTEXT_TOKEN } from './tree-item-base.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; -@customElement('umb-tree-item') -export class UmbTreeItem extends UmbLitElement { +@customElement('umb-tree-item-base') +export class UmbTreeItemBaseElement extends UmbLitElement { static styles = [UUITextStyles, css``]; private _item?: EntityTreeItemResponseModel; @@ -137,7 +137,7 @@ export class UmbTreeItem extends UmbLitElement { ? repeat( this._childItems, (item) => item.key, - (item) => html`` + (item) => html`` ) : ''} `; @@ -146,6 +146,6 @@ export class UmbTreeItem extends UmbLitElement { declare global { interface HTMLElementTagNameMap { - 'umb-tree-item': UmbTreeItem; + 'umb-tree-item-base': UmbTreeItemBaseElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.stories.ts similarity index 66% rename from src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.stories.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.stories.ts index 90962da327..1f76f40872 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.stories.ts @@ -1,14 +1,14 @@ import { Meta, StoryObj } from '@storybook/web-components'; -import './tree-item.element'; -import type { UmbTreeItem } from './tree-item.element'; +import './tree-item-base.element'; +import type { UmbTreeItemBaseElement } from './tree-item-base.element'; -const meta: Meta = { +const meta: Meta = { title: 'Components/Tree/Tree Item', component: 'umb-tree-item', }; export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Overview: Story = { args: { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts index 5514f84ce6..25e34c849d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts @@ -8,7 +8,7 @@ import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; -import './tree-item/tree-item.element'; +import './tree-item-base/tree-item-base.element'; import './context-menu/tree-context-menu-page.service'; import './context-menu/tree-context-menu.service'; @@ -118,7 +118,7 @@ export class UmbTreeElement extends UmbLitElement { this._items, // TODO: add getUnique to a repository interface (item, index) => index, - (item) => html`` + (item) => html`` )} `; } From 4bc178020d7b61bee0af6ced60956a89b19f2b8a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 10:46:47 +0100 Subject: [PATCH 015/114] move context token into folder --- .../consume/context-consumer.controller.ts | 2 +- .../libs/context-api/consume/context-consumer.ts | 15 ++++++++------- .../context-api/consume/context-request.event.ts | 7 +++---- .../libs/context-api/index.ts | 2 +- .../context-api/provide/context-provide.event.ts | 2 +- .../provide/context-provider.controller.ts | 2 +- .../libs/context-api/provide/context-provider.ts | 12 ++++++++---- .../context-api/{ => token}/context-token.test.ts | 4 ++-- .../libs/context-api/{ => token}/context-token.ts | 0 9 files changed, 25 insertions(+), 21 deletions(-) rename src/Umbraco.Web.UI.Client/libs/context-api/{ => token}/context-token.test.ts (91%) rename src/Umbraco.Web.UI.Client/libs/context-api/{ => token}/context-token.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/libs/context-api/consume/context-consumer.controller.ts b/src/Umbraco.Web.UI.Client/libs/context-api/consume/context-consumer.controller.ts index 2d30084d7f..f9b72588b2 100644 --- a/src/Umbraco.Web.UI.Client/libs/context-api/consume/context-consumer.controller.ts +++ b/src/Umbraco.Web.UI.Client/libs/context-api/consume/context-consumer.controller.ts @@ -1,4 +1,4 @@ -import { UmbContextToken } from '../context-token'; +import { UmbContextToken } from '../token/context-token'; import { UmbContextConsumer } from './context-consumer'; import { UmbContextCallback } from './context-request.event'; import type { UmbControllerHostInterface, UmbControllerInterface } from '@umbraco-cms/backoffice/controller'; diff --git a/src/Umbraco.Web.UI.Client/libs/context-api/consume/context-consumer.ts b/src/Umbraco.Web.UI.Client/libs/context-api/consume/context-consumer.ts index 0fe4fc33d8..5432b1dc0d 100644 --- a/src/Umbraco.Web.UI.Client/libs/context-api/consume/context-consumer.ts +++ b/src/Umbraco.Web.UI.Client/libs/context-api/consume/context-consumer.ts @@ -1,4 +1,4 @@ -import { UmbContextToken } from '../context-token'; +import { UmbContextToken } from '../token/context-token'; import { isUmbContextProvideEventType, umbContextProvideEventType } from '../provide/context-provide.event'; import { UmbContextRequestEventImplementation, UmbContextCallback } from './context-request.event'; @@ -7,10 +7,8 @@ import { UmbContextRequestEventImplementation, UmbContextCallback } from './cont * @class UmbContextConsumer */ export class UmbContextConsumer { - - _promise?: Promise; - _promiseResolver?: (instance:T) => void; + _promiseResolver?: (instance: T) => void; private _instance?: T; get instance() { @@ -44,9 +42,12 @@ export class UmbContextConsumer((resolve) => { - this._instance ? resolve(this._instance) : (this._promiseResolver = resolve); - })); + return ( + this._promise || + (this._promise = new Promise((resolve) => { + this._instance ? resolve(this._instance) : (this._promiseResolver = resolve); + })) + ); } /** diff --git a/src/Umbraco.Web.UI.Client/libs/context-api/consume/context-request.event.ts b/src/Umbraco.Web.UI.Client/libs/context-api/consume/context-request.event.ts index ab96c5bd51..d1b630be4b 100644 --- a/src/Umbraco.Web.UI.Client/libs/context-api/consume/context-request.event.ts +++ b/src/Umbraco.Web.UI.Client/libs/context-api/consume/context-request.event.ts @@ -1,4 +1,4 @@ -import { UmbContextToken } from '../context-token'; +import { UmbContextToken } from '../token/context-token'; export const umbContextRequestEventType = 'umb:context-request'; export const umbDebugContextEventType = 'umb:debug-contexts'; @@ -33,9 +33,8 @@ export const isUmbContextRequestEvent = (event: Event): event is UmbContextReque return event.type === umbContextRequestEventType; }; - export class UmbContextDebugRequest extends Event { - public constructor(public readonly callback:any) { + public constructor(public readonly callback: any) { super(umbDebugContextEventType, { bubbles: true, composed: true, cancelable: false }); } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI.Client/libs/context-api/index.ts b/src/Umbraco.Web.UI.Client/libs/context-api/index.ts index 67aaa8edcf..39b438786a 100644 --- a/src/Umbraco.Web.UI.Client/libs/context-api/index.ts +++ b/src/Umbraco.Web.UI.Client/libs/context-api/index.ts @@ -4,4 +4,4 @@ export * from './consume/context-request.event'; export * from './provide/context-provider.controller'; export * from './provide/context-provider'; export * from './provide/context-provide.event'; -export * from './context-token'; +export * from './token/context-token'; diff --git a/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provide.event.ts b/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provide.event.ts index 37b88cea24..9388743921 100644 --- a/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provide.event.ts +++ b/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provide.event.ts @@ -1,4 +1,4 @@ -import { UmbContextToken } from '../context-token'; +import { UmbContextToken } from '../token/context-token'; export const umbContextProvideEventType = 'umb:context-provide'; diff --git a/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provider.controller.ts b/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provider.controller.ts index 54c9e2e167..7412ae6a0c 100644 --- a/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provider.controller.ts +++ b/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provider.controller.ts @@ -1,4 +1,4 @@ -import { UmbContextToken } from '../context-token'; +import { UmbContextToken } from '../token/context-token'; import { UmbContextProvider } from './context-provider'; import type { UmbControllerHostInterface, UmbControllerInterface } from '@umbraco-cms/backoffice/controller'; diff --git a/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provider.ts b/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provider.ts index c9ce3ab9c3..efed204d3a 100644 --- a/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provider.ts +++ b/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provider.ts @@ -1,5 +1,9 @@ -import { umbContextRequestEventType, isUmbContextRequestEvent, umbDebugContextEventType } from '../consume/context-request.event'; -import { UmbContextToken } from '../context-token'; +import { + umbContextRequestEventType, + isUmbContextRequestEvent, + umbDebugContextEventType, +} from '../consume/context-request.event'; +import { UmbContextToken } from '../token/context-token'; import { UmbContextProvideEventImplementation } from './context-provide.event'; /** @@ -68,14 +72,14 @@ export class UmbContextProvider { private _handleDebugContextRequest = (event: any) => { // If the event doesn't have an instances property, create it. - if(!event.instances){ + if (!event.instances) { event.instances = new Map(); } // If the event doesn't have an instance for this context, add it. // Nearest to the DOM element of will be added first // as contexts can change/override deeper in the DOM - if(!event.instances.has(this._contextAlias)){ + if (!event.instances.has(this._contextAlias)) { event.instances.set(this._contextAlias, this.#instance); } }; diff --git a/src/Umbraco.Web.UI.Client/libs/context-api/context-token.test.ts b/src/Umbraco.Web.UI.Client/libs/context-api/token/context-token.test.ts similarity index 91% rename from src/Umbraco.Web.UI.Client/libs/context-api/context-token.test.ts rename to src/Umbraco.Web.UI.Client/libs/context-api/token/context-token.test.ts index 66531d06f0..4493b739d6 100644 --- a/src/Umbraco.Web.UI.Client/libs/context-api/context-token.test.ts +++ b/src/Umbraco.Web.UI.Client/libs/context-api/token/context-token.test.ts @@ -1,7 +1,7 @@ import { expect } from '@open-wc/testing'; -import { UmbContextConsumer } from './consume/context-consumer'; +import { UmbContextConsumer } from '../consume/context-consumer'; import { UmbContextToken } from './context-token'; -import { UmbContextProvider } from './provide/context-provider'; +import { UmbContextProvider } from '../provide/context-provider'; const testContextAlias = 'my-test-context'; diff --git a/src/Umbraco.Web.UI.Client/libs/context-api/context-token.ts b/src/Umbraco.Web.UI.Client/libs/context-api/token/context-token.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/libs/context-api/context-token.ts rename to src/Umbraco.Web.UI.Client/libs/context-api/token/context-token.ts From 739b3adfc06000a7e0fb90a952d55c24bb22fcba Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 11:07:32 +0100 Subject: [PATCH 016/114] remove sidebar from document menu item --- .../src/backoffice/documents/documents/manifests.ts | 2 +- .../document-menu-item.element.ts} | 8 ++++---- .../{sidebar-menu-item => menu-item}/manifests.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) rename src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/{sidebar-menu-item/document-sidebar-menu-item.element.ts => menu-item/document-menu-item.element.ts} (54%) rename src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/{sidebar-menu-item => menu-item}/manifests.ts (85%) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/manifests.ts index db1abd9914..61718098ac 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/manifests.ts @@ -1,5 +1,5 @@ import { manifests as collectionManifests } from './collection/manifests'; -import { manifests as menuItemManifests } from './sidebar-menu-item/manifests'; +import { manifests as menuItemManifests } from './menu-item/manifests'; import { manifests as repositoryManifests } from './repository/manifests'; import { manifests as treeManifests } from './tree/manifests'; import { manifests as workspaceManifests } from './workspace/manifests'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/sidebar-menu-item/document-sidebar-menu-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/menu-item/document-menu-item.element.ts similarity index 54% rename from src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/sidebar-menu-item/document-sidebar-menu-item.element.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/menu-item/document-menu-item.element.ts index 7102a30105..07d94f6a1f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/sidebar-menu-item/document-sidebar-menu-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/menu-item/document-menu-item.element.ts @@ -2,17 +2,17 @@ import { html } from 'lit'; import { customElement } from 'lit/decorators.js'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -@customElement('umb-document-sidebar-menu-item') -export class UmbDocumentSidebarMenuItemElement extends UmbLitElement { +@customElement('umb-document-menu-item') +export class UmbDocumentMenuItemElement extends UmbLitElement { render() { return html``; } } -export default UmbDocumentSidebarMenuItemElement; +export default UmbDocumentMenuItemElement; declare global { interface HTMLElementTagNameMap { - 'umb-document-sidebar-menu-item': UmbDocumentSidebarMenuItemElement; + 'umb-document-menu-item': UmbDocumentMenuItemElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/sidebar-menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/menu-item/manifests.ts similarity index 85% rename from src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/sidebar-menu-item/manifests.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/menu-item/manifests.ts index e06fc87a74..5c448b6d0b 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/sidebar-menu-item/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/menu-item/manifests.ts @@ -5,7 +5,7 @@ const menuItem: ManifestMenuItem = { alias: 'Umb.MenuItem.Documents', name: 'Documents Menu Item', weight: 100, - loader: () => import('./document-sidebar-menu-item.element'), + loader: () => import('./document-menu-item.element'), meta: { label: 'Documents', icon: 'umb:folder', From 74f56186ca905c7a1d424a36a8494238f9b35fd4 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 23 Mar 2023 11:22:49 +0100 Subject: [PATCH 017/114] update --- ...space-view-document-type-design.element.ts | 5 +- ...ce-view-document-type-templates.element.ts | 31 ++-- .../input-template-picker.element.ts | 159 +++++++++--------- .../template-card/template-card.element.ts | 4 +- .../workspace-layout.element.ts | 6 +- .../src/backoffice/shared/modals/manifests.ts | 12 ++ .../shared/modals/template-picker/index.ts | 18 ++ .../template-picker-modal.element.ts | 104 ++++++++++++ .../shared/modals/template/index.ts | 18 ++ .../modals/template/template-modal.element.ts | 97 +++++++++++ .../src/core/mocks/data/document-type.data.ts | 8 +- 11 files changed, 356 insertions(+), 106 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts index 2b50b0310e..a27bfb57fb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts @@ -123,8 +123,9 @@ export class UmbWorkspaceViewDocumentTypeDesignElement extends UmbLitElement {
- - + + +
diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts index 99fbdacaa7..cc89db1358 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts @@ -1,10 +1,9 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, property, state } from 'lit/decorators.js'; +import { customElement, state } from 'lit/decorators.js'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; - import '../../../../../shared/property-creator/property-creator.element.ts'; @customElement('umb-workspace-view-document-type-templates') @@ -37,24 +36,13 @@ export class UmbWorkspaceViewDocumentTypeTemplatesElement extends UmbLitElement `, ]; - @property() - defaultTemplateKey?: string = '123'; - @state() _documentType?: DocumentTypeResponseModel; - @state() - _templates = [ - { key: '123', name: 'Blog Post Page' }, - { key: '456', name: 'Blog Entry Page' }, - ]; - private _workspaceContext?: UmbWorkspaceDocumentTypeContext; constructor() { super(); - - // TODO: Figure out if this is the best way to consume the context or if it can be strongly typed with an UmbContextToken this.consumeContext('umbWorkspaceContext', (documentTypeContext) => { this._workspaceContext = documentTypeContext; this._observeDocumentType(); @@ -69,13 +57,14 @@ export class UmbWorkspaceViewDocumentTypeTemplatesElement extends UmbLitElement }); } - #changeDefaultTemplate(e: CustomEvent) { - //this.defaultTemplateKey = (e.target as UmbTemplateCardElement).value as string; - console.log('default template key', this.defaultTemplateKey); + async #changeDefaultKey(e: CustomEvent) { + // save new default key + console.log('workspace: default template key', e); } - #removeTemplate(key: string) { - console.log('remove template', key); + #changeAllowedKeys(e: CustomEvent) { + // save new allowed keys + console.log('workspace: allowed templates changed', e); } render() { @@ -83,7 +72,11 @@ export class UmbWorkspaceViewDocumentTypeTemplatesElement extends UmbLitElement
Choose which templates editors are allowed to use on content of this type
- +
`; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts index 8311ae6099..828f13bfe1 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts @@ -1,15 +1,14 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, property, queryAll, state } from 'lit/decorators.js'; -import { repeat } from 'lit/directives/repeat.js'; +import { customElement, property, state } from 'lit/decorators.js'; import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; - -import { TemplateResource } from '@umbraco-cms/backoffice/backend-api'; -import { UMB_CONFIRM_MODAL_TOKEN } from '../../modals/confirm'; +import { TemplateResource, TemplateResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbTemplateCardElement } from '../template-card/template-card.element'; +import { UMB_TEMPLATE_PICKER_MODAL_TOKEN } from '../../modals/template-picker'; +import { UMB_TEMPLATE_MODAL_TOKEN } from '../../modals/template'; @customElement('umb-input-template-picker') export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElement) { @@ -31,19 +30,6 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen min-width: 180px; min-height: 150px; } - - .fade-in { - animation: fadeIn 1s; - } - - @keyframes fadeIn { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } - } `, ]; /** @@ -82,30 +68,43 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen @property({ type: String, attribute: 'min-message' }) maxMessage = 'This field exceeds the allowed amount of items'; - @state() - private _items: Array = [ - { key: '2bf464b6-3aca-4388-b043-4eb439cc2643', name: 'Doc 1', default: false }, - { key: '9a84c0b3-03b4-4dd4-84ac-706740ac0f71', name: 'Test', default: true }, - ]; + _allowedKeys: Array = []; + @property({ type: Array }) + public get allowedKeys() { + return this._allowedKeys; + } + public set allowedKeys(newKeys: Array) { + //this.#observePickedTemplates(); + this._allowedKeys = newKeys; + } + + _defaultKey = ''; + @property({ type: String }) + public get defaultKey(): string { + return this._defaultKey; + } + public set defaultKey(newKey: string) { + this._defaultKey = newKey; + super.value = newKey; + } private _modalContext?: UmbModalContext; - //private _documentStore?: UmbDocumentTreeStore; - //private _pickedItemsObserver?: UmbObserverController; + //private _templateStore?: UmbTemplateTreeStore; + //private _pickedItemsObserver?: UmbObserverController; + + @state() + _templates: TemplateResponseModel[] = []; + + public get templates(): TemplateResponseModel[] { + return this._templates; + } + public set templates(newTemplates: TemplateResponseModel[]) { + this._templates = newTemplates; + this.allowedKeys = newTemplates.map((template) => template.key ?? ''); + } constructor() { super(); - - this.addValidator( - 'rangeUnderflow', - () => this.minMessage, - () => !!this.min && this._items.length < this.min - ); - this.addValidator( - 'rangeOverflow', - () => this.maxMessage, - () => !!this.max && this._items.length > this.max - ); - this.consumeContext(UMB_MODAL_CONTEXT_TOKEN, (instance) => { this._modalContext = instance; }); @@ -113,79 +112,83 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen connectedCallback(): void { super.connectedCallback(); - this._items = this._items.sort((a, b) => b.default - a.default); - this.#setup(); + this.allowedKeys.forEach((key) => this.#setup(key)); } - async #setup() { - const templates = await tryExecuteAndNotify(this, TemplateResource.getTreeTemplateRoot({ skip: 0, take: 9999 })); - console.log(templates); + async #setup(templateKey: string) { + const { data } = await tryExecuteAndNotify(this, TemplateResource.getTemplateByKey({ key: templateKey })); + if (!data) return; + this.templates = [...this.templates, data]; } protected getFormElement() { return undefined; } - #openTemplatePickerModal() { - console.log('template picker modal'); - } - - #changeSelected() { - console.log('selected'); - } - - /** Clicking the template card buttons */ - #changeDefault(e: CustomEvent) { - const key = (e.target as UmbTemplateCardElement).value; + e.stopPropagation(); + const newKey = (e.target as UmbTemplateCardElement).value as string; + this.defaultKey = newKey; + this.dispatchEvent(new CustomEvent('change-default', { bubbles: true, composed: true })); + } - const oldDefault = this._items.find((x) => x.default === true); - const newDefault = this._items.find((x) => x.key === key); - - const items = this._items.map((item) => { - if (item.default === true) return { ...newDefault, default: true }; - if (item.key === key) return { ...oldDefault, default: false }; - return item; + #openPicker() { + //TODO: Tree-picker modal? + const modalHandler = this._modalContext?.open(UMB_TEMPLATE_PICKER_MODAL_TOKEN, { + multiple: true, + selection: [...this.allowedKeys], }); - this._items = items; - } - - #openTemplate(e: CustomEvent) { - const key = (e.target as UmbTemplateCardElement).value; - console.log('open', key); + modalHandler?.onSubmit().then((data) => { + console.log(data.selection); + this.dispatchEvent(new CustomEvent('change-allowed', { bubbles: true, composed: true })); + }); } #removeTemplate(key: string) { - console.log('remove', key); + console.log('picker: remove', key); + const templateIndex = this.templates.findIndex((x) => x.key === key); + this.templates.splice(templateIndex, 1); + this.templates = [...this._templates]; } render() { return html` - ${repeat( - this._items, - (template) => template.default, - (template, index) => html`
+ ${this.templates.map( + (template) => html` + ?default="${template.key === this.defaultKey}"> -
` + ` )} - Add + Add `; } + + #openTemplate(e: CustomEvent) { + const key = (e.target as UmbTemplateCardElement).value; + + const modalHandler = this._modalContext?.open(UMB_TEMPLATE_MODAL_TOKEN, { + multiple: true, + selection: [...this.allowedKeys], + }); + + modalHandler?.onSubmit().then((res) => { + console.log('save template'); + }); + } } export default UmbInputTemplatePickerElement; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.element.ts index c971f22dbb..50f8cc5484 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/template-card/template-card.element.ts @@ -139,7 +139,7 @@ export class UmbTemplateCardElement extends FormControlMixin(UmbLitElement) { e.preventDefault(); e.stopPropagation(); //this.selected = true; - this.dispatchEvent(new CustomEvent('default-change', { bubbles: true, composed: true })); + this.dispatchEvent(new CustomEvent('change-default', { bubbles: true, composed: true })); } #openTemplate(e: KeyboardEvent) { e.preventDefault(); @@ -149,7 +149,6 @@ export class UmbTemplateCardElement extends FormControlMixin(UmbLitElement) { render() { return html`
-
`; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-layout/workspace-layout.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-layout/workspace-layout.element.ts index bbe2cf2a8e..f1fe4b7ff2 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-layout/workspace-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-layout/workspace-layout.element.ts @@ -40,9 +40,9 @@ export class UmbWorkspaceLayout extends UmbLitElement { } #router-slot { - display:flex; - flex-direction:column; - height:100%; + display: flex; + flex-direction: column; + height: 100%; } uui-input { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/manifests.ts index ac7dfa75d5..78fa2bd2b7 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/manifests.ts @@ -31,6 +31,18 @@ const modals: Array = [ name: 'Section Picker Modal', loader: () => import('./section-picker/section-picker-modal.element'), }, + { + type: 'modal', + alias: 'Umb.Modal.TemplatePicker', + name: 'Template Picker Modal', + loader: () => import('./template-picker/template-picker-modal.element'), + }, + { + type: 'modal', + alias: 'Umb.Modal.Template', + name: 'Template Modal', + loader: () => import('./template/template-modal.element'), + }, ]; export const manifests = [...modals]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/index.ts new file mode 100644 index 0000000000..f8f2560e3e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/index.ts @@ -0,0 +1,18 @@ +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbTemplatePickerModalData { + multiple: boolean; + selection: string[]; +} + +export interface UmbTemplatePickerModalResult { + selection: string[] | undefined; +} + +export const UMB_TEMPLATE_PICKER_MODAL_TOKEN = new UmbModalToken< + UmbTemplatePickerModalData, + UmbTemplatePickerModalResult +>('Umb.Modal.TemplatePicker', { + type: 'sidebar', + size: 'small', +}); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts new file mode 100644 index 0000000000..503b3113a8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts @@ -0,0 +1,104 @@ +import { css, html } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, state } from 'lit/decorators.js'; +import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; +import { UmbTreeElement } from '../../components/tree/tree.element'; +import { UmbTemplatePickerModalData, UmbTemplatePickerModalResult } from '.'; + +//TODO: make a default tree-picker that can be used across multiple pickers +// TODO: make use of UmbPickerLayoutBase +@customElement('umb-template-picker-modal') +export class UmbTemplatePickerModalElement extends UmbModalBaseElement< + UmbTemplatePickerModalData, + UmbTemplatePickerModalResult +> { + static styles = [ + UUITextStyles, + css` + h3 { + margin-left: var(--uui-size-space-5); + margin-right: var(--uui-size-space-5); + } + + uui-input { + width: 100%; + } + + hr { + border: none; + border-bottom: 1px solid var(--uui-color-divider); + margin: 16px 0; + } + + #content-list { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-3); + } + + .content-item { + cursor: pointer; + } + + .content-item.selected { + background-color: var(--uui-color-selected); + color: var(--uui-color-selected-contrast); + } + `, + ]; + + @state() + _selection: Array = []; + + @state() + _multiple = true; + + connectedCallback() { + super.connectedCallback(); + this._selection = this.data?.selection ?? []; + this._multiple = this.data?.multiple ?? true; + } + + private _handleSelectionChange(e: CustomEvent) { + e.stopPropagation(); + const element = e.target as UmbTreeElement; + //TODO: Should multiple property be implemented here or be passed down into umb-tree? + this._selection = this._multiple ? element.selection : [element.selection[element.selection.length - 1]]; + } + + private _submit() { + this.modalHandler?.submit({ selection: this._selection }); + } + + private _close() { + this.modalHandler?.reject(); + } + + render() { + return html` + + + +
+ +
+
+ + +
+
+ `; + } +} + +export default UmbTemplatePickerModalElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-template-picker-modal': UmbTemplatePickerModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/index.ts new file mode 100644 index 0000000000..28f1568e30 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/index.ts @@ -0,0 +1,18 @@ +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbTemplateModalData { + multiple: boolean; + selection: string[]; +} + +export interface UmbTemplateModalResult { + selection: string[] | undefined; +} + +export const UMB_TEMPLATE_MODAL_TOKEN = new UmbModalToken( + 'Umb.Modal.Template', + { + type: 'sidebar', + size: 'large', + } +); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts new file mode 100644 index 0000000000..89a6f66061 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts @@ -0,0 +1,97 @@ +import { css, html } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, state } from 'lit/decorators.js'; +import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; +import { UmbTreeElement } from '../../components/tree/tree.element'; +import { UmbTemplateModalData, UmbTemplateModalResult } from '.'; + +//TODO: make a default tree-picker that can be used across multiple pickers +// TODO: make use of UmbPickerLayoutBase +@customElement('umb-template-modal') +export class UmbTemplateModalElement extends UmbModalBaseElement { + static styles = [ + UUITextStyles, + css` + h3 { + margin-left: var(--uui-size-space-5); + margin-right: var(--uui-size-space-5); + } + + uui-input { + width: 100%; + } + + hr { + border: none; + border-bottom: 1px solid var(--uui-color-divider); + margin: 16px 0; + } + + #content-list { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-3); + } + + .content-item { + cursor: pointer; + } + + .content-item.selected { + background-color: var(--uui-color-selected); + color: var(--uui-color-selected-contrast); + } + `, + ]; + + @state() + _selection: Array = []; + + @state() + _multiple = true; + + connectedCallback() { + super.connectedCallback(); + this._selection = this.data?.selection ?? []; + this._multiple = this.data?.multiple ?? true; + } + + private _handleSelectionChange(e: CustomEvent) { + e.stopPropagation(); + const element = e.target as UmbTreeElement; + //TODO: Should multiple property be implemented here or be passed down into umb-tree? + this._selection = this._multiple ? element.selection : [element.selection[element.selection.length - 1]]; + } + + private _submit() { + this.modalHandler?.submit({ selection: this._selection }); + } + + private _close() { + this.modalHandler?.reject(); + } + + render() { + return html` + + + +
+ Code editor? +
+
+ + +
+
+ `; + } +} + +export default UmbTemplateModalElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-template-modal': UmbTemplateModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/document-type.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/document-type.data.ts index b02af718db..1f418b6b0c 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/document-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/document-type.data.ts @@ -890,8 +890,12 @@ export const data: Array = [ }, }, { - allowedTemplateKeys: [], - defaultTemplateKey: null, + allowedTemplateKeys: [ + '2bf464b6-3aca-4388-b043-4eb439cc2643', + '9a84c0b3-03b4-4dd4-84ac-706740ac0f71', + '9a84c0b3-03b4-4dd4-84ac-706740ac0f72', + ], + defaultTemplateKey: '2bf464b6-3aca-4388-b043-4eb439cc2643', key: 'simple-document-type-key', alias: 'simpleDocumentType', name: 'Simple Document Type', From 6df715f4ac4f41cf6513859e9a792c06b5c05eae Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 12:32:51 +0100 Subject: [PATCH 018/114] add option to pass props to an extension slot element --- .../extension-slot/extension-slot.element.ts | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/extension-slot/extension-slot.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/extension-slot/extension-slot.element.ts index ff7e0176de..4ef98f15eb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/extension-slot/extension-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/extension-slot/extension-slot.element.ts @@ -4,7 +4,11 @@ import type { TemplateResult } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { map } from 'rxjs'; import { repeat } from 'lit/directives/repeat.js'; -import { createExtensionElement, isManifestElementableType, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; +import { + createExtensionElement, + isManifestElementableType, + umbExtensionsRegistry, +} from '@umbraco-cms/backoffice/extensions-api'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; export type InitializedExtension = { alias: string; weight: number; component: HTMLElement | null }; @@ -34,6 +38,16 @@ export class UmbExtensionSlotElement extends UmbLitElement { @property({ type: Object, attribute: false }) public filter: (manifest: any) => boolean = () => true; + private _props?: Record = {}; + @property({ type: Object, attribute: false }) + get props() { + return this._props; + } + set props(newVal) { + this._props = newVal; + this.#assignPropsToAllComponents(); + } + @property({ type: String, attribute: 'default-element' }) public defaultElement = ''; @@ -77,6 +91,7 @@ export class UmbExtensionSlotElement extends UmbLitElement { // TODO: Lets make an console.error in this case? } if (component) { + this.#assignProps(component); (component as any).manifest = extension; extensionObject.component = component; @@ -95,6 +110,18 @@ export class UmbExtensionSlotElement extends UmbLitElement { ); } + #assignPropsToAllComponents() { + this._extensions.forEach((ext) => this.#assignProps(ext.component)); + } + + #assignProps = (component: HTMLElement | null) => { + if (!component || !this._props) return; + + Object.keys(this._props).forEach((key) => { + (component as any)[key] = this._props?.[key]; + }); + }; + render() { // TODO: check if we can use repeat directly. return repeat( From 0fc5a1d09997aa6d979f73ec47d4499666ea151e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 12:33:25 +0100 Subject: [PATCH 019/114] add tree item element to render tree item extensions --- .../tree/tree-item/tree-item.element.ts | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts new file mode 100644 index 0000000000..462921d54d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts @@ -0,0 +1,29 @@ +import { css, html } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property } from 'lit/decorators.js'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { EntityTreeItemResponseModel } from 'libs/backend-api/src'; +import { ManifestTreeItem } from 'libs/extensions-registry/tree-item.models'; + +@customElement('umb-tree-item') +export class UmbTreeItemElement extends UmbLitElement { + static styles = [UUITextStyles, css``]; + + @property({ type: Object, attribute: false }) + item?: EntityTreeItemResponseModel; + + render() { + return html` manifests.conditions.entityType === this.item?.type} + .props=${{ + item: this.item, + }}>`; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-tree-item': UmbTreeItemElement; + } +} From 95b2febcde96b18928a8ebaa17d8853b302e11e1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 12:33:52 +0100 Subject: [PATCH 020/114] use tree item element in tree element --- .../src/backoffice/shared/components/tree/tree.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts index 25e34c849d..3466abc60b 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts @@ -8,6 +8,7 @@ import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import './tree-item/tree-item.element'; import './tree-item-base/tree-item-base.element'; import './context-menu/tree-context-menu-page.service'; import './context-menu/tree-context-menu.service'; @@ -118,7 +119,7 @@ export class UmbTreeElement extends UmbLitElement { this._items, // TODO: add getUnique to a repository interface (item, index) => index, - (item) => html`` + (item) => html`` )} `; } From 89f5832d2c9c2fbf208a765d709d0620c01926e7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 12:36:32 +0100 Subject: [PATCH 021/114] Make tree item context self-providing --- .../tree/tree-item-base/tree-item-base.context.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts index d7c6b91b7e..b3560cbbc7 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts @@ -7,7 +7,11 @@ import { UmbSectionContext, UMB_SECTION_CONTEXT_TOKEN } from '../../section/sect import { UmbTreeContextBase } from '../tree.context'; import { BooleanState, StringState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; -import { UmbContextConsumerController, UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import { + UmbContextConsumerController, + UmbContextProviderController, + UmbContextToken, +} from '@umbraco-cms/backoffice/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import type { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; @@ -66,6 +70,8 @@ export class UmbTreeItemContextBase Date: Thu, 23 Mar 2023 13:00:06 +0100 Subject: [PATCH 022/114] add entity tree item kind --- .../documents/documents/tree/manifests.ts | 2 +- .../backoffice/media/media/tree/manifests.ts | 14 +++++- .../src/backoffice/shared/components/index.ts | 1 + .../entity-tree-item.context.ts | 10 ++++ .../entity-tree-item.element.ts | 41 ++++++++++++++++ .../tree-item-base/tree-item-base.context.ts | 49 +++++++++++-------- .../tree-item-base/tree-item-base.element.ts | 4 +- 7 files changed, 95 insertions(+), 26 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts index ee92e43e8d..f3a852ed7d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts @@ -14,9 +14,9 @@ const tree: ManifestTree = { const treeItem: ManifestTreeItem = { type: 'treeItem', + kind: 'entity', alias: 'Umb.TreeItem.Document', name: 'Document Tree Item', - loader: () => import('./tree-item/document-tree-item.element'), conditions: { entityType: 'document', }, diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/tree/manifests.ts index 6f40b6d6ee..b3aa588fdf 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/tree/manifests.ts @@ -1,5 +1,5 @@ import { UmbMediaRepository } from '../repository/media.repository'; -import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; +import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const treeAlias = 'Umb.Tree.Media'; @@ -12,4 +12,14 @@ const tree: ManifestTree = { }, }; -export const manifests = [tree]; +const treeItem: ManifestTreeItem = { + type: 'treeItem', + kind: 'entity', + alias: 'Umb.TreeItem.Media', + name: 'Media Tree Item', + conditions: { + entityType: 'media', + }, +}; + +export const manifests = [tree, treeItem]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts index 6bdba312a4..d3ce0e6ae5 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts @@ -34,6 +34,7 @@ import './section/section-sidebar/section-sidebar.element'; import './section/section.element'; import './table/table.element'; import './tree/tree.element'; +import './tree/entity-tree-item/entity-tree-item.element'; import './tree/tree-menu-item/tree-menu-item.element'; import './variantable-property/variantable-property.element'; import './workspace/workspace-action-menu/workspace-action-menu.element'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.context.ts new file mode 100644 index 0000000000..934cd4b874 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.context.ts @@ -0,0 +1,10 @@ +import { UmbTreeItemContextBase } from '../tree-item-base/tree-item-base.context'; +import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; +import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; + +// TODO get unique method from an entity repository static method +export class UmbEntityTreeItemContext extends UmbTreeItemContextBase { + constructor(host: UmbControllerHostInterface, treeItem: EntityTreeItemResponseModel) { + super(host, treeItem, (x: EntityTreeItemResponseModel) => x.key); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.element.ts new file mode 100644 index 0000000000..7540c8156c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.element.ts @@ -0,0 +1,41 @@ +import { css, html, nothing } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property } from 'lit/decorators.js'; +import { UmbEntityTreeItemContext } from './entity-tree-item.context'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { ManifestKind } from '@umbraco-cms/backoffice/extensions-registry'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; + +// TODO: Move to separate file: +const manifest: ManifestKind = { + type: 'kind', + alias: 'Umb.Kind.EntityTreeItem', + matchKind: 'entity', + matchType: 'treeItem', + manifest: { + type: 'treeItem', + elementName: 'umb-entity-tree-item', + }, +}; +umbExtensionsRegistry.register(manifest); + +@customElement('umb-entity-tree-item') +export class UmbEntityTreeItemElement extends UmbLitElement { + static styles = [UUITextStyles, css``]; + + @property({ type: Object, attribute: false }) + item?: EntityTreeItemResponseModel; + + render() { + if (!this.item) return nothing; + new UmbEntityTreeItemContext(this, this.item); + return html``; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-entity-tree-item': UmbEntityTreeItemElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts index b3560cbbc7..298fb67aa9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts @@ -15,12 +15,18 @@ import { import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import type { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; +// add type for unique function +export type UmbTreeItemUniqueFunction = (x: T) => string | null | undefined; + export class UmbTreeItemContextBase { public host: UmbControllerHostInterface; public treeItem: T; public unique: string; public type: string; + #hasChildren = new BooleanState(false); + hasChildren = this.#hasChildren.asObservable(); + #isLoading = new BooleanState(false); isLoading = this.#isLoading.asObservable(); @@ -43,36 +49,22 @@ export class UmbTreeItemContextBase string | null | undefined) { + constructor(host: UmbControllerHostInterface, treeItem: T, getUniqueFunction: UmbTreeItemUniqueFunction) { this.host = host; this.treeItem = treeItem; - const unique = getUnique(this.treeItem); + const unique = getUniqueFunction(this.treeItem); if (!unique) throw new Error('Could not create tree item context, unique key is missing'); this.unique = unique; if (!this.treeItem.type) throw new Error('Could not create tree item context, tree item type is missing'); - this.type = this.treeItem.type; - new UmbContextConsumerController(host, UMB_SECTION_CONTEXT_TOKEN, (instance) => { - this.#sectionContext = instance; - this.#observeSectionPath(); - }); - - new UmbContextConsumerController(host, UMB_SECTION_SIDEBAR_CONTEXT_TOKEN, (instance) => { - this.#sectionSidebarContext = instance; - }); - - new UmbContextConsumerController(host, 'umbTreeContext', (treeContext: UmbTreeContextBase) => { - this.treeContext = treeContext; - this.#observeIsSelectable(); - this.#observeIsSelected(); - }); - - new UmbContextProviderController(host, UMB_TREE_ITEM_CONTEXT_TOKEN, this); - this.#observeTreeItemActions(); + this.#hasChildren.next(this.treeItem.hasChildren || false); + + this.#consumeContexts(); + new UmbContextProviderController(host, UMB_TREE_ITEM_CONTEXT_TOKEN, this); } public async requestChildren() { @@ -95,6 +87,23 @@ export class UmbTreeItemContextBase { + this.#sectionContext = instance; + this.#observeSectionPath(); + }); + + new UmbContextConsumerController(this.host, UMB_SECTION_SIDEBAR_CONTEXT_TOKEN, (instance) => { + this.#sectionSidebarContext = instance; + }); + + new UmbContextConsumerController(this.host, 'umbTreeContext', (treeContext: UmbTreeContextBase) => { + this.treeContext = treeContext; + this.#observeIsSelectable(); + this.#observeIsSelected(); + }); + } + #observeIsSelectable() { if (!this.treeContext) return; new UmbObserverController(this.host, this.treeContext.selectable, (value) => this.#isSelectable.next(value)); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts index 601bb816a4..54f8f9d397 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts @@ -22,9 +22,6 @@ export class UmbTreeItemBaseElement extends UmbLitElement { this.requestUpdate('item', oldVal); } - @property({ type: Boolean, attribute: 'has-children' }) - hasChildren = false; - @state() private _childItems?: EntityTreeItemResponseModel[]; @@ -52,6 +49,7 @@ export class UmbTreeItemBaseElement extends UmbLitElement { this.#treeItemContext = instance; if (!this.#treeItemContext) return; // TODO: investigate if we can make an observe decorator + this.observe(this.#treeItemContext.hasChildren, (value) => (this.hasChildren = value)); this.observe(this.#treeItemContext.isLoading, (value) => (this._isLoading = value)); this.observe(this.#treeItemContext.isSelectable, (value) => (this._isSelectable = value)); this.observe(this.#treeItemContext.isSelected, (value) => (this._isSelected = value)); From dacafd3746f044af9aadcc49771228dce290fa1c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 13:02:02 +0100 Subject: [PATCH 023/114] add state for has children --- .../tree/tree-item-base/tree-item-base.element.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts index 54f8f9d397..0513801269 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts @@ -40,6 +40,9 @@ export class UmbTreeItemBaseElement extends UmbLitElement { @state() private _hasActions = false; + @state() + private _hasChildren = false; + #treeItemContext?: UmbTreeItemContextBase; constructor() { @@ -49,7 +52,7 @@ export class UmbTreeItemBaseElement extends UmbLitElement { this.#treeItemContext = instance; if (!this.#treeItemContext) return; // TODO: investigate if we can make an observe decorator - this.observe(this.#treeItemContext.hasChildren, (value) => (this.hasChildren = value)); + this.observe(this.#treeItemContext.hasChildren, (value) => (this._hasChildren = value)); this.observe(this.#treeItemContext.isLoading, (value) => (this._isLoading = value)); this.observe(this.#treeItemContext.isSelectable, (value) => (this._isSelectable = value)); this.observe(this.#treeItemContext.isSelected, (value) => (this._isSelected = value)); @@ -102,7 +105,7 @@ export class UmbTreeItemBaseElement extends UmbLitElement { ?selectable=${this._isSelectable} ?selected=${this._isSelected} .loading=${this._isLoading} - .hasChildren=${this.hasChildren} + .hasChildren=${this._hasChildren} label="${ifDefined(this.item?.name)}" href="${ifDefined(this._href)}"> ${this.#renderIcon()} ${this.#renderActions()} ${this.#renderChildItems()} From 5c5078ce088f61a7afc045c7004e540a340727b2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 13:13:01 +0100 Subject: [PATCH 024/114] use tree-item for child items so they also get rendered with the correct extension --- .../components/tree/tree-item-base/tree-item-base.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts index 0513801269..8b78c6586f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts @@ -138,7 +138,7 @@ export class UmbTreeItemBaseElement extends UmbLitElement { ? repeat( this._childItems, (item) => item.key, - (item) => html`` + (item) => html`` ) : ''} `; From 525ad12bf036f2d93bd954ea5990b879bf60e68a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 13:29:49 +0100 Subject: [PATCH 025/114] add temp entity tree item manifest for all tree items --- .../documents/document-types/tree/manifests.ts | 14 ++++++++++++-- .../backoffice/media/media-types/tree/manifests.ts | 14 ++++++++++++-- .../members/member-groups/tree/manifests.ts | 14 ++++++++++++-- .../members/member-types/tree/manifests.ts | 14 ++++++++++++-- .../backoffice/members/members/tree/manifests.ts | 14 ++++++++++++-- .../settings/data-types/tree/manifests.ts | 14 ++++++++++++-- .../settings/relation-types/tree/manifests.ts | 14 ++++++++++++-- .../templating/templates/tree/manifests.ts | 14 ++++++++++++-- .../translation/dictionary/tree/manifests.ts | 14 ++++++++++++-- 9 files changed, 108 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/tree/manifests.ts index fbe7421b2c..30b9f1493a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/tree/manifests.ts @@ -1,5 +1,5 @@ import { UmbDocumentTypeRepository } from '../repository/document-type.repository'; -import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; +import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { type: 'tree', @@ -10,4 +10,14 @@ const tree: ManifestTree = { }, }; -export const manifests = [tree]; +const treeItem: ManifestTreeItem = { + type: 'treeItem', + kind: 'entity', + alias: 'Umb.TreeItem.DocumentType', + name: 'Document Type Tree Item', + conditions: { + entityType: 'document-type', + }, +}; + +export const manifests = [tree, treeItem]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/tree/manifests.ts index 526aff49b2..164fec3904 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/tree/manifests.ts @@ -1,5 +1,5 @@ import { UmbMediaTypeRepository } from '../repository/media-type.repository'; -import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; +import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { type: 'tree', @@ -10,4 +10,14 @@ const tree: ManifestTree = { }, }; -export const manifests = [tree]; +const treeItem: ManifestTreeItem = { + type: 'treeItem', + kind: 'entity', + alias: 'Umb.TreeItem.MediaType', + name: 'Media Type Tree Item', + conditions: { + entityType: 'media-type', + }, +}; + +export const manifests = [tree, treeItem]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/tree/manifests.ts index ee8ef370fb..f4e3c2bb10 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/tree/manifests.ts @@ -1,5 +1,5 @@ import { UmbMemberGroupRepository } from '../repository/member-group.repository'; -import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; +import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const treeAlias = 'Umb.Tree.MemberGroups'; @@ -13,4 +13,14 @@ const tree: ManifestTree = { }, }; -export const manifests = [tree]; +const treeItem: ManifestTreeItem = { + type: 'treeItem', + kind: 'entity', + alias: 'Umb.TreeItem.MemberGroup', + name: 'Member Group Tree Item', + conditions: { + entityType: 'member-group', + }, +}; + +export const manifests = [tree, treeItem]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/tree/manifests.ts index 042a06d314..e15489ab38 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/tree/manifests.ts @@ -1,5 +1,5 @@ import { UmbMemberTypeRepository } from '../repository/member-type.repository'; -import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; +import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const treeAlias = 'Umb.Tree.MemberTypes'; @@ -12,4 +12,14 @@ const tree: ManifestTree = { }, }; -export const manifests = [tree]; +const treeItem: ManifestTreeItem = { + type: 'treeItem', + kind: 'entity', + alias: 'Umb.TreeItem.MemberType', + name: 'Member Type Tree Item', + conditions: { + entityType: 'member-type', + }, +}; + +export const manifests = [tree, treeItem]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/members/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/members/tree/manifests.ts index 3be0767383..00ee74f8c0 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/members/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/members/tree/manifests.ts @@ -1,5 +1,5 @@ import { UmbMemberRepository } from '../repository/member.repository'; -import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; +import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { type: 'tree', @@ -11,4 +11,14 @@ const tree: ManifestTree = { }, }; -export const manifests = [tree]; +const treeItem: ManifestTreeItem = { + type: 'treeItem', + kind: 'entity', + alias: 'Umb.TreeItem.Member', + name: 'Member Tree Item', + conditions: { + entityType: 'member', + }, +}; + +export const manifests = [tree, treeItem]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/tree/manifests.ts index 6aef98a542..253a74a011 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/tree/manifests.ts @@ -1,5 +1,5 @@ import { UmbDataTypeRepository } from '../repository/data-type.repository'; -import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; +import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { type: 'tree', @@ -10,4 +10,14 @@ const tree: ManifestTree = { }, }; -export const manifests = [tree]; +const treeItem: ManifestTreeItem = { + type: 'treeItem', + kind: 'entity', + alias: 'Umb.TreeItem.DataType', + name: 'Data Type Tree Item', + conditions: { + entityType: 'data-type', + }, +}; + +export const manifests = [tree, treeItem]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/tree/manifests.ts index 9b806c1dd6..c362124d31 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/tree/manifests.ts @@ -1,5 +1,5 @@ import { UmbRelationTypeRepository } from '../repository/relation-type.repository'; -import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; +import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { type: 'tree', @@ -10,4 +10,14 @@ const tree: ManifestTree = { }, }; -export const manifests = [tree]; +const treeItem: ManifestTreeItem = { + type: 'treeItem', + kind: 'entity', + alias: 'Umb.TreeItem.RelationType', + name: 'Relation Type Tree Item', + conditions: { + entityType: 'relation-type', + }, +}; + +export const manifests = [tree, treeItem]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/tree/manifests.ts index e1aff10e2f..0a9f6a445a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/tree/manifests.ts @@ -1,5 +1,5 @@ import { UmbTemplateRepository } from '../repository/template.repository'; -import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; +import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { type: 'tree', @@ -10,4 +10,14 @@ const tree: ManifestTree = { }, }; -export const manifests = [tree]; +const treeItem: ManifestTreeItem = { + type: 'treeItem', + kind: 'entity', + alias: 'Umb.TreeItem.Template', + name: 'Template Tree Item', + conditions: { + entityType: 'template', + }, +}; + +export const manifests = [tree, treeItem]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/tree/manifests.ts index 50c7f506a6..db5158f921 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/tree/manifests.ts @@ -1,5 +1,5 @@ import { UmbDictionaryRepository } from '../repository/dictionary.repository'; -import type { ManifestTree } from '@umbraco-cms/backoffice/extensions-registry'; +import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { type: 'tree', @@ -10,4 +10,14 @@ const tree: ManifestTree = { }, }; -export const manifests = [tree]; +const treeItem: ManifestTreeItem = { + type: 'treeItem', + kind: 'entity', + alias: 'Umb.TreeItem.DictionaryItem', + name: 'Dictionary Item Tree Item', + conditions: { + entityType: 'dictionary-item', + }, +}; + +export const manifests = [tree, treeItem]; From 4ab069a6146cca54f21abe66d044450e582a946c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 14:19:02 +0100 Subject: [PATCH 026/114] render temp status symbol on document tree items --- .../documents/documents/tree/manifests.ts | 2 +- .../tree-item/document-tree-item.context.ts | 10 +++++++ .../tree-item/document-tree-item.element.ts | 30 ++++++++++++------- .../tree-item-base/tree-item-base.element.ts | 25 ++++++++++++++-- 4 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.context.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts index f3a852ed7d..ee92e43e8d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts @@ -14,9 +14,9 @@ const tree: ManifestTree = { const treeItem: ManifestTreeItem = { type: 'treeItem', - kind: 'entity', alias: 'Umb.TreeItem.Document', name: 'Document Tree Item', + loader: () => import('./tree-item/document-tree-item.element'), conditions: { entityType: 'document', }, diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.context.ts new file mode 100644 index 0000000000..49c2653424 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.context.ts @@ -0,0 +1,10 @@ +import { UmbTreeItemContextBase } from '../../../../shared/components/tree/tree-item-base/tree-item-base.context'; +import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; +import { DocumentTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; + +// TODO get unique method from an document repository static method +export class UmbDocumentTreeItemContext extends UmbTreeItemContextBase { + constructor(host: UmbControllerHostInterface, treeItem: DocumentTreeItemResponseModel) { + super(host, treeItem, (x: DocumentTreeItemResponseModel) => x.key); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts index d488839fde..c24c2ddb03 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts @@ -1,6 +1,7 @@ import { css, html, nothing } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property } from 'lit/decorators.js'; +import { UmbDocumentTreeItemContext } from './document-tree-item.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { DocumentTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; @@ -9,18 +10,23 @@ export class UmbDocumentTreeItemElement extends UmbLitElement { static styles = [ UUITextStyles, css` - #label { - display: flex; - align-items: center; + #icon-container { + position: relative; + } + + #icon { + vertical-align: middle; } #status-symbol { - width: 6px; - height: 6px; + width: 8px; + height: 8px; background-color: blue; display: block; - border-radius: 3px; - margin-right: 10px; + position: absolute; + bottom: 0; + right: 0; + border-radius: 100%; } `, ]; @@ -30,12 +36,16 @@ export class UmbDocumentTreeItemElement extends UmbLitElement { render() { if (!this.item) return nothing; + new UmbDocumentTreeItemContext(this, this.item); return html` -
- - ${this.item?.name} +
+ ${this.item?.icon + ? html` + + ` + : nothing}
`; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts index 8b78c6586f..0bba8e6432 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts @@ -43,6 +43,9 @@ export class UmbTreeItemBaseElement extends UmbLitElement { @state() private _hasChildren = false; + @state() + private _iconSlotHasChildren = false; + #treeItemContext?: UmbTreeItemContextBase; constructor() { @@ -108,14 +111,32 @@ export class UmbTreeItemBaseElement extends UmbLitElement { .hasChildren=${this._hasChildren} label="${ifDefined(this.item?.name)}" href="${ifDefined(this._href)}"> - ${this.#renderIcon()} ${this.#renderActions()} ${this.#renderChildItems()} + ${this.#renderIcon()} ${this.#renderLabel()} ${this.#renderActions()} ${this.#renderChildItems()} `; } + #hasNodes = (e: Event) => { + return (e.target as HTMLSlotElement).assignedNodes({ flatten: true }).length > 0; + }; + #renderIcon() { - return html` ${this.item?.icon ? html` ` : nothing} `; + return html` + { + this._iconSlotHasChildren = this.#hasNodes(e); + }}> + ${this.item?.icon && !this._iconSlotHasChildren + ? html` ` + : nothing} + `; + } + + #renderLabel() { + return html``; } #renderActions() { From dca92f46460c8812205ce6870ded74134a7fef01 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 14:24:50 +0100 Subject: [PATCH 027/114] temp document tree item label --- .../tree-item/document-tree-item.element.ts | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts index c24c2ddb03..68ab99af32 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts @@ -39,17 +39,28 @@ export class UmbDocumentTreeItemElement extends UmbLitElement { new UmbDocumentTreeItemContext(this, this.item); return html` - -
- ${this.item?.icon - ? html` - - ` - : nothing} -
+ ${this.#renderIconWithStatusSymbol()} ${this.#renderLabel()}
`; } + + // TODO: implement correct status symbol + #renderIconWithStatusSymbol() { + return html` + + ${this.item?.icon + ? html` + + ` + : nothing} + + `; + } + + // TODO: lower opacity if item is not published + #renderLabel() { + return html` ${this.item?.name} `; + } } export default UmbDocumentTreeItemElement; From 1aef861c91bdf0dfde5a3992971c083a6fa0c18a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 23 Mar 2023 14:39:33 +0100 Subject: [PATCH 028/114] set has children to false --- src/Umbraco.Web.UI.Client/src/core/mocks/data/document.data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/document.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/document.data.ts index a99805afe0..49e4d48e49 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/document.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/document.data.ts @@ -516,7 +516,7 @@ export const treeData: Array = [ name: 'All property editors', type: 'document', icon: 'document', - hasChildren: true, + hasChildren: false, }, { $type: 'DocumentTreeItemViewModel', From b3c2bace803a172488289eed407ceca60dfc6ff0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 09:36:23 +0100 Subject: [PATCH 029/114] make tree store a generic --- .../libs/store/tree-store-base.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/store/tree-store-base.ts b/src/Umbraco.Web.UI.Client/libs/store/tree-store-base.ts index 7b2f35893e..8a7647d015 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/tree-store-base.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/tree-store-base.ts @@ -9,25 +9,27 @@ import { UmbStoreBase } from '@umbraco-cms/backoffice/store'; * @description - General Tree Data Store */ // TODO: consider if tree store could be turned into a general EntityTreeStore class? -export class UmbTreeStoreBase extends UmbStoreBase { - #data = new ArrayState([], (x) => x.key); +export class UmbTreeStoreBase< + T extends EntityTreeItemResponseModel = EntityTreeItemResponseModel +> extends UmbStoreBase { + #data = new ArrayState([], (x) => x.key); /** * Appends items to the store - * @param {Array} items + * @param {Array} items * @memberof UmbTreeStoreBase */ - appendItems(items: Array) { + appendItems(items: Array) { this.#data.append(items); } /** * Updates an item in the store * @param {string} key - * @param {Partial} data + * @param {Partial} data * @memberof UmbTreeStoreBase */ - updateItem(key: string, data: Partial) { + updateItem(key: string, data: Partial) { this.#data.next(partialUpdateFrozenArray(this.#data.getValue(), data, (entry) => entry.key === key)); } From 0dcbd7b5e72d7d79fdbfdec4e5afd337dcbf9e53 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 09:37:11 +0100 Subject: [PATCH 030/114] make tree data source a generic --- .../repository/repository-tree-data-source.interface.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts index c131d41fff..5c8290dd11 100644 --- a/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts @@ -1,8 +1,8 @@ import { EntityTreeItemResponseModel, PagedEntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository'; -export interface RepositoryTreeDataSource { - getRootItems(): Promise>; - getChildrenOf(parentKey: string): Promise>; +export interface RepositoryTreeDataSource { + getRootItems(): Promise>; + getChildrenOf(parentKey: string): Promise>; getItems(key: Array): Promise>; } From bc350d07af7c13e89755788c7c6b83d255d40dc6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 09:38:02 +0100 Subject: [PATCH 031/114] add stylesheet request interceptors --- .../core/mocks/domains/stylesheet.handlers.ts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/domains/stylesheet.handlers.ts diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/stylesheet.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/stylesheet.handlers.ts new file mode 100644 index 0000000000..b7ddf60b0c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/stylesheet.handlers.ts @@ -0,0 +1,34 @@ +import { rest } from 'msw'; +import { umbStylesheetData } from '../data/stylesheet.data'; +import { umbracoPath } from '@umbraco-cms/backoffice/utils'; + +export const handlers = [ + rest.get(umbracoPath('/tree/stylesheet/root'), (req, res, ctx) => { + const response = umbStylesheetData.getTreeRoot(); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get(umbracoPath('/tree/stylesheet/children'), (req, res, ctx) => { + const path = req.url.searchParams.get('path'); + if (!path) return; + + const response = umbStylesheetData.getTreeItemChildren(path); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get(umbracoPath('/tree/stylesheet/item'), (req, res, ctx) => { + const paths = req.url.searchParams.getAll('paths'); + if (!paths) return; + + const items = umbStylesheetData.getTreeItem(paths); + return res(ctx.status(200), ctx.json(items)); + }), + + rest.get(umbracoPath('/stylesheet/:path'), (req, res, ctx) => { + const path = req.params.path as string; + if (!path) return; + + const response = umbStylesheetData.getByPath(path); + return res(ctx.status(200), ctx.json(response)); + }), +]; From 4c40a661e5ec063416787e0bd1ce3caac3c5e566 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 09:57:05 +0100 Subject: [PATCH 032/114] remove unused handler --- .../src/core/mocks/domains/stylesheet.handlers.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/stylesheet.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/stylesheet.handlers.ts index b7ddf60b0c..ef252a199e 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/stylesheet.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/stylesheet.handlers.ts @@ -23,12 +23,4 @@ export const handlers = [ const items = umbStylesheetData.getTreeItem(paths); return res(ctx.status(200), ctx.json(items)); }), - - rest.get(umbracoPath('/stylesheet/:path'), (req, res, ctx) => { - const path = req.params.path as string; - if (!path) return; - - const response = umbStylesheetData.getByPath(path); - return res(ctx.status(200), ctx.json(response)); - }), ]; From e1e4df2c4516724c76876b568f653a2f4ceda844 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 09:57:18 +0100 Subject: [PATCH 033/114] import stylesheet handlers --- src/Umbraco.Web.UI.Client/src/core/mocks/browser-handlers.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/browser-handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/browser-handlers.ts index 1219928040..a756d4c727 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/browser-handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/browser-handlers.ts @@ -28,6 +28,7 @@ import { handlers as redirectManagementHandlers } from './domains/redirect-manag import { handlers as logViewerHandlers } from './domains/log-viewer.handlers'; import { handlers as packageHandlers } from './domains/package.handlers'; import { handlers as rteEmbedHandlers } from './domains/rte-embed.handlers'; +import { handlers as stylesheetHandlers } from './domains/stylesheet.handlers'; const handlers = [ serverHandlers.serverVersionHandler, @@ -59,6 +60,7 @@ const handlers = [ ...logViewerHandlers, ...packageHandlers, ...rteEmbedHandlers, + ...stylesheetHandlers, ]; switch (import.meta.env.VITE_UMBRACO_INSTALL_STATUS) { From 4cfcd21364c23888a660fcf80333766b03ef9c71 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 09:57:41 +0100 Subject: [PATCH 034/114] add mocked stylesheet data + mocked db --- .../src/core/mocks/data/stylesheet.data.ts | 80 +++++++++++++++++++ .../src/core/mocks/data/utils.ts | 12 ++- 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/data/stylesheet.data.ts diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/stylesheet.data.ts new file mode 100644 index 0000000000..96da26036b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/stylesheet.data.ts @@ -0,0 +1,80 @@ +import { UmbEntityData } from './entity.data'; +import { createFileSystemTreeItem } from './utils'; +import { + FileSystemTreeItemPresentationModel, + PagedFileSystemTreeItemPresentationModel, +} from '@umbraco-cms/backoffice/backend-api'; + +type StylesheetDBItem = FileSystemTreeItemPresentationModel & { + content: string; +}; + +export const data: Array = [ + { + path: 'Stylesheet File 1.css', + isFolder: false, + name: 'Stylesheet File 1.css', + type: 'stylesheet', + icon: 'icon-brackets', + hasChildren: false, + content: `Stylesheet content 1`, + }, + { + path: 'Stylesheet File 2.css', + isFolder: false, + name: 'Stylesheet File 2.css', + type: 'stylesheet', + icon: 'icon-brackets', + hasChildren: false, + content: `Stylesheet content 2`, + }, + { + path: 'Folder 1', + isFolder: true, + name: 'Folder 1', + type: 'stylesheet', + icon: 'icon-folder', + hasChildren: false, + content: `Stylesheet content 3`, + }, + { + path: 'Folder 1/Stylesheet File 3.css', + isFolder: false, + name: 'Stylesheet File 3.css', + type: 'stylesheet', + icon: 'icon-brackets', + hasChildren: false, + content: `Stylesheet content 3`, + }, +]; + +// Temp mocked database +// TODO: all properties are optional in the server schema. I don't think this is correct. +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +class UmbStylesheetData extends UmbEntityData { + constructor() { + super(data); + } + + getTreeRoot(): PagedFileSystemTreeItemPresentationModel { + const items = this.data.filter((item) => item.path === item.name); + const treeItems = items.map((item) => createFileSystemTreeItem(item)); + const total = items.length; + return { items: treeItems, total }; + } + + getTreeItemChildren(parentPath: string): PagedFileSystemTreeItemPresentationModel { + const items = this.data.filter((item) => item.path?.startsWith(parentPath)); + const treeItems = items.map((item) => createFileSystemTreeItem(item)); + const total = items.length; + return { items: treeItems, total }; + } + + getTreeItem(paths: Array): Array { + const items = this.data.filter((item) => paths.includes(item.path ?? '')); + return items.map((item) => createFileSystemTreeItem(item)); + } +} + +export const umbStylesheetData = new UmbStylesheetData(); diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/utils.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/utils.ts index 257b43976e..325e8e46b0 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/utils.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/utils.ts @@ -6,6 +6,7 @@ import type { FolderTreeItemResponseModel, DocumentTypeResponseModel, DocumentResponseModel, + FileSystemTreeItemPresentationModel, } from '@umbraco-cms/backoffice/backend-api'; export const createEntityTreeItem = (item: any): EntityTreeItemResponseModel => { @@ -38,7 +39,9 @@ export const createContentTreeItem = (item: any): ContentTreeItemResponseModel & }; // TODO: remove isTrashed type extension when we have found a solution to trashed items -export const createDocumentTreeItem = (item: DocumentResponseModel): DocumentTreeItemResponseModel & { isTrashed: boolean } => { +export const createDocumentTreeItem = ( + item: DocumentResponseModel +): DocumentTreeItemResponseModel & { isTrashed: boolean } => { return { ...createContentTreeItem(item), /* @@ -57,3 +60,10 @@ export const createDocumentTypeTreeItem = (item: DocumentTypeResponseModel): Doc isElement: item.isElement, }; }; + +export const createFileSystemTreeItem = (item: any): FileSystemTreeItemPresentationModel => { + return { + ...createFolderTreeItem(item), + path: item.path, + }; +}; From 6ee46fcc6f093ce80f2dd51b24e4f89b9e55b79e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 10:10:55 +0100 Subject: [PATCH 035/114] update types in tree repository interface --- .../repository/tree-repository.interface.ts | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/repository/tree-repository.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/tree-repository.interface.ts index a1de9f88ba..6d57205da4 100644 --- a/src/Umbraco.Web.UI.Client/libs/repository/tree-repository.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/repository/tree-repository.interface.ts @@ -1,24 +1,31 @@ import type { Observable } from 'rxjs'; -import { EntityTreeItemResponseModel, PagedEntityTreeItemResponseModel, ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; +import { + EntityTreeItemResponseModel, + PagedEntityTreeItemResponseModel, + ProblemDetailsModel, +} from '@umbraco-cms/backoffice/backend-api'; -export interface UmbTreeRepository { +export interface UmbTreeRepository< + PagedItemsType = PagedEntityTreeItemResponseModel, + ItemsType = EntityTreeItemResponseModel +> { requestRootTreeItems: () => Promise<{ - data: PagedEntityTreeItemResponseModel | undefined; + data: PagedItemsType | undefined; error: ProblemDetailsModel | undefined; - asObservable?: () => Observable; + asObservable?: () => Observable; }>; - requestTreeItemsOf: (parentKey: string | null) => Promise<{ - data: PagedEntityTreeItemResponseModel | undefined; + requestTreeItemsOf: (parentUnique: string | null) => Promise<{ + data: PagedItemsType | undefined; error: ProblemDetailsModel | undefined; - asObservable?: () => Observable; + asObservable?: () => Observable; }>; - requestTreeItems: (keys: string[]) => Promise<{ - data: Array | undefined; + requestTreeItems: (uniques: string[]) => Promise<{ + data: Array | undefined; error: ProblemDetailsModel | undefined; - asObservable?: () => Observable; + asObservable?: () => Observable; }>; - rootTreeItems: () => Promise>; - treeItemsOf: (parentKey: string | null) => Promise>; - treeItems: (keys: string[]) => Promise>; + rootTreeItems: () => Promise>; + treeItemsOf: (parentUnique: string | null) => Promise>; + treeItems: (uniques: string[]) => Promise>; } From 328693b0836a5a2a747ad2021b2174b051aba091 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 10:19:30 +0100 Subject: [PATCH 036/114] rename TreeStoreBase to EntityTreeStore --- .../libs/extensions-registry/store.models.ts | 4 ++-- .../libs/store/tree-store-base.ts | 16 ++++++++-------- .../document-blueprint.tree.store.ts | 4 ++-- .../repository/document-type.tree.store.ts | 4 ++-- .../documents/repository/document.tree.store.ts | 10 ++++------ .../repository/media-type.tree.store.ts | 6 +++--- .../media/media/repository/media.tree.store.ts | 6 +++--- .../repository/member-group.tree.store.ts | 6 +++--- .../repository/member-type.tree.store.ts | 4 ++-- .../members/repository/member.tree.store.ts | 6 +++--- .../repository/data-type.tree.store.ts | 8 +++----- .../repository/relation-type.tree.store.ts | 4 ++-- .../templates/repository/template.tree.store.ts | 8 +++----- .../repository/dictionary.tree.store.ts | 6 +++--- 14 files changed, 43 insertions(+), 49 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/extensions-registry/store.models.ts b/src/Umbraco.Web.UI.Client/libs/extensions-registry/store.models.ts index abeb6b9fda..496251134f 100644 --- a/src/Umbraco.Web.UI.Client/libs/extensions-registry/store.models.ts +++ b/src/Umbraco.Web.UI.Client/libs/extensions-registry/store.models.ts @@ -1,10 +1,10 @@ import type { ManifestClass } from './models'; -import { UmbStoreBase, UmbTreeStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbStoreBase, UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; export interface ManifestStore extends ManifestClass { type: 'store'; } -export interface ManifestTreeStore extends ManifestClass { +export interface ManifestTreeStore extends ManifestClass { type: 'treeStore'; } diff --git a/src/Umbraco.Web.UI.Client/libs/store/tree-store-base.ts b/src/Umbraco.Web.UI.Client/libs/store/tree-store-base.ts index 8a7647d015..303c13718f 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/tree-store-base.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/tree-store-base.ts @@ -4,12 +4,12 @@ import { UmbStoreBase } from '@umbraco-cms/backoffice/store'; /** * @export - * @class UmbTreeStoreBase + * @class UmbEntityTreeStore * @extends {UmbStoreBase} * @description - General Tree Data Store */ // TODO: consider if tree store could be turned into a general EntityTreeStore class? -export class UmbTreeStoreBase< +export class UmbEntityTreeStore< T extends EntityTreeItemResponseModel = EntityTreeItemResponseModel > extends UmbStoreBase { #data = new ArrayState([], (x) => x.key); @@ -17,7 +17,7 @@ export class UmbTreeStoreBase< /** * Appends items to the store * @param {Array} items - * @memberof UmbTreeStoreBase + * @memberof UmbEntityTreeStore */ appendItems(items: Array) { this.#data.append(items); @@ -27,7 +27,7 @@ export class UmbTreeStoreBase< * Updates an item in the store * @param {string} key * @param {Partial} data - * @memberof UmbTreeStoreBase + * @memberof UmbEntityTreeStore */ updateItem(key: string, data: Partial) { this.#data.next(partialUpdateFrozenArray(this.#data.getValue(), data, (entry) => entry.key === key)); @@ -36,7 +36,7 @@ export class UmbTreeStoreBase< /** * Removes an item from the store * @param {string} key - * @memberof UmbTreeStoreBase + * @memberof UmbEntityTreeStore */ removeItem(key: string) { this.#data.removeOne(key); @@ -44,7 +44,7 @@ export class UmbTreeStoreBase< /** * An observable to observe the root items - * @memberof UmbTreeStoreBase + * @memberof UmbEntityTreeStore */ rootItems = this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === null)); @@ -52,7 +52,7 @@ export class UmbTreeStoreBase< * Returns an observable to observe the children of a given parent * @param {(string | null)} parentKey * @return {*} - * @memberof UmbTreeStoreBase + * @memberof UmbEntityTreeStore */ childrenOf(parentKey: string | null) { return this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === parentKey)); @@ -62,7 +62,7 @@ export class UmbTreeStoreBase< * Returns an observable to observe the items with the given keys * @param {Array} keys * @return {*} - * @memberof UmbTreeStoreBase + * @memberof UmbEntityTreeStore */ items(keys: Array) { return this.#data.getObservablePart((items) => items.filter((item) => keys.includes(item.key ?? ''))); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-blueprints/document-blueprint.tree.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-blueprints/document-blueprint.tree.store.ts index fb1968d7a2..cbb0c01bbb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-blueprints/document-blueprint.tree.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-blueprints/document-blueprint.tree.store.ts @@ -1,5 +1,5 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import { UmbTreeStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; import type { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; export const UMB_DOCUMENT_BLUEPRINT_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken( @@ -12,7 +12,7 @@ export const UMB_DOCUMENT_BLUEPRINT_TREE_STORE_CONTEXT_TOKEN = new UmbContextTok * @extends {UmbStoreBase} * @description - Tree Data Store for Document Blueprints */ -export class UmbDocumentBlueprintTreeStore extends UmbTreeStoreBase { +export class UmbDocumentBlueprintTreeStore extends UmbEntityTreeStore { constructor(host: UmbControllerHostInterface) { super(host, UMB_DOCUMENT_BLUEPRINT_TREE_STORE_CONTEXT_TOKEN.toString()); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/document-type.tree.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/document-type.tree.store.ts index 7cfdee24df..4052a3ff76 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/document-type.tree.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/document-type.tree.store.ts @@ -1,5 +1,5 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import { UmbTreeStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; /** @@ -9,7 +9,7 @@ import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; * @description - Tree Data Store for Document-Types */ // TODO: consider if tree store could be turned into a general EntityTreeStore class? -export class UmbDocumentTypeTreeStore extends UmbTreeStoreBase { +export class UmbDocumentTypeTreeStore extends UmbEntityTreeStore { /** * Creates an instance of UmbDocumentTypeTreeStore. * @param {UmbControllerHostInterface} host diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.tree.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.tree.store.ts index 4b3bbaa7f8..4cab5a9ac3 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.tree.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.tree.store.ts @@ -1,14 +1,14 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import { UmbTreeStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; /** * @export * @class UmbDocumentTreeStore - * @extends {UmbTreeStoreBase} + * @extends {UmbEntityTreeStore} * @description - Tree Data Store for Templates */ -export class UmbDocumentTreeStore extends UmbTreeStoreBase { +export class UmbDocumentTreeStore extends UmbEntityTreeStore { /** * Creates an instance of UmbDocumentTreeStore. * @param {UmbControllerHostInterface} host @@ -19,6 +19,4 @@ export class UmbDocumentTreeStore extends UmbTreeStoreBase { } } -export const UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken( - 'UmbDocumentTreeStore' -); +export const UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken('UmbDocumentTreeStore'); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/repository/media-type.tree.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/repository/media-type.tree.store.ts index 6e6f69ed7d..3392acb8d1 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/repository/media-type.tree.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/repository/media-type.tree.store.ts @@ -1,14 +1,14 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import { UmbTreeStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; import type { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; /** * @export * @class UmbMediaTypeTreeStore - * @extends {UmbTreeStoreBase} + * @extends {UmbEntityTreeStore} * @description - Tree Data Store for Media Types */ -export class UmbMediaTypeTreeStore extends UmbTreeStoreBase { +export class UmbMediaTypeTreeStore extends UmbEntityTreeStore { /** * Creates an instance of UmbMediaTypeTreeStore. * @param {UmbControllerHostInterface} host diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.tree.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.tree.store.ts index 88903b1cb1..4214a9d7f2 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.tree.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.tree.store.ts @@ -1,7 +1,7 @@ import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { ArrayState } from '@umbraco-cms/backoffice/observable-api'; -import { UmbTreeStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; export const UMB_MEDIA_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken('UmbMediaTreeStore'); @@ -9,10 +9,10 @@ export const UMB_MEDIA_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken([], (x) => x.key); /** diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/member-group.tree.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/member-group.tree.store.ts index 1a67085088..6e20bb0447 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/member-group.tree.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/member-group.tree.store.ts @@ -1,14 +1,14 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import { UmbTreeStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; import type { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; /** * @export * @class UmbMemberGroupTreeStore - * @extends {UmbTreeStoreBase} + * @extends {UmbEntityTreeStore} * @description - Tree Data Store for Member Groups */ -export class UmbMemberGroupTreeStore extends UmbTreeStoreBase { +export class UmbMemberGroupTreeStore extends UmbEntityTreeStore { /** * Creates an instance of UmbMemberGroupTreeStore. * @param {UmbControllerHostInterface} host diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/member-type.tree.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/member-type.tree.store.ts index f008de15aa..8fb32d6bea 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/member-type.tree.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/member-type.tree.store.ts @@ -1,5 +1,5 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import { UmbTreeStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; import type { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; /** @@ -8,7 +8,7 @@ import type { UmbControllerHostInterface } from '@umbraco-cms/backoffice/control * @extends {UmbStoreBase} * @description - Tree Data Store for Member Types */ -export class UmbMemberTypeTreeStore extends UmbTreeStoreBase { +export class UmbMemberTypeTreeStore extends UmbEntityTreeStore { constructor(host: UmbControllerHostInterface) { super(host, UMB_MEMBER_TYPE_TREE_STORE_CONTEXT_TOKEN.toString()); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/members/repository/member.tree.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/members/repository/member.tree.store.ts index b315e84c5a..a5c832358e 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/members/repository/member.tree.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/members/repository/member.tree.store.ts @@ -1,5 +1,5 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import { UmbTreeStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; import type { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; export const UMB_MEMBER_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken('UmbMemberTreeStore'); @@ -7,10 +7,10 @@ export const UMB_MEMBER_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken( - 'UmbDataTypeTreeStore' -); +export const UMB_DATA_TYPE_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken('UmbDataTypeTreeStore'); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/repository/relation-type.tree.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/repository/relation-type.tree.store.ts index 0220ccaa87..b66af29604 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/repository/relation-type.tree.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/repository/relation-type.tree.store.ts @@ -1,6 +1,6 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; -import { UmbTreeStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; /** * @export @@ -9,7 +9,7 @@ import { UmbTreeStoreBase } from '@umbraco-cms/backoffice/store'; * @description - Tree Data Store for relation-types */ // TODO: consider if tree store could be turned into a general EntityTreeStore class? -export class UmbRelationTypeTreeStore extends UmbTreeStoreBase { +export class UmbRelationTypeTreeStore extends UmbEntityTreeStore { /** * Creates an instance of UmbRelationTypeTreeStore. * @param {UmbControllerHostInterface} host diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/repository/template.tree.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/repository/template.tree.store.ts index ecbe8c9031..b606566c98 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/repository/template.tree.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/repository/template.tree.store.ts @@ -1,10 +1,8 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import { UmbTreeStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; import type { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; -export const UMB_TEMPLATE_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken( - 'UmbTemplateTreeStore' -); +export const UMB_TEMPLATE_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken('UmbTemplateTreeStore'); /** * @export @@ -12,7 +10,7 @@ export const UMB_TEMPLATE_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken Date: Fri, 24 Mar 2023 10:23:03 +0100 Subject: [PATCH 037/114] align file name with new class name --- .../libs/store/{tree-store-base.ts => entity-tree-store.ts} | 0 src/Umbraco.Web.UI.Client/libs/store/index.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/Umbraco.Web.UI.Client/libs/store/{tree-store-base.ts => entity-tree-store.ts} (100%) diff --git a/src/Umbraco.Web.UI.Client/libs/store/tree-store-base.ts b/src/Umbraco.Web.UI.Client/libs/store/entity-tree-store.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/libs/store/tree-store-base.ts rename to src/Umbraco.Web.UI.Client/libs/store/entity-tree-store.ts diff --git a/src/Umbraco.Web.UI.Client/libs/store/index.ts b/src/Umbraco.Web.UI.Client/libs/store/index.ts index 865fdf2b5a..54a2a8d327 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/index.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/index.ts @@ -1,3 +1,3 @@ export * from './store'; export * from './store-base'; -export * from './tree-store-base'; +export * from './entity-tree-store'; From baebfb55defb7f254b9e263a62d39e2b64d1082d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 10:44:04 +0100 Subject: [PATCH 038/114] remove current tree store interface --- src/Umbraco.Web.UI.Client/libs/store/store.ts | 29 ------------------- .../shared/collection/collection.context.ts | 12 +++----- .../dashboard-collection.element.ts | 2 +- .../workspace-view-collection.element.ts | 2 +- 4 files changed, 6 insertions(+), 39 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/store/store.ts b/src/Umbraco.Web.UI.Client/libs/store/store.ts index 083cc9fc2f..d4af9c2275 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/store.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/store.ts @@ -9,33 +9,7 @@ export interface UmbDataStore { readonly storeAlias: string; } -export interface UmbTreeStore extends UmbDataStore { - - getTreeRoot(): Observable>; - - getTreeItemChildren(key: string): Observable>; - - // Notice: this might not be right to put here as only some content items has ability to be trashed. - /** - * @description - Trash data. - * @param {string[]} keys - * @return {*} {(Promise)} - * @memberof UmbTreeStore - */ - trash(keys: string[]): Promise; - - // Notice: this might not be right to put here as only some content items has ability to be moved. - /** - * @description - Move data. - * @param {string[]} keys - * @return {*} {(Promise)} - * @memberof UmbTreeStore - */ - move(keys: string[], destination: string): Promise; -} - export interface UmbEntityDetailStore extends UmbDataStore { - /** * @description - Request scaffold data by entityType and . The data is added to the store and is returned as an Observable. * @param {string} key @@ -61,10 +35,7 @@ export interface UmbEntityDetailStore extends UmbDataStore { save(data: T[]): Promise; } - export interface UmbContentStore extends UmbEntityDetailStore { - // TODO: make something that is specific for UmbContentStore, or then we should get rid of it. But for now i kept it as we might want this for rollback or other things specific to Content types. save(data: T[]): Promise; - } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/collection/collection.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/collection/collection.context.ts index 4347266039..d698ed1f71 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/collection/collection.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/collection/collection.context.ts @@ -1,6 +1,5 @@ import { Observable } from 'rxjs'; import type { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; -import type { UmbTreeStore } from '@umbraco-cms/backoffice/store'; import type { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbContextToken, UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { ArrayState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; @@ -9,17 +8,14 @@ import { createExtensionClass } from 'libs/extensions-api/create-extension-class import { UmbTreeRepository } from '@umbraco-cms/backoffice/repository'; // TODO: Clean up the need for store as Media has switched to use Repositories(repository). -export class UmbCollectionContext< - DataType extends EntityTreeItemResponseModel = EntityTreeItemResponseModel, - StoreType extends UmbTreeStore = UmbTreeStore -> { +export class UmbCollectionContext { private _host: UmbControllerHostInterface; private _entityType: string | null; private _entityKey: string | null; #repository?: UmbTreeRepository; - private _store?: StoreType; + private _store?: any; protected _dataObserver?: UmbObserverController; #data = new ArrayState(>[]); @@ -46,7 +42,7 @@ export class UmbCollectionContext< this._entityKey = entityKey; if (storeAlias) { - new UmbContextConsumerController(this._host, storeAlias, (_instance: StoreType) => { + new UmbContextConsumerController(this._host, storeAlias, (_instance) => { this._store = _instance; if (!this._store) { // TODO: if we keep the type assumption of _store existing, then we should here make sure to break the application in a good way. @@ -175,4 +171,4 @@ export class UmbCollectionContext< } } -export const UMB_COLLECTION_CONTEXT_TOKEN = new UmbContextToken>('UmbCollectionContext'); +export const UMB_COLLECTION_CONTEXT_TOKEN = new UmbContextToken>('UmbCollectionContext'); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/collection/dashboards/dashboard-collection.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/collection/dashboards/dashboard-collection.element.ts index 5c21bbee38..2c96968191 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/collection/dashboards/dashboard-collection.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/collection/dashboards/dashboard-collection.element.ts @@ -25,7 +25,7 @@ export class UmbDashboardCollectionElement extends UmbLitElement { ]; // TODO: Use the right type here: - private _collectionContext?: UmbCollectionContext; + private _collectionContext?: UmbCollectionContext; public manifest!: ManifestDashboardCollection; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-content/views/collection/workspace-view-collection.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-content/views/collection/workspace-view-collection.element.ts index a5a5be1fec..b6c42e1de1 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-content/views/collection/workspace-view-collection.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-content/views/collection/workspace-view-collection.element.ts @@ -30,7 +30,7 @@ export class UmbWorkspaceViewCollectionElement extends UmbLitElement { private _workspaceContext?: UmbEntityWorkspaceContextInterface; // TODO: add type for the collection context. - private _collectionContext?: UmbCollectionContext; + private _collectionContext?: UmbCollectionContext; constructor() { super(); From eaa27d8257f5fcce445a4542b7ad6eac526cbcd7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 10:44:19 +0100 Subject: [PATCH 039/114] add new tree store interface --- .../libs/store/tree-store.interface.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts diff --git a/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts b/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts new file mode 100644 index 0000000000..3dcf6529c5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts @@ -0,0 +1,11 @@ +import type { Observable } from 'rxjs'; + +export interface UmbTreeStore { + appendItems: (items: Array) => void; + updateItem: (unique: string, item: Partial) => void; + removeItem: (unique: string) => void; + + rootItems: () => Observable>; + childrenOf: (parentUnique: string | null) => Observable>; + treeItems: (uniques: Array) => Observable>; +} From 72221bf8986e37355c18413af020008e2a95da16 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 10:44:50 +0100 Subject: [PATCH 040/114] export tree store interface from module --- src/Umbraco.Web.UI.Client/libs/store/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/libs/store/index.ts b/src/Umbraco.Web.UI.Client/libs/store/index.ts index 54a2a8d327..cdb08c0d7c 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/index.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/index.ts @@ -1,3 +1,4 @@ export * from './store'; export * from './store-base'; export * from './entity-tree-store'; +export * from './tree-store.interface'; From c008d71bb3bfd54611d2c53369fd41c6a2d99e50 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 10:46:31 +0100 Subject: [PATCH 041/114] use tree store interface in manifest --- .../libs/extensions-registry/store.models.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/extensions-registry/store.models.ts b/src/Umbraco.Web.UI.Client/libs/extensions-registry/store.models.ts index 496251134f..18e8c10c17 100644 --- a/src/Umbraco.Web.UI.Client/libs/extensions-registry/store.models.ts +++ b/src/Umbraco.Web.UI.Client/libs/extensions-registry/store.models.ts @@ -1,10 +1,10 @@ import type { ManifestClass } from './models'; -import { UmbStoreBase, UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; +import { UmbStoreBase, UmbTreeStore } from '@umbraco-cms/backoffice/store'; export interface ManifestStore extends ManifestClass { type: 'store'; } -export interface ManifestTreeStore extends ManifestClass { +export interface ManifestTreeStore extends ManifestClass { type: 'treeStore'; } From 1ab817ab94cad3d94eb37524858284d781eb506a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 10:47:11 +0100 Subject: [PATCH 042/114] require tree items to extend TreeItemPresentationModel --- src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts b/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts index 3dcf6529c5..aaee70915e 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts @@ -1,6 +1,7 @@ import type { Observable } from 'rxjs'; +import { TreeItemPresentationModel } from '../backend-api'; -export interface UmbTreeStore { +export interface UmbTreeStore { appendItems: (items: Array) => void; updateItem: (unique: string, item: Partial) => void; removeItem: (unique: string) => void; From 749af924c2c19519fb0feaaf2d486c234b96cc2e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 10:50:00 +0100 Subject: [PATCH 043/114] root items doesn't have to be a method --- src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts b/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts index aaee70915e..a219fe0bf6 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts @@ -6,7 +6,7 @@ export interface UmbTreeStore) => void; removeItem: (unique: string) => void; - rootItems: () => Observable>; + rootItems: Observable>; childrenOf: (parentUnique: string | null) => Observable>; treeItems: (uniques: Array) => Observable>; } From b5f4e9c98acf5594f66a79de623a23d3b4dc1d75 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 10:50:47 +0100 Subject: [PATCH 044/114] rename tree items to items --- src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts b/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts index a219fe0bf6..fab7dacd17 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts @@ -8,5 +8,5 @@ export interface UmbTreeStore>; childrenOf: (parentUnique: string | null) => Observable>; - treeItems: (uniques: Array) => Observable>; + items: (uniques: Array) => Observable>; } From 88be27b387904936db5b3e92ae517c0c9ad3e561 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 10:51:22 +0100 Subject: [PATCH 045/114] add interface to entity tree store --- .../libs/store/entity-tree-store.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/store/entity-tree-store.ts b/src/Umbraco.Web.UI.Client/libs/store/entity-tree-store.ts index 303c13718f..6fb7ca7e3c 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/entity-tree-store.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/entity-tree-store.ts @@ -1,6 +1,6 @@ import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { ArrayState, partialUpdateFrozenArray } from '@umbraco-cms/backoffice/observable-api'; -import { UmbStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbStoreBase, UmbTreeStore } from '@umbraco-cms/backoffice/store'; /** * @export @@ -9,17 +9,15 @@ import { UmbStoreBase } from '@umbraco-cms/backoffice/store'; * @description - General Tree Data Store */ // TODO: consider if tree store could be turned into a general EntityTreeStore class? -export class UmbEntityTreeStore< - T extends EntityTreeItemResponseModel = EntityTreeItemResponseModel -> extends UmbStoreBase { - #data = new ArrayState([], (x) => x.key); +export class UmbEntityTreeStore extends UmbStoreBase implements UmbTreeStore { + #data = new ArrayState([], (x) => x.key); /** * Appends items to the store * @param {Array} items * @memberof UmbEntityTreeStore */ - appendItems(items: Array) { + appendItems(items: Array) { this.#data.append(items); } @@ -29,7 +27,7 @@ export class UmbEntityTreeStore< * @param {Partial} data * @memberof UmbEntityTreeStore */ - updateItem(key: string, data: Partial) { + updateItem(key: string, data: Partial) { this.#data.next(partialUpdateFrozenArray(this.#data.getValue(), data, (entry) => entry.key === key)); } From c3c3cfcf004d6a84fe47e0b02979908d08e207dc Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 10:59:31 +0100 Subject: [PATCH 046/114] remove todo --- src/Umbraco.Web.UI.Client/libs/store/entity-tree-store.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/libs/store/entity-tree-store.ts b/src/Umbraco.Web.UI.Client/libs/store/entity-tree-store.ts index 6fb7ca7e3c..1e82f6acaa 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/entity-tree-store.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/entity-tree-store.ts @@ -8,7 +8,6 @@ import { UmbStoreBase, UmbTreeStore } from '@umbraco-cms/backoffice/store'; * @extends {UmbStoreBase} * @description - General Tree Data Store */ -// TODO: consider if tree store could be turned into a general EntityTreeStore class? export class UmbEntityTreeStore extends UmbStoreBase implements UmbTreeStore { #data = new ArrayState([], (x) => x.key); From 8a675adfb228948f98ee779ccbc23ca514bc7691 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 11:09:15 +0100 Subject: [PATCH 047/114] add file system tree store class --- .../templating/file-system-tree.store.ts | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/file-system-tree.store.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/file-system-tree.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/file-system-tree.store.ts new file mode 100644 index 0000000000..eba5aee290 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/file-system-tree.store.ts @@ -0,0 +1,67 @@ +import { FileSystemTreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; +import { ArrayState, partialUpdateFrozenArray } from '@umbraco-cms/backoffice/observable-api'; +import { UmbStoreBase, UmbTreeStore } from '@umbraco-cms/backoffice/store'; + +/** + * @export + * @class UmbFileSystemTreeStore + * @extends {UmbStoreBase} + * @description - General Tree Data Store + */ +export class UmbFileSystemTreeStore extends UmbStoreBase implements UmbTreeStore { + #data = new ArrayState([], (x) => x.path); + + /** + * Appends items to the store + * @param {Array} items + * @memberof UmbFileSystemTreeStore + */ + appendItems(items: Array) { + this.#data.append(items); + } + + /** + * Updates an item in the store + * @param {string} path + * @param {Partial} data + * @memberof UmbFileSystemTreeStore + */ + updateItem(path: string, data: Partial) { + this.#data.next(partialUpdateFrozenArray(this.#data.getValue(), data, (entry) => entry.path === path)); + } + + /** + * Removes an item from the store + * @param {string} path + * @memberof UmbFileSystemTreeStore + */ + removeItem(path: string) { + this.#data.removeOne(path); + } + + /** + * An observable to observe the root items + * @memberof UmbFileSystemTreeStore + */ + rootItems = this.#data.getObservablePart((items) => items.filter((item) => item.path === item.name)); + + /** + * Returns an observable to observe the children of a given parent + * @param {(string | null)} parentPath + * @return {*} + * @memberof UmbFileSystemTreeStore + */ + childrenOf(parentPath: string | null) { + return this.#data.getObservablePart((items) => items.filter((item) => item.path?.startsWith(parentPath ?? ''))); + } + + /** + * Returns an observable to observe the items with the given keys + * @param {Array} paths + * @return {*} + * @memberof UmbFileSystemTreeStore + */ + items(paths: Array) { + return this.#data.getObservablePart((items) => items.filter((item) => paths.includes(item.path ?? ''))); + } +} From a1ee08c08b706e1472ccb2faf5501052b3b5239b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 11:10:47 +0100 Subject: [PATCH 048/114] import file system tree store from libs --- .../templating => libs/store}/file-system-tree.store.ts | 0 src/Umbraco.Web.UI.Client/libs/store/index.ts | 1 + 2 files changed, 1 insertion(+) rename src/Umbraco.Web.UI.Client/{src/backoffice/templating => libs/store}/file-system-tree.store.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/file-system-tree.store.ts b/src/Umbraco.Web.UI.Client/libs/store/file-system-tree.store.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/backoffice/templating/file-system-tree.store.ts rename to src/Umbraco.Web.UI.Client/libs/store/file-system-tree.store.ts diff --git a/src/Umbraco.Web.UI.Client/libs/store/index.ts b/src/Umbraco.Web.UI.Client/libs/store/index.ts index cdb08c0d7c..f9152d3ebd 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/index.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/index.ts @@ -1,4 +1,5 @@ export * from './store'; export * from './store-base'; export * from './entity-tree-store'; +export * from './file-system-tree.store'; export * from './tree-store.interface'; From 4ee545ef904b0b6d4ee307f185e06dff0cddf1ff Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 11:25:25 +0100 Subject: [PATCH 049/114] use TreeItem presentation model en tree item element --- .../shared/components/tree/tree-item/tree-item.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts index 462921d54d..d91f31c020 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts @@ -2,7 +2,7 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property } from 'lit/decorators.js'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { EntityTreeItemResponseModel } from 'libs/backend-api/src'; +import { TreeItemPresentationModel } from 'libs/backend-api/src'; import { ManifestTreeItem } from 'libs/extensions-registry/tree-item.models'; @customElement('umb-tree-item') @@ -10,7 +10,7 @@ export class UmbTreeItemElement extends UmbLitElement { static styles = [UUITextStyles, css``]; @property({ type: Object, attribute: false }) - item?: EntityTreeItemResponseModel; + item?: TreeItemPresentationModel; render() { return html` Date: Fri, 24 Mar 2023 11:25:46 +0100 Subject: [PATCH 050/114] use TreeItemPresentationModel in tree item base element --- .../tree/tree-item-base/tree-item-base.element.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts index 0bba8e6432..c74b4d9b8a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts @@ -5,13 +5,13 @@ import { ifDefined } from 'lit/directives/if-defined.js'; import { repeat } from 'lit/directives/repeat.js'; import { UmbTreeItemContextBase, UMB_TREE_ITEM_CONTEXT_TOKEN } from './tree-item-base.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; @customElement('umb-tree-item-base') export class UmbTreeItemBaseElement extends UmbLitElement { static styles = [UUITextStyles, css``]; - private _item?: EntityTreeItemResponseModel; + private _item?: TreeItemPresentationModel; @property({ type: Object, attribute: false }) get item() { return this._item; @@ -23,7 +23,7 @@ export class UmbTreeItemBaseElement extends UmbLitElement { } @state() - private _childItems?: EntityTreeItemResponseModel[]; + private _childItems?: TreeItemPresentationModel[]; @state() private _href?: string; @@ -158,7 +158,8 @@ export class UmbTreeItemBaseElement extends UmbLitElement { ${this._childItems ? repeat( this._childItems, - (item) => item.key, + // TODO: get unique here instead of name. we might be able to get it from the context + (item) => item.name, (item) => html`` ) : ''} From 8b982f97cbeda974022fa17184351598c108f687 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 11:26:04 +0100 Subject: [PATCH 051/114] add file system tree item --- .../file-system-tree-item.context.ts | 10 +++++ .../file-system-tree-item.element.ts | 41 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts new file mode 100644 index 0000000000..2426614064 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts @@ -0,0 +1,10 @@ +import { UmbTreeItemContextBase } from '../tree-item-base/tree-item-base.context'; +import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; +import { FileSystemTreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; + +// TODO get unique method from an entity repository static method +export class UmbFileSystemTreeItemContext extends UmbTreeItemContextBase { + constructor(host: UmbControllerHostInterface, treeItem: FileSystemTreeItemPresentationModel) { + super(host, treeItem, (x: FileSystemTreeItemPresentationModel) => x.path); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.element.ts new file mode 100644 index 0000000000..3572e6dccc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.element.ts @@ -0,0 +1,41 @@ +import { css, html, nothing } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property } from 'lit/decorators.js'; +import { UmbFileSystemTreeItemContext } from './file-system-tree-item.context'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { ManifestKind } from '@umbraco-cms/backoffice/extensions-registry'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; +import { FileSystemTreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; + +// TODO: Move to separate file: +const manifest: ManifestKind = { + type: 'kind', + alias: 'Umb.Kind.FileSystemTreeItem', + matchKind: 'fileSystem', + matchType: 'treeItem', + manifest: { + type: 'treeItem', + elementName: 'umb-file-system-tree-item', + }, +}; +umbExtensionsRegistry.register(manifest); + +@customElement('umb-file-system-tree-item') +export class UmbFileSystemTreeItemElement extends UmbLitElement { + static styles = [UUITextStyles, css``]; + + @property({ type: Object, attribute: false }) + item?: FileSystemTreeItemPresentationModel; + + render() { + if (!this.item) return nothing; + new UmbFileSystemTreeItemContext(this, this.item); + return html``; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-file-system-tree-item': UmbFileSystemTreeItemElement; + } +} From adf87cf7359563cd569245c486fddd6309d5f977 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 11:46:40 +0100 Subject: [PATCH 052/114] import file-system-tree-item --- .../src/backoffice/shared/components/index.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts index d3ce0e6ae5..c4e61d4c70 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts @@ -32,10 +32,14 @@ import './ref-property-editor-ui/ref-property-editor-ui.element'; import './section/section-main/section-main.element'; import './section/section-sidebar/section-sidebar.element'; import './section/section.element'; + import './table/table.element'; + import './tree/tree.element'; import './tree/entity-tree-item/entity-tree-item.element'; +import './tree/file-system-tree-item/file-system-tree-item.element'; import './tree/tree-menu-item/tree-menu-item.element'; + import './variantable-property/variantable-property.element'; import './workspace/workspace-action-menu/workspace-action-menu.element'; @@ -46,8 +50,8 @@ import './history/history-item.element'; import './workspace/workspace-action/workspace-action.element'; import './workspace/workspace-layout/workspace-layout.element'; -import './code-editor'; - import './workspace/workspace-footer-layout/workspace-footer-layout.element'; +import './code-editor'; + export const manifests = [...debugManifests]; From 57b1eb85b466896dbe1e048f58179419726c592f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 11:46:49 +0100 Subject: [PATCH 053/114] fix interface --- src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts b/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts index fab7dacd17..3f7440385b 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts @@ -1,7 +1,7 @@ import type { Observable } from 'rxjs'; import { TreeItemPresentationModel } from '../backend-api'; -export interface UmbTreeStore { +export interface UmbTreeStore { appendItems: (items: Array) => void; updateItem: (unique: string, item: Partial) => void; removeItem: (unique: string) => void; From ec55a8a3be1aa0976c90ea75f95d4a535e034721 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 11:50:50 +0100 Subject: [PATCH 054/114] update icons in mock data --- .../src/core/mocks/data/stylesheet.data.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/stylesheet.data.ts index 96da26036b..f5e303b893 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/stylesheet.data.ts @@ -15,7 +15,7 @@ export const data: Array = [ isFolder: false, name: 'Stylesheet File 1.css', type: 'stylesheet', - icon: 'icon-brackets', + icon: 'umb:brackets', hasChildren: false, content: `Stylesheet content 1`, }, @@ -24,7 +24,7 @@ export const data: Array = [ isFolder: false, name: 'Stylesheet File 2.css', type: 'stylesheet', - icon: 'icon-brackets', + icon: 'umb:brackets', hasChildren: false, content: `Stylesheet content 2`, }, @@ -33,8 +33,8 @@ export const data: Array = [ isFolder: true, name: 'Folder 1', type: 'stylesheet', - icon: 'icon-folder', - hasChildren: false, + icon: 'umb:folder', + hasChildren: true, content: `Stylesheet content 3`, }, { @@ -42,7 +42,7 @@ export const data: Array = [ isFolder: false, name: 'Stylesheet File 3.css', type: 'stylesheet', - icon: 'icon-brackets', + icon: 'umb:brackets', hasChildren: false, content: `Stylesheet content 3`, }, From 5fd2e93bebc7b423c017ed379b9337d215dc1ac6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 11:52:16 +0100 Subject: [PATCH 055/114] wip files for stylesheet editing --- .../src/backoffice/templating/index.ts | 3 +- .../templating/stylesheets/index.ts | 8 ++ .../templating/stylesheets/manifests.ts | 6 ++ .../stylesheets/menu-item/manifests.ts | 20 ++++ .../stylesheets/repository/manifests.ts | 25 +++++ .../sources/stylesheet.tree.server.data.ts | 53 +++++++++++ .../repository/stylesheet.repository.ts | 91 +++++++++++++++++++ .../repository/stylesheet.tree.store.ts | 24 +++++ .../templating/stylesheets/tree/manifests.ts | 27 ++++++ .../stylesheets/workspace/manifests.ts | 20 ++++ .../stylesheet-workspace-edit.element.ts | 29 ++++++ .../workspace/stylesheet-workspace.context.ts | 38 ++++++++ .../workspace/stylesheet-workspace.element.ts | 48 ++++++++++ .../workspace/stylesheet-workspace.stories.ts | 18 ++++ 14 files changed, 409 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/menu-item/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.tree.store.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/tree/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.stories.ts 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 a1d157077e..02854c3770 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/index.ts @@ -1,9 +1,10 @@ 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'; -export const manifests = [...menuManifests, ...templateManifests]; +export const manifests = [...menuManifests, ...templateManifests, ...stylesheetManifests]; const registerExtensions = (manifests: Array) => { manifests.forEach((manifest) => umbExtensionsRegistry.register(manifest)); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/index.ts new file mode 100644 index 0000000000..7d6c362f01 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/index.ts @@ -0,0 +1,8 @@ +import { FileSystemTreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; + +// TODO: temp until we have a proper stylesheet model +export interface StylesheetDetails extends FileSystemTreeItemPresentationModel { + content: string; +} + +export const STYLESHEET_ENTITY_TYPE = 'stylesheet'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/manifests.ts new file mode 100644 index 0000000000..ddaa4babdc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/manifests.ts @@ -0,0 +1,6 @@ +import { manifests as repositoryManifests } from './repository/manifests'; +import { manifests as menuItemManifests } from './menu-item/manifests'; +import { manifests as treeManifests } from './tree/manifests'; +import { manifests as workspaceManifests } from './workspace/manifests'; + +export const manifests = [...repositoryManifests, ...menuItemManifests, ...treeManifests, ...workspaceManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/menu-item/manifests.ts new file mode 100644 index 0000000000..c6ee826fc0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/menu-item/manifests.ts @@ -0,0 +1,20 @@ +import { STYLESHEET_TREE_ALIAS } from '../tree/manifests'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; + +const menuItem: ManifestTypes = { + type: 'menuItem', + kind: 'tree', + alias: 'Umb.MenuItem.Stylesheets', + name: 'Stylesheets Menu Item', + weight: 400, + meta: { + label: 'Stylesheets', + icon: 'umb:folder', + treeAlias: STYLESHEET_TREE_ALIAS, + }, + conditions: { + menus: ['Umb.Menu.Templating'], + }, +}; + +export const manifests = [menuItem]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/manifests.ts new file mode 100644 index 0000000000..34225d54b8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/manifests.ts @@ -0,0 +1,25 @@ +import { UmbStylesheetRepository } from './stylesheet.repository'; +import { UmbStylesheetTreeStore } from './stylesheet.tree.store'; +import { ManifestRepository } from 'libs/extensions-registry/repository.models'; +import { ManifestTreeStore } from '@umbraco-cms/backoffice/extensions-registry'; + +export const STYLESHEET_REPOSITORY_ALIAS = 'Umb.Repository.Stylesheet'; + +const repository: ManifestRepository = { + type: 'repository', + alias: STYLESHEET_REPOSITORY_ALIAS, + name: 'Stylesheet Repository', + class: UmbStylesheetRepository, +}; + +export const STYLESHEET_STORE_ALIAS = 'Umb.Store.Stylesheet'; +export const STYLESHEET_TREE_STORE_ALIAS = 'Umb.Store.StylesheetTree'; + +const treeStore: ManifestTreeStore = { + type: 'treeStore', + alias: STYLESHEET_TREE_STORE_ALIAS, + name: 'Stylesheet Tree Store', + class: UmbStylesheetTreeStore, +}; + +export const manifests = [treeStore, repository]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts new file mode 100644 index 0000000000..38a0e10e09 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts @@ -0,0 +1,53 @@ +import { + FileSystemTreeItemPresentationModel, + PagedFileSystemTreeItemPresentationModel, + StylesheetResource, +} from '@umbraco-cms/backoffice/backend-api'; +import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { RepositoryTreeDataSource } from 'libs/repository/repository-tree-data-source.interface'; + +/** + * A data source for the Stylesheet tree that fetches data from the server + * @export + * @class UmbStylesheetTreeServerDataSource + * @implements {RepositoryTreeDataSource} + */ +export class UmbStylesheetTreeServerDataSource + implements RepositoryTreeDataSource +{ + #host: UmbControllerHostInterface; + + /** + * Creates an instance of UmbStylesheetTreeServerDataSource. + * @param {UmbControllerHostInterface} host + * @memberof UmbStylesheetTreeServerDataSource + */ + constructor(host: UmbControllerHostInterface) { + this.#host = host; + } + + /** + * Fetches the stylesheet tree root items from the server + * @return {*} + * @memberof UmbStylesheetTreeServerDataSource + */ + async getRootItems() { + return tryExecuteAndNotify(this.#host, StylesheetResource.getTreeStylesheetRoot({})); + } + + /** + * Fetches the children of a given stylesheet path from the server + * @param {(string | undefined)} path + * @return {*} + * @memberof UmbStylesheetTreeServerDataSource + */ + async getChildrenOf(path: string | undefined) { + return tryExecuteAndNotify( + this.#host, + StylesheetResource.getTreeStylesheetChildren({ + path, + }) + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts new file mode 100644 index 0000000000..9259bd7e35 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts @@ -0,0 +1,91 @@ +import { UmbStylesheetTreeStore, UMB_STYLESHEET_TREE_STORE_CONTEXT_TOKEN } from './stylesheet.tree.store'; +import { UmbStylesheetTreeServerDataSource } from './sources/stylesheet.tree.server.data'; +import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; +import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; +import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; +import { UmbTreeRepository } from '@umbraco-cms/backoffice/repository'; +import { + FileSystemTreeItemPresentationModel, + PagedFileSystemTreeItemPresentationModel, + ProblemDetailsModel, +} from '@umbraco-cms/backoffice/backend-api'; + +export class UmbStylesheetRepository + implements UmbTreeRepository +{ + #host: UmbControllerHostInterface; + #treeDataSource: UmbStylesheetTreeServerDataSource; + #treeStore?: UmbStylesheetTreeStore; + #notificationContext?: UmbNotificationContext; + #initResolver?: () => void; + #initialized = false; + + constructor(host: UmbControllerHostInterface) { + this.#host = host; + // TODO: figure out how spin up get the correct data source + this.#treeDataSource = new UmbStylesheetTreeServerDataSource(this.#host); + + new UmbContextConsumerController(this.#host, UMB_STYLESHEET_TREE_STORE_CONTEXT_TOKEN, (instance) => { + this.#treeStore = instance; + this.#checkIfInitialized(); + }); + + new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => { + this.#notificationContext = instance; + this.#checkIfInitialized(); + }); + } + + #init = new Promise((resolve) => { + this.#initialized ? resolve() : (this.#initResolver = resolve); + }); + + #checkIfInitialized() { + if (this.#treeStore && this.#notificationContext) { + this.#initialized = true; + this.#initResolver?.(); + } + } + + async requestRootTreeItems() { + await this.#init; + + const { data, error } = await this.#treeDataSource.getRootItems(); + + if (data) { + this.#treeStore?.appendItems(data.items); + } + + return { data, error }; + } + + async requestTreeItemsOf(path: string | null) {} + + async requestTreeItems(keys: Array) { + await this.#init; + + if (!keys) { + const error: ProblemDetailsModel = { title: 'Keys are missing' }; + return { data: undefined, error }; + } + + const { data, error } = await this.#treeDataSource.getItems(keys); + + return { data, error }; + } + + async rootTreeItems() { + await this.#init; + return this.#treeStore!.rootItems; + } + + async treeItemsOf(parentKey: string | null) { + await this.#init; + return this.#treeStore!.childrenOf(parentKey); + } + + async treeItems(keys: Array) { + await this.#init; + return this.#treeStore!.items(keys); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.tree.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.tree.store.ts new file mode 100644 index 0000000000..bf7a427c5c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.tree.store.ts @@ -0,0 +1,24 @@ +import { UmbFileSystemTreeStore } from '@umbraco-cms/backoffice/store'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import type { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; + +/** + * @export + * @class UmbStylesheetTreeStore + * @extends {UmbEntityTreeStore} + * @description - Tree Data Store for Stylesheets + */ +export class UmbStylesheetTreeStore extends UmbFileSystemTreeStore { + /** + * Creates an instance of UmbStylesheetTreeStore. + * @param {UmbControllerHostInterface} host + * @memberof UmbStylesheetTreeStore + */ + constructor(host: UmbControllerHostInterface) { + super(host, UMB_STYLESHEET_TREE_STORE_CONTEXT_TOKEN.toString()); + } +} + +export const UMB_STYLESHEET_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken( + 'UmbStylesheetTreeStore' +); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/tree/manifests.ts new file mode 100644 index 0000000000..f3430be1ec --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/tree/manifests.ts @@ -0,0 +1,27 @@ +import { UmbStylesheetRepository } from '../repository/stylesheet.repository'; +import { STYLESHEET_ENTITY_TYPE } from '..'; +import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; + +export const STYLESHEET_TREE_ALIAS = 'Umb.Tree.Stylesheet'; + +const tree: ManifestTree = { + type: 'tree', + alias: STYLESHEET_TREE_ALIAS, + name: 'Stylesheet Tree', + weight: 10, + meta: { + repository: UmbStylesheetRepository, + }, +}; + +const treeItem: ManifestTreeItem = { + type: 'treeItem', + kind: 'fileSystem', + alias: 'Umb.TreeItem.Stylesheet', + name: 'Stylesheet Tree Item', + conditions: { + entityType: STYLESHEET_ENTITY_TYPE, + }, +}; + +export const manifests = [tree, treeItem]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/manifests.ts new file mode 100644 index 0000000000..ad0675cf06 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/manifests.ts @@ -0,0 +1,20 @@ +import type { + ManifestWorkspace, + ManifestWorkspaceAction, + ManifestWorkspaceView, +} from '@umbraco-cms/backoffice/extensions-registry'; + +const workspace: ManifestWorkspace = { + type: 'workspace', + alias: 'Umb.Workspace.StyleSheet', + name: 'Stylesheet Workspace', + loader: () => import('./stylesheet-workspace.element'), + meta: { + entityType: 'stylesheet', + }, +}; + +const workspaceViews: Array = []; +const workspaceActions: Array = []; + +export const manifests = [workspace, ...workspaceViews, ...workspaceActions]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts new file mode 100644 index 0000000000..a01b9dc02e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts @@ -0,0 +1,29 @@ +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { css, html, LitElement } from 'lit'; +import { customElement } from 'lit/decorators.js'; + +@customElement('umb-stylesheet-workspace-edit') +export class UmbStylesheetWorkspaceEditElement extends LitElement { + static styles = [ + UUITextStyles, + css` + :host { + display: block; + width: 100%; + height: 100%; + } + `, + ]; + + render() { + return html` Member Workspace `; + } +} + +export default UmbStylesheetWorkspaceEditElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-stylesheet-workspace-edit': UmbStylesheetWorkspaceEditElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts new file mode 100644 index 0000000000..1ef0802cff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -0,0 +1,38 @@ +import { UmbWorkspaceContext } from '../../../shared/components/workspace/workspace-context/workspace-context'; +import { UmbEntityWorkspaceContextInterface as UmbEntityWorkspaceContextInterface } from '../../../shared/components/workspace/workspace-context/workspace-entity-context.interface'; +import { UmbStylesheetRepository } from '../repository/stylesheet.repository'; +import type { MemberDetails } from '@umbraco-cms/backoffice/models'; +import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; + +export class UmbStylesheetWorkspaceContext + extends UmbWorkspaceContext + implements UmbEntityWorkspaceContextInterface +{ + constructor(host: UmbControllerHostInterface) { + super(host, new UmbStylesheetRepository(host)); + } + + getEntityType(): string { + return 'stylesheet'; + } + + getEntityKey() { + return '1234'; + } + + getData() { + return 'fake' as unknown as MemberDetails; + } + + async save() { + console.log('save'); + } + + async load(key: string) { + console.log('load', key); + } + + public destroy(): void { + console.log('destroy'); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts new file mode 100644 index 0000000000..651dd61020 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts @@ -0,0 +1,48 @@ +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { css, html } from 'lit'; +import { customElement, state } from 'lit/decorators.js'; +import { IRoutingInfo } from 'router-slot'; +import { UmbStylesheetWorkspaceEditElement } from './stylesheet-workspace-edit.element'; +import { UmbStylesheetWorkspaceContext } from './stylesheet-workspace.context'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; + +@customElement('umb-stylesheet-workspace') +export class UmbStylesheetWorkspaceElement extends UmbLitElement { + static styles = [ + UUITextStyles, + css` + :host { + display: block; + width: 100%; + height: 100%; + } + `, + ]; + + #workspaceContext = new UmbStylesheetWorkspaceContext(this); + #element = new UmbStylesheetWorkspaceEditElement(); + + @state() + _routes: any[] = [ + { + path: 'edit/:path', + component: () => this.#element, + setup: (component: HTMLElement, info: IRoutingInfo) => { + const path = info.match.params.path; + this.#workspaceContext.load(path); + }, + }, + ]; + + render() { + return html` `; + } +} + +export default UmbStylesheetWorkspaceElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-stylesheet-workspace': UmbStylesheetWorkspaceElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.stories.ts new file mode 100644 index 0000000000..09b9cdb96d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.stories.ts @@ -0,0 +1,18 @@ +import './stylesheet-workspace.element'; + +import { Meta, Story } from '@storybook/web-components'; +import { html } from 'lit'; + +import { data } from '../../../../core/mocks/data/member.data'; + +import type { UmbStylesheetWorkspaceElement } from './stylesheet-workspace.element'; + +export default { + title: 'Workspaces/Member', + component: 'umb-member-workspace', + id: 'umb-member-workspace', +} as Meta; + +export const AAAOverview: Story = () => + html` `; +AAAOverview.storyName = 'Overview'; From 9e624f3d4944df2c3d33873263749b4877b891cb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 13:12:28 +0100 Subject: [PATCH 056/114] add wip stylesheet path utils --- src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts new file mode 100644 index 0000000000..76636de368 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts @@ -0,0 +1,5 @@ +// TODO: we can try and make pretty urls if we want to +export const urlFriendlyPathFromServerPath = (path: string) => encodeURIComponent(path).replace('.', '-'); + +// TODO: we can try and make pretty urls if we want to +export const serverPathFromUrlFriendlyPath = (unique: string) => decodeURIComponent(unique.replace('-', '.')); From 5b7e85423cb18a5677b4fb926e5c7c360faf5e5f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 13:12:48 +0100 Subject: [PATCH 057/114] make url friendly unique for file system tree items --- .../file-system-tree-item/file-system-tree-item.context.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts index 2426614064..a51b41b87a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts @@ -1,10 +1,15 @@ import { UmbTreeItemContextBase } from '../tree-item-base/tree-item-base.context'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { FileSystemTreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; +import { urlFriendlyPathFromServerPath } from 'src/backoffice/templating/utils'; // TODO get unique method from an entity repository static method export class UmbFileSystemTreeItemContext extends UmbTreeItemContextBase { constructor(host: UmbControllerHostInterface, treeItem: FileSystemTreeItemPresentationModel) { super(host, treeItem, (x: FileSystemTreeItemPresentationModel) => x.path); } + + constructPath(pathname: string, entityType: string, path: string) { + return `section/${pathname}/workspace/${entityType}/edit/${urlFriendlyPathFromServerPath(path)}`; + } } From 10df05e0474c97ce39d06102152c5d482d07ceec Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 13:14:08 +0100 Subject: [PATCH 058/114] make construct path method public --- .../tree/tree-item-base/tree-item-base.context.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts index 298fb67aa9..d0e94a4863 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts @@ -14,6 +14,7 @@ import { } from '@umbraco-cms/backoffice/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import type { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; +import { urlFriendlyPathFromServerPath } from 'src/backoffice/templating/utils'; // add type for unique function export type UmbTreeItemUniqueFunction = (x: T) => string | null | undefined; @@ -126,7 +127,7 @@ export class UmbTreeItemContextBase { if (!pathname) return; - const path = this.#constructPath(pathname, this.type, this.unique); + const path = this.constructPath(pathname, this.type, this.unique); this.#path.next(path); }); } @@ -143,8 +144,8 @@ export class UmbTreeItemContextBase Date: Fri, 24 Mar 2023 13:14:22 +0100 Subject: [PATCH 059/114] add todo --- .../workspace/workspace-context/workspace-context.interface.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-context.interface.ts index c518155e53..d5ef7d313b 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-context.interface.ts @@ -7,6 +7,7 @@ export interface UmbWorkspaceContextInterface { isNew: Observable; getIsNew(): boolean; setIsNew(value: boolean): void; + // TODO: should we consider another name than entity type. File system files are not entities but still have this type. getEntityType(): string; getData(): T; destroy(): void; From 3f27659cd2ff25b6a151c84930a622fb4e96b846 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 13:14:42 +0100 Subject: [PATCH 060/114] update temp text in workspace --- .../stylesheets/workspace/stylesheet-workspace-edit.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts index a01b9dc02e..69c89804e5 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts @@ -16,7 +16,7 @@ export class UmbStylesheetWorkspaceEditElement extends LitElement { ]; render() { - return html` Member Workspace `; + return html` Stylesheet workspace `; } } From 50af17385c0be34fce801158972d5a7f8d7d20b3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 13:15:41 +0100 Subject: [PATCH 061/114] create serverPath from the url path when loading a stylesheet workspace --- .../workspace/stylesheet-workspace.context.ts | 11 ++++++----- .../workspace/stylesheet-workspace.element.ts | 4 +++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 1ef0802cff..e426843b5c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -1,17 +1,17 @@ import { UmbWorkspaceContext } from '../../../shared/components/workspace/workspace-context/workspace-context'; -import { UmbEntityWorkspaceContextInterface as UmbEntityWorkspaceContextInterface } from '../../../shared/components/workspace/workspace-context/workspace-entity-context.interface'; import { UmbStylesheetRepository } from '../repository/stylesheet.repository'; -import type { MemberDetails } from '@umbraco-cms/backoffice/models'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; +import { UmbWorkspaceContextInterface } from 'src/backoffice/shared/components/workspace/workspace-context/workspace-context.interface'; export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext - implements UmbEntityWorkspaceContextInterface + implements UmbWorkspaceContextInterface { constructor(host: UmbControllerHostInterface) { super(host, new UmbStylesheetRepository(host)); } + /* getEntityType(): string { return 'stylesheet'; } @@ -28,11 +28,12 @@ export class UmbStylesheetWorkspaceContext console.log('save'); } - async load(key: string) { - console.log('load', key); + async load(path: string) { + console.log('load', path); } public destroy(): void { console.log('destroy'); } + */ } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts index 651dd61020..3479aff92c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts @@ -5,6 +5,7 @@ import { IRoutingInfo } from 'router-slot'; import { UmbStylesheetWorkspaceEditElement } from './stylesheet-workspace-edit.element'; import { UmbStylesheetWorkspaceContext } from './stylesheet-workspace.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { serverPathFromUrlFriendlyPath } from '../../utils'; @customElement('umb-stylesheet-workspace') export class UmbStylesheetWorkspaceElement extends UmbLitElement { @@ -29,7 +30,8 @@ export class UmbStylesheetWorkspaceElement extends UmbLitElement { component: () => this.#element, setup: (component: HTMLElement, info: IRoutingInfo) => { const path = info.match.params.path; - this.#workspaceContext.load(path); + const serverPath = serverPathFromUrlFriendlyPath(path); + this.#workspaceContext.load(serverPath); }, }, ]; From fd05ff7637d9f968819517a2bf5694d6dae0768f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 13:23:46 +0100 Subject: [PATCH 062/114] move workspace context interface to workspace lib --- .../libs/workspace/actions/save/save.action.ts | 2 +- src/Umbraco.Web.UI.Client/libs/workspace/context/index.ts | 1 + .../workspace/context}/workspace-context.interface.ts | 0 src/Umbraco.Web.UI.Client/libs/workspace/index.ts | 1 + .../workspace-context/workspace-entity-context.interface.ts | 2 +- .../stylesheets/workspace/stylesheet-workspace.context.ts | 2 +- 6 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/libs/workspace/context/index.ts rename src/Umbraco.Web.UI.Client/{src/backoffice/shared/components/workspace/workspace-context => libs/workspace/context}/workspace-context.interface.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/libs/workspace/actions/save/save.action.ts b/src/Umbraco.Web.UI.Client/libs/workspace/actions/save/save.action.ts index 38dd1744eb..dde528e171 100644 --- a/src/Umbraco.Web.UI.Client/libs/workspace/actions/save/save.action.ts +++ b/src/Umbraco.Web.UI.Client/libs/workspace/actions/save/save.action.ts @@ -1,4 +1,4 @@ -import { UmbWorkspaceContextInterface } from '../../../../src/backoffice/shared/components/workspace/workspace-context/workspace-context.interface'; +import { UmbWorkspaceContextInterface } from '../../context/workspace-context.interface'; import { UmbWorkspaceActionBase } from '../workspace-action-base'; import type { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; diff --git a/src/Umbraco.Web.UI.Client/libs/workspace/context/index.ts b/src/Umbraco.Web.UI.Client/libs/workspace/context/index.ts new file mode 100644 index 0000000000..c4aea806a5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/libs/workspace/context/index.ts @@ -0,0 +1 @@ +export * from './workspace-context.interface'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/libs/workspace/context/workspace-context.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-context.interface.ts rename to src/Umbraco.Web.UI.Client/libs/workspace/context/workspace-context.interface.ts diff --git a/src/Umbraco.Web.UI.Client/libs/workspace/index.ts b/src/Umbraco.Web.UI.Client/libs/workspace/index.ts index 485f1b10af..de14fcfee4 100644 --- a/src/Umbraco.Web.UI.Client/libs/workspace/index.ts +++ b/src/Umbraco.Web.UI.Client/libs/workspace/index.ts @@ -1 +1,2 @@ export * from './actions'; +export * from './context'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-entity-context.interface.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-entity-context.interface.ts index e066a7ec1a..a06b85f015 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-entity-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-entity-context.interface.ts @@ -1,4 +1,4 @@ -import type { UmbWorkspaceContextInterface } from './workspace-context.interface'; +import type { UmbWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace'; export interface UmbEntityWorkspaceContextInterface extends UmbWorkspaceContextInterface { getEntityKey(): string | undefined; // COnsider if this should go away now that we have getUnique() diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts index e426843b5c..324422e1eb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -1,7 +1,7 @@ import { UmbWorkspaceContext } from '../../../shared/components/workspace/workspace-context/workspace-context'; import { UmbStylesheetRepository } from '../repository/stylesheet.repository'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; -import { UmbWorkspaceContextInterface } from 'src/backoffice/shared/components/workspace/workspace-context/workspace-context.interface'; +import { UmbWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace'; export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext From 1eb15880d0ecc41cbcced2e781870eb0e1cf6297 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 14:04:20 +0100 Subject: [PATCH 063/114] make tree data source interface generic --- .../repository/repository-tree-data-source.interface.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts index 5c8290dd11..5a62dff639 100644 --- a/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts @@ -1,8 +1,7 @@ -import { EntityTreeItemResponseModel, PagedEntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository'; -export interface RepositoryTreeDataSource { - getRootItems(): Promise>; - getChildrenOf(parentKey: string): Promise>; - getItems(key: Array): Promise>; +export interface RepositoryTreeDataSource { + getRootItems(): Promise>; + getChildrenOf(parentUnique: string): Promise>; + getItems(unique: Array): Promise>>; } From f2c453178f88b7cd12296b5a59f2981c3d1fbc50 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 14:12:46 +0100 Subject: [PATCH 064/114] add missing tree method to data source --- .../sources/stylesheet.tree.server.data.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts index 38a0e10e09..664eeceb64 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts @@ -14,7 +14,7 @@ import { RepositoryTreeDataSource } from 'libs/repository/repository-tree-data-s * @implements {RepositoryTreeDataSource} */ export class UmbStylesheetTreeServerDataSource - implements RepositoryTreeDataSource + implements RepositoryTreeDataSource { #host: UmbControllerHostInterface; @@ -50,4 +50,19 @@ export class UmbStylesheetTreeServerDataSource }) ); } + + /** + * Fetches stylesheet items from the server + * @param {(string | undefined)} path + * @return {*} + * @memberof UmbStylesheetTreeServerDataSource + */ + async getItems(path: Array) { + return tryExecuteAndNotify( + this.#host, + StylesheetResource.getTreeStylesheetItem({ + path, + }) + ); + } } From 30b796e179c5be4682c2232f9e3f5b159d3d9a7f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 14:13:07 +0100 Subject: [PATCH 065/114] clean up stylesheet repository --- .../repository/stylesheet.repository.ts | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts index 9259bd7e35..f21b6e2067 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts @@ -7,7 +7,6 @@ import { UmbTreeRepository } from '@umbraco-cms/backoffice/repository'; import { FileSystemTreeItemPresentationModel, PagedFileSystemTreeItemPresentationModel, - ProblemDetailsModel, } from '@umbraco-cms/backoffice/backend-api'; export class UmbStylesheetRepository @@ -59,18 +58,24 @@ export class UmbStylesheetRepository return { data, error }; } - async requestTreeItemsOf(path: string | null) {} + async requestTreeItemsOf(path: string | null) { + if (!path) throw new Error('Cannot request tree item with missing path'); - async requestTreeItems(keys: Array) { await this.#init; - if (!keys) { - const error: ProblemDetailsModel = { title: 'Keys are missing' }; - return { data: undefined, error }; + const { data, error } = await this.#treeDataSource.getChildrenOf(path); + + if (data) { + this.#treeStore!.appendItems(data.items); } - const { data, error } = await this.#treeDataSource.getItems(keys); + return { data, error, asObservable: () => this.#treeStore!.childrenOf(path) }; + } + async requestTreeItems(paths: Array) { + if (!paths) throw new Error('Paths are missing'); + await this.#init; + const { data, error } = await this.#treeDataSource.getItems(paths); return { data, error }; } @@ -79,13 +84,15 @@ export class UmbStylesheetRepository return this.#treeStore!.rootItems; } - async treeItemsOf(parentKey: string | null) { + async treeItemsOf(parentPath: string | null) { + if (!parentPath) throw new Error('Parent Path is missing'); await this.#init; - return this.#treeStore!.childrenOf(parentKey); + return this.#treeStore!.childrenOf(parentPath); } - async treeItems(keys: Array) { + async treeItems(paths: Array) { + if (!paths) throw new Error('Paths are missing'); await this.#init; - return this.#treeStore!.items(keys); + return this.#treeStore!.items(paths); } } From b7fb9511f10ee36fdccd852e1503a5d5b037dbda Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 14:15:51 +0100 Subject: [PATCH 066/114] remove repository from data source name + prefix with Umb --- .../repository-tree-data-source.interface.ts | 2 +- .../repository/document-type.repository.ts | 8 +- .../sources/document-type.tree.server.data.ts | 4 +- .../repository/document.repository.ts | 8 +- .../sources/document.tree.server.data.ts | 4 +- .../repository/media-type.repository.ts | 4 +- .../sources/media-type.tree.server.data.ts | 4 +- .../media/repository/media.repository.ts | 4 +- .../sources/media.tree.server.data.ts | 4 +- .../repository/member-group.repository.ts | 8 +- .../sources/member-group.tree.server.data.ts | 74 +++++++++---------- .../repository/member-type.repository.ts | 4 +- .../sources/member-type.tree.server.data.ts | 4 +- .../repository/data-type.repository.ts | 8 +- .../sources/data-type.tree.server.data.ts | 4 +- .../sources/stylesheet.tree.server.data.ts | 6 +- .../repository/dictionary.repository.ts | 4 +- .../sources/dictionary.tree.server.data.ts | 4 +- 18 files changed, 71 insertions(+), 87 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts index 5a62dff639..2a8999a88c 100644 --- a/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts @@ -1,6 +1,6 @@ import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository'; -export interface RepositoryTreeDataSource { +export interface UmbTreeDataSource { getRootItems(): Promise>; getChildrenOf(parentUnique: string): Promise>; getItems(unique: Array): Promise>>; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/document-type.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/document-type.repository.ts index 174b6d4f8f..c44c9d0601 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/document-type.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/document-type.repository.ts @@ -1,8 +1,4 @@ -import type { - RepositoryTreeDataSource, - UmbTreeRepository, - UmbDetailRepository, -} from '@umbraco-cms/backoffice/repository'; +import type { UmbTreeDataSource, UmbTreeRepository, UmbDetailRepository } from '@umbraco-cms/backoffice/repository'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { ProblemDetailsModel, DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; @@ -19,7 +15,7 @@ export class UmbDocumentTypeRepository implements UmbTreeRepository, UmbDetailRe #host: UmbControllerHostInterface; - #treeSource: RepositoryTreeDataSource; + #treeSource: UmbTreeDataSource; #treeStore?: UmbDocumentTypeTreeStore; #detailDataSource: UmbDocumentTypeServerDataSource; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/sources/document-type.tree.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/sources/document-type.tree.server.data.ts index 1d7deb1778..6d5f8877f4 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/sources/document-type.tree.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/sources/document-type.tree.server.data.ts @@ -1,4 +1,4 @@ -import type { RepositoryTreeDataSource } from '@umbraco-cms/backoffice/repository'; +import type { UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; import { ProblemDetailsModel, DocumentTypeResource } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; @@ -9,7 +9,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class DocumentTreeServerDataSource * @implements {DocumentTreeDataSource} */ -export class DocumentTypeTreeServerDataSource implements RepositoryTreeDataSource { +export class DocumentTypeTreeServerDataSource implements UmbTreeDataSource { #host: UmbControllerHostInterface; // TODO: how do we handle trashed items? diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.repository.ts index a3490cf3c5..a0f9397790 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.repository.ts @@ -2,11 +2,7 @@ import { UmbDocumentServerDataSource } from './sources/document.server.data'; import { UmbDocumentStore, UMB_DOCUMENT_STORE_CONTEXT_TOKEN } from './document.store'; import { UmbDocumentTreeStore, UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN } from './document.tree.store'; import { DocumentTreeServerDataSource } from './sources/document.tree.server.data'; -import type { - RepositoryTreeDataSource, - UmbTreeRepository, - UmbDetailRepository, -} from '@umbraco-cms/backoffice/repository'; +import type { UmbTreeDataSource, UmbTreeRepository, UmbDetailRepository } from '@umbraco-cms/backoffice/repository'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { ProblemDetailsModel, DocumentResponseModel } from '@umbraco-cms/backoffice/backend-api'; @@ -19,7 +15,7 @@ export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailReposi #host: UmbControllerHostInterface; - #treeSource: RepositoryTreeDataSource; + #treeSource: UmbTreeDataSource; #treeStore?: UmbDocumentTreeStore; #detailDataSource: UmbDocumentServerDataSource; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/document.tree.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/document.tree.server.data.ts index 17ab86a2fb..3dd6b3d6ff 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/document.tree.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/document.tree.server.data.ts @@ -1,4 +1,4 @@ -import type { RepositoryTreeDataSource } from '@umbraco-cms/backoffice/repository'; +import type { UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; import { ProblemDetailsModel, DocumentResource } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; @@ -9,7 +9,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class DocumentTreeServerDataSource * @implements {DocumentTreeDataSource} */ -export class DocumentTreeServerDataSource implements RepositoryTreeDataSource { +export class DocumentTreeServerDataSource implements UmbTreeDataSource { #host: UmbControllerHostInterface; // TODO: how do we handle trashed items? diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/repository/media-type.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/repository/media-type.repository.ts index 5bdfda591d..011e67a7e1 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/repository/media-type.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/repository/media-type.repository.ts @@ -7,14 +7,14 @@ import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-ap import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import type { MediaTypeDetails } from '@umbraco-cms/backoffice/models'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; -import { UmbTreeRepository, RepositoryTreeDataSource } from '@umbraco-cms/backoffice/repository'; +import { UmbTreeRepository, UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; export class UmbMediaTypeRepository implements UmbTreeRepository { #init!: Promise; #host: UmbControllerHostInterface; - #treeSource: RepositoryTreeDataSource; + #treeSource: UmbTreeDataSource; #treeStore?: UmbMediaTypeTreeStore; #detailSource: UmbMediaTypeDetailServerDataSource; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/repository/sources/media-type.tree.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/repository/sources/media-type.tree.server.data.ts index b246beefef..3c2f57bf07 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/repository/sources/media-type.tree.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/repository/sources/media-type.tree.server.data.ts @@ -1,6 +1,6 @@ import { MediaTypeResource, ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; -import { RepositoryTreeDataSource } from '@umbraco-cms/backoffice/repository'; +import { UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; /** @@ -9,7 +9,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class MediaTypeTreeServerDataSource * @implements {MediaTypeTreeDataSource} */ -export class MediaTypeTreeServerDataSource implements RepositoryTreeDataSource { +export class MediaTypeTreeServerDataSource implements UmbTreeDataSource { #host: UmbControllerHostInterface; /** diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.repository.ts index 24e5fd28aa..bab50b24b8 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.repository.ts @@ -1,4 +1,4 @@ -import type { RepositoryTreeDataSource } from '@umbraco-cms/backoffice/repository'; +import type { UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; @@ -18,7 +18,7 @@ export class UmbMediaRepository implements UmbTreeRepository, UmbDetailRepositor #host: UmbControllerHostInterface; - #treeSource: RepositoryTreeDataSource; + #treeSource: UmbTreeDataSource; #treeStore?: UmbMediaTreeStore; #detailDataSource: UmbMediaDetailServerDataSource; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/sources/media.tree.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/sources/media.tree.server.data.ts index b2b2cd2603..75c88bf7b4 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/sources/media.tree.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/sources/media.tree.server.data.ts @@ -1,4 +1,4 @@ -import type { RepositoryTreeDataSource } from '@umbraco-cms/backoffice/repository'; +import type { UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; import { ProblemDetailsModel, MediaResource } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; @@ -9,7 +9,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class MediaTreeServerDataSource * @implements {MediaTreeDataSource} */ -export class MediaTreeServerDataSource implements RepositoryTreeDataSource { +export class MediaTreeServerDataSource implements UmbTreeDataSource { #host: UmbControllerHostInterface; // TODO: how do we handle trashed items? diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/member-group.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/member-group.repository.ts index 0ed1749225..5ca8bcbac1 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/member-group.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/member-group.repository.ts @@ -7,11 +7,7 @@ import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import type { MemberGroupDetails } from '@umbraco-cms/backoffice/models'; import { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; -import type { - RepositoryTreeDataSource, - UmbDetailRepository, - UmbTreeRepository, -} from '@umbraco-cms/backoffice/repository'; +import type { UmbTreeDataSource, UmbDetailRepository, UmbTreeRepository } from '@umbraco-cms/backoffice/repository'; // TODO => Update type when backend updated export class UmbMemberGroupRepository implements UmbTreeRepository, UmbDetailRepository { @@ -19,7 +15,7 @@ export class UmbMemberGroupRepository implements UmbTreeRepository, UmbDetailRep #host: UmbControllerHostInterface; - #treeSource: RepositoryTreeDataSource; + #treeSource: UmbTreeDataSource; #treeStore?: UmbMemberGroupTreeStore; #detailSource: UmbMemberGroupDetailServerDataSource; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/sources/member-group.tree.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/sources/member-group.tree.server.data.ts index 6ccabbbf3c..5388958abd 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/sources/member-group.tree.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/sources/member-group.tree.server.data.ts @@ -1,6 +1,6 @@ import { MemberGroupResource, ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; -import { RepositoryTreeDataSource } from '@umbraco-cms/backoffice/repository'; +import { UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; /** @@ -9,7 +9,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class MemberGroupTreeServerDataSource * @implements {MemberGroupTreeDataSource} */ -export class MemberGroupTreeServerDataSource implements RepositoryTreeDataSource { +export class MemberGroupTreeServerDataSource implements UmbTreeDataSource { #host: UmbControllerHostInterface; /** @@ -22,42 +22,42 @@ export class MemberGroupTreeServerDataSource implements RepositoryTreeDataSource } /** - * Fetches the root items for the tree from the server - * @return {*} - * @memberof MemberGroupTreeServerDataSource - */ - async getRootItems() { - return tryExecuteAndNotify(this.#host, MemberGroupResource.getTreeMemberGroupRoot({})); - } + * Fetches the root items for the tree from the server + * @return {*} + * @memberof MemberGroupTreeServerDataSource + */ + async getRootItems() { + return tryExecuteAndNotify(this.#host, MemberGroupResource.getTreeMemberGroupRoot({})); + } - /** - * Fetches the children of a given parent key from the server - * @param {(string | null)} parentKey - * @return {*} - * @memberof MemberGroupTreeServerDataSource - */ - async getChildrenOf(parentKey: string | null) { - // Not implemented for this tree - return {}; - } + /** + * Fetches the children of a given parent key from the server + * @param {(string | null)} parentKey + * @return {*} + * @memberof MemberGroupTreeServerDataSource + */ + async getChildrenOf(parentKey: string | null) { + // Not implemented for this tree + return {}; + } - /** - * Fetches the items for the given keys from the server - * @param {Array} keys - * @return {*} - * @memberof MemberGroupTreeServerDataSource - */ - async getItems(keys: Array) { - if (!keys || keys.length === 0) { - const error: ProblemDetailsModel = { title: 'Keys are missing' }; - return { error }; - } + /** + * Fetches the items for the given keys from the server + * @param {Array} keys + * @return {*} + * @memberof MemberGroupTreeServerDataSource + */ + async getItems(keys: Array) { + if (!keys || keys.length === 0) { + const error: ProblemDetailsModel = { title: 'Keys are missing' }; + return { error }; + } - return tryExecuteAndNotify( - this.#host, - MemberGroupResource.getTreeMemberGroupItem({ - key: keys, - }) - ); - } + return tryExecuteAndNotify( + this.#host, + MemberGroupResource.getTreeMemberGroupItem({ + key: keys, + }) + ); + } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/member-type.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/member-type.repository.ts index 5b7f0cf65d..6aaa528dd0 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/member-type.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/member-type.repository.ts @@ -4,7 +4,7 @@ import { UmbMemberTypeStore, UMB_MEMBER_TYPE_STORE_CONTEXT_TOKEN } from './membe import { UmbMemberTypeDetailServerDataSource } from './sources/member-type.detail.server.data'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; -import { RepositoryTreeDataSource, UmbDetailRepository, UmbTreeRepository } from '@umbraco-cms/backoffice/repository'; +import { UmbTreeDataSource, UmbDetailRepository, UmbTreeRepository } from '@umbraco-cms/backoffice/repository'; import { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; import type { MemberTypeDetails } from '@umbraco-cms/backoffice/models'; @@ -17,7 +17,7 @@ export class UmbMemberTypeRepository implements UmbTreeRepository, UmbDetailRepo #host: UmbControllerHostInterface; - #treeSource: RepositoryTreeDataSource; + #treeSource: UmbTreeDataSource; #treeStore?: UmbMemberTypeTreeStore; #detailSource: UmbMemberTypeDetailServerDataSource; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/sources/member-type.tree.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/sources/member-type.tree.server.data.ts index 1384165787..4f450b5bde 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/sources/member-type.tree.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/sources/member-type.tree.server.data.ts @@ -1,6 +1,6 @@ import { MemberTypeResource, ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; -import { RepositoryTreeDataSource } from '@umbraco-cms/backoffice/repository'; +import { UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; /** @@ -9,7 +9,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class MemberTypeTreeServerDataSource * @implements {MemberTypeTreeDataSource} */ -export class MemberTypeTreeServerDataSource implements RepositoryTreeDataSource { +export class MemberTypeTreeServerDataSource implements UmbTreeDataSource { #host: UmbControllerHostInterface; /** diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/data-type.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/data-type.repository.ts index bcdd0b5099..f6519a85df 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/data-type.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/data-type.repository.ts @@ -1,8 +1,4 @@ -import type { - RepositoryTreeDataSource, - UmbTreeRepository, - UmbDetailRepository, -} from '@umbraco-cms/backoffice/repository'; +import type { UmbTreeDataSource, UmbTreeRepository, UmbDetailRepository } from '@umbraco-cms/backoffice/repository'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { ProblemDetailsModel, DataTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; @@ -23,7 +19,7 @@ export class UmbDataTypeRepository implements UmbTreeRepository, UmbDetailReposi #host: UmbControllerHostInterface; - #treeSource: RepositoryTreeDataSource; + #treeSource: UmbTreeDataSource; #treeStore?: UmbDataTypeTreeStore; #detailDataSource: UmbDataTypeServerDataSource; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/sources/data-type.tree.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/sources/data-type.tree.server.data.ts index ae8ebd987a..933a057a7b 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/sources/data-type.tree.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/sources/data-type.tree.server.data.ts @@ -1,4 +1,4 @@ -import type { RepositoryTreeDataSource } from '@umbraco-cms/backoffice/repository'; +import type { UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; import { ProblemDetailsModel, DataTypeResource } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; @@ -9,7 +9,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class DocumentTreeServerDataSource * @implements {DocumentTreeDataSource} */ -export class DataTypeTreeServerDataSource implements RepositoryTreeDataSource { +export class DataTypeTreeServerDataSource implements UmbTreeDataSource { #host: UmbControllerHostInterface; // TODO: how do we handle trashed items? diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts index 664eeceb64..b7eb9388cd 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts @@ -5,16 +5,16 @@ import { } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; -import { RepositoryTreeDataSource } from 'libs/repository/repository-tree-data-source.interface'; +import { UmbTreeDataSource } from 'libs/repository/repository-tree-data-source.interface'; /** * A data source for the Stylesheet tree that fetches data from the server * @export * @class UmbStylesheetTreeServerDataSource - * @implements {RepositoryTreeDataSource} + * @implements {UmbTreeDataSource} */ export class UmbStylesheetTreeServerDataSource - implements RepositoryTreeDataSource + implements UmbTreeDataSource { #host: UmbControllerHostInterface; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/dictionary.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/dictionary.repository.ts index a57b2c645f..a420b1ffc8 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/dictionary.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/dictionary.repository.ts @@ -1,6 +1,6 @@ import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; -import { RepositoryTreeDataSource, UmbDetailRepository, UmbTreeRepository } from '@umbraco-cms/backoffice/repository'; +import { UmbTreeDataSource, UmbDetailRepository, UmbTreeRepository } from '@umbraco-cms/backoffice/repository'; import { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; import type { DictionaryDetails } from '../'; @@ -14,7 +14,7 @@ export class UmbDictionaryRepository implements UmbTreeRepository, UmbDetailRepo #host: UmbControllerHostInterface; - #treeSource: RepositoryTreeDataSource; + #treeSource: UmbTreeDataSource; #treeStore?: UmbDictionaryTreeStore; #detailSource: UmbDictionaryDetailServerDataSource; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/sources/dictionary.tree.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/sources/dictionary.tree.server.data.ts index 55ac44213f..a96b16666d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/sources/dictionary.tree.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/sources/dictionary.tree.server.data.ts @@ -1,6 +1,6 @@ import { DictionaryResource, ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; -import { RepositoryTreeDataSource } from '@umbraco-cms/backoffice/repository'; +import { UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; /** @@ -9,7 +9,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class DictionaryTreeServerDataSource * @implements {DictionaryTreeDataSource} */ -export class DictionaryTreeServerDataSource implements RepositoryTreeDataSource { +export class DictionaryTreeServerDataSource implements UmbTreeDataSource { #host: UmbControllerHostInterface; /** From 960a43f330af56daa16c6d2b066c00997703a08d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 14:17:05 +0100 Subject: [PATCH 067/114] rename file --- src/Umbraco.Web.UI.Client/libs/repository/index.ts | 2 +- ...e-data-source.interface.ts => tree-data-source.interface.ts} | 0 .../repository/sources/stylesheet.tree.server.data.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/Umbraco.Web.UI.Client/libs/repository/{repository-tree-data-source.interface.ts => tree-data-source.interface.ts} (100%) diff --git a/src/Umbraco.Web.UI.Client/libs/repository/index.ts b/src/Umbraco.Web.UI.Client/libs/repository/index.ts index cd4c9e7d46..1f02dadaaa 100644 --- a/src/Umbraco.Web.UI.Client/libs/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/libs/repository/index.ts @@ -1,5 +1,5 @@ export * from './data-source-response.interface'; export * from './detail-repository.interface'; export * from './tree-repository.interface'; -export * from './repository-tree-data-source.interface'; +export * from './tree-data-source.interface'; export * from './repository-detail-data-source.interface'; diff --git a/src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/tree-data-source.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/libs/repository/repository-tree-data-source.interface.ts rename to src/Umbraco.Web.UI.Client/libs/repository/tree-data-source.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts index b7eb9388cd..7165e29c2e 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.tree.server.data.ts @@ -5,7 +5,7 @@ import { } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; -import { UmbTreeDataSource } from 'libs/repository/repository-tree-data-source.interface'; +import { UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; /** * A data source for the Stylesheet tree that fetches data from the server From 54465d2c4a59d310686b8ba1f06d7667f5bd7f7e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 14:41:17 +0100 Subject: [PATCH 068/114] remove repository from data source + prefix with Umb --- .../repository-detail-data-source.interface.ts | 12 ++++++------ .../repository/sources/document-type.server.data.ts | 10 +++++++--- .../repository/sources/document.server.data.ts | 4 ++-- .../documents/documents/repository/sources/index.ts | 4 ++-- .../repository/sources/media.detail.server.data.ts | 4 ++-- .../sources/member-group.detail.server.data.ts | 4 ++-- .../repository/sources/data-type.server.data.ts | 4 ++-- .../settings/languages/repository/sources/index.ts | 4 ++-- .../repository/sources/relation-type.server.data.ts | 4 ++-- 9 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/repository/repository-detail-data-source.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/repository-detail-data-source.interface.ts index ff4cdd3a6a..766ddf1e87 100644 --- a/src/Umbraco.Web.UI.Client/libs/repository/repository-detail-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/repository/repository-detail-data-source.interface.ts @@ -1,9 +1,9 @@ import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository'; -export interface RepositoryDetailDataSource { - createScaffold(parentKey: string | null): Promise>; - get(key: string): Promise>; - insert(data: DetailType): Promise>; - update(data: DetailType): Promise>; - delete(key: string): Promise>; +export interface UmbDataSource { + createScaffold(parentKey: string | null): Promise>; + get(key: string): Promise>; + insert(data: T): Promise>; + update(data: T): Promise>; + delete(key: string): Promise>; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/sources/document-type.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/sources/document-type.server.data.ts index 358910aabc..f5819640ff 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/sources/document-type.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/sources/document-type.server.data.ts @@ -1,5 +1,9 @@ -import { RepositoryDetailDataSource } from '@umbraco-cms/backoffice/repository'; -import { DocumentTypeResource, ProblemDetailsModel, DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { UmbDataSource } from '@umbraco-cms/backoffice/repository'; +import { + DocumentTypeResource, + ProblemDetailsModel, + DocumentTypeResponseModel, +} from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; @@ -9,7 +13,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class UmbDocumentTypeServerDataSource * @implements {RepositoryDetailDataSource} */ -export class UmbDocumentTypeServerDataSource implements RepositoryDetailDataSource { +export class UmbDocumentTypeServerDataSource implements UmbDataSource { #host: UmbControllerHostInterface; /** diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/document.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/document.server.data.ts index 467b0fa35f..c68b6a8eb1 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/document.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/document.server.data.ts @@ -1,5 +1,5 @@ import { v4 as uuidv4 } from 'uuid'; -import { RepositoryDetailDataSource } from '@umbraco-cms/backoffice/repository'; +import { UmbDataSource } from '@umbraco-cms/backoffice/repository'; import { DocumentResource, ProblemDetailsModel, @@ -15,7 +15,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class UmbDocumentServerDataSource * @implements {RepositoryDetailDataSource} */ -export class UmbDocumentServerDataSource implements RepositoryDetailDataSource { +export class UmbDocumentServerDataSource implements UmbDataSource { #host: UmbControllerHostInterface; /** diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/index.ts index ac6a6497ed..de97e4eed6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/index.ts @@ -1,7 +1,7 @@ import type { DocumentResponseModel } from '@umbraco-cms/backoffice/backend-api'; -import { RepositoryDetailDataSource, DataSourceResponse } from '@umbraco-cms/backoffice/repository'; +import { UmbDataSource, DataSourceResponse } from '@umbraco-cms/backoffice/repository'; -export interface UmbDocumentDataSource extends RepositoryDetailDataSource { +export interface UmbDocumentDataSource extends UmbDataSource { createScaffold(documentTypeKey: string): Promise>; trash(key: string): Promise>; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/sources/media.detail.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/sources/media.detail.server.data.ts index 57b1fde3c7..120cb495e8 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/sources/media.detail.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/sources/media.detail.server.data.ts @@ -1,5 +1,5 @@ import type { MediaDetails } from '../../'; -import { RepositoryDetailDataSource } from '@umbraco-cms/backoffice/repository'; +import { UmbDataSource } from '@umbraco-cms/backoffice/repository'; import { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; @@ -10,7 +10,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class UmbTemplateDetailServerDataSource * @implements {TemplateDetailDataSource} */ -export class UmbMediaDetailServerDataSource implements RepositoryDetailDataSource { +export class UmbMediaDetailServerDataSource implements UmbDataSource { #host: UmbControllerHostInterface; /** diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/sources/member-group.detail.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/sources/member-group.detail.server.data.ts index 91d1b54cd7..544de51bc6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/sources/member-group.detail.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/repository/sources/member-group.detail.server.data.ts @@ -2,7 +2,7 @@ import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; import { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; import type { MemberGroupDetails } from '@umbraco-cms/backoffice/models'; -import { RepositoryDetailDataSource } from '@umbraco-cms/backoffice/repository'; +import { UmbDataSource } from '@umbraco-cms/backoffice/repository'; /** * @description - A data source for the MemberGroup detail that fetches data from the server @@ -11,7 +11,7 @@ import { RepositoryDetailDataSource } from '@umbraco-cms/backoffice/repository'; * @implements {MemberGroupDetailDataSource} */ // TODO => Provide type when it is available -export class UmbMemberGroupDetailServerDataSource implements RepositoryDetailDataSource { +export class UmbMemberGroupDetailServerDataSource implements UmbDataSource { #host: UmbControllerHostInterface; constructor(host: UmbControllerHostInterface) { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/sources/data-type.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/sources/data-type.server.data.ts index 375237041e..86585ea6f1 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/sources/data-type.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/sources/data-type.server.data.ts @@ -1,5 +1,5 @@ import { v4 as uuidv4 } from 'uuid'; -import { RepositoryDetailDataSource } from '@umbraco-cms/backoffice/repository'; +import { UmbDataSource } from '@umbraco-cms/backoffice/repository'; import { ProblemDetailsModel, DataTypeResource, @@ -15,7 +15,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class UmbDataTypeServerDataSource * @implements {RepositoryDetailDataSource} */ -export class UmbDataTypeServerDataSource implements RepositoryDetailDataSource { +export class UmbDataTypeServerDataSource implements UmbDataSource { #host: UmbControllerHostInterface; /** diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/sources/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/sources/index.ts index 3a2bfbb366..4a3e236af4 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/sources/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/sources/index.ts @@ -1,5 +1,5 @@ import { LanguageResponseModel, PagedLanguageResponseModel } from '@umbraco-cms/backoffice/backend-api'; -import { RepositoryDetailDataSource, DataSourceResponse } from '@umbraco-cms/backoffice/repository'; +import { UmbDataSource, DataSourceResponse } from '@umbraco-cms/backoffice/repository'; // TODO: This is a temporary solution until we have a proper paging interface type paging = { @@ -7,7 +7,7 @@ type paging = { take: number; }; -export interface UmbLanguageDataSource extends RepositoryDetailDataSource { +export interface UmbLanguageDataSource extends UmbDataSource { createScaffold(): Promise>; get(isoCode: string): Promise>; delete(isoCode: string): Promise>; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/repository/sources/relation-type.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/repository/sources/relation-type.server.data.ts index d7756f9ae9..b16a93ebc8 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/repository/sources/relation-type.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/repository/sources/relation-type.server.data.ts @@ -1,4 +1,4 @@ -import { RepositoryDetailDataSource } from '@umbraco-cms/backoffice/repository'; +import { UmbDataSource } from '@umbraco-cms/backoffice/repository'; import { ProblemDetailsModel, RelationTypeResource, @@ -15,7 +15,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class UmbRelationTypeServerDataSource * @implements {RepositoryDetailDataSource} */ -export class UmbRelationTypeServerDataSource implements RepositoryDetailDataSource { +export class UmbRelationTypeServerDataSource implements UmbDataSource { #host: UmbControllerHostInterface; /** From 08191c101290092182725574eb8219f3090bd0ca Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 14:41:37 +0100 Subject: [PATCH 069/114] wip stylesheet data source --- .../sources/stylesheet.server.data.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.server.data.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.server.data.ts new file mode 100644 index 0000000000..2c9dcd186e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.server.data.ts @@ -0,0 +1,33 @@ +import { UmbDataSource } from '@umbraco-cms/backoffice/repository'; +import { DataTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; + +/** + * A data source for the Stylesheet that fetches data from the server + * @export + * @class UmbStylesheetServerDataSource + * @implements {UmbStylesheetServerDataSource} + */ +export class UmbStylesheetServerDataSource implements UmbDataSource { + #host: UmbControllerHostInterface; + + /** + * Creates an instance of UmbStylesheetServerDataSource. + * @param {UmbControllerHostInterface} host + * @memberof UmbStylesheetServerDataSource + */ + constructor(host: UmbControllerHostInterface) { + this.#host = host; + } + + /** + * Fetches a Stylesheet with the given path from the server + * @param {string} path + * @return {*} + * @memberof UmbStylesheetServerDataSource + */ + async get(path: string) { + if (!path) throw new Error('Path is missing'); + console.log('GET STYLESHEET WITH PATH', path); + } +} From b39429cab874402c138b912b83199dfa84afc348 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 14:44:21 +0100 Subject: [PATCH 070/114] add dummy methods to stylesheet data source --- .../sources/stylesheet.server.data.ts | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.server.data.ts index 2c9dcd186e..4419399142 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.server.data.ts @@ -1,5 +1,5 @@ -import { UmbDataSource } from '@umbraco-cms/backoffice/repository'; -import { DataTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { StylesheetDetails } from '../..'; +import { DataSourceResponse, UmbDataSource } from '@umbraco-cms/backoffice/repository'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; /** @@ -8,7 +8,7 @@ import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; * @class UmbStylesheetServerDataSource * @implements {UmbStylesheetServerDataSource} */ -export class UmbStylesheetServerDataSource implements UmbDataSource { +export class UmbStylesheetServerDataSource implements UmbDataSource { #host: UmbControllerHostInterface; /** @@ -19,6 +19,9 @@ export class UmbStylesheetServerDataSource implements UmbDataSource> { + throw new Error('Method not implemented.'); + } /** * Fetches a Stylesheet with the given path from the server @@ -29,5 +32,16 @@ export class UmbStylesheetServerDataSource implements UmbDataSource> { + throw new Error('Method not implemented.'); + } + update(data: StylesheetDetails): Promise> { + throw new Error('Method not implemented.'); + } + delete(key: string): Promise> { + throw new Error('Method not implemented.'); } } From 6202ba9b683d218eee2cc3b3b4db9e99c643b2e7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 14:45:35 +0100 Subject: [PATCH 071/114] rename data source file --- ...detail-data-source.interface.ts => data-source.interface.ts} | 0 src/Umbraco.Web.UI.Client/libs/repository/index.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/Umbraco.Web.UI.Client/libs/repository/{repository-detail-data-source.interface.ts => data-source.interface.ts} (100%) diff --git a/src/Umbraco.Web.UI.Client/libs/repository/repository-detail-data-source.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/data-source.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/libs/repository/repository-detail-data-source.interface.ts rename to src/Umbraco.Web.UI.Client/libs/repository/data-source.interface.ts diff --git a/src/Umbraco.Web.UI.Client/libs/repository/index.ts b/src/Umbraco.Web.UI.Client/libs/repository/index.ts index 1f02dadaaa..59d72e9b48 100644 --- a/src/Umbraco.Web.UI.Client/libs/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/libs/repository/index.ts @@ -2,4 +2,4 @@ export * from './data-source-response.interface'; export * from './detail-repository.interface'; export * from './tree-repository.interface'; export * from './tree-data-source.interface'; -export * from './repository-detail-data-source.interface'; +export * from './data-source.interface'; From eeef6fcf8c508a36ab13cf4d5805788d800a3d74 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 14:48:52 +0100 Subject: [PATCH 072/114] move data source interfaces into folder --- .../{ => data-source}/data-source-response.interface.ts | 0 .../repository/{ => data-source}/data-source.interface.ts | 0 .../libs/repository/data-source/index.ts | 3 +++ .../{ => data-source}/tree-data-source.interface.ts | 0 src/Umbraco.Web.UI.Client/libs/repository/index.ts | 4 +--- 5 files changed, 4 insertions(+), 3 deletions(-) rename src/Umbraco.Web.UI.Client/libs/repository/{ => data-source}/data-source-response.interface.ts (100%) rename src/Umbraco.Web.UI.Client/libs/repository/{ => data-source}/data-source.interface.ts (100%) create mode 100644 src/Umbraco.Web.UI.Client/libs/repository/data-source/index.ts rename src/Umbraco.Web.UI.Client/libs/repository/{ => data-source}/tree-data-source.interface.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/libs/repository/data-source-response.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/data-source/data-source-response.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/libs/repository/data-source-response.interface.ts rename to src/Umbraco.Web.UI.Client/libs/repository/data-source/data-source-response.interface.ts diff --git a/src/Umbraco.Web.UI.Client/libs/repository/data-source.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/data-source/data-source.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/libs/repository/data-source.interface.ts rename to src/Umbraco.Web.UI.Client/libs/repository/data-source/data-source.interface.ts diff --git a/src/Umbraco.Web.UI.Client/libs/repository/data-source/index.ts b/src/Umbraco.Web.UI.Client/libs/repository/data-source/index.ts new file mode 100644 index 0000000000..0c12e00d34 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/libs/repository/data-source/index.ts @@ -0,0 +1,3 @@ +export * from './data-source-response.interface'; +export * from './data-source.interface'; +export * from './tree-data-source.interface'; diff --git a/src/Umbraco.Web.UI.Client/libs/repository/tree-data-source.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/data-source/tree-data-source.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/libs/repository/tree-data-source.interface.ts rename to src/Umbraco.Web.UI.Client/libs/repository/data-source/tree-data-source.interface.ts diff --git a/src/Umbraco.Web.UI.Client/libs/repository/index.ts b/src/Umbraco.Web.UI.Client/libs/repository/index.ts index 59d72e9b48..f4727c8ffc 100644 --- a/src/Umbraco.Web.UI.Client/libs/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/libs/repository/index.ts @@ -1,5 +1,3 @@ -export * from './data-source-response.interface'; +export * from './data-source'; export * from './detail-repository.interface'; export * from './tree-repository.interface'; -export * from './tree-data-source.interface'; -export * from './data-source.interface'; From af19b30febac49d0cb6b8faa8bbfe5e6ed7b3a05 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 15:00:17 +0100 Subject: [PATCH 073/114] default to any --- .../libs/repository/data-source/tree-data-source.interface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/libs/repository/data-source/tree-data-source.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/data-source/tree-data-source.interface.ts index 2a8999a88c..ae57ef57af 100644 --- a/src/Umbraco.Web.UI.Client/libs/repository/data-source/tree-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/repository/data-source/tree-data-source.interface.ts @@ -1,6 +1,6 @@ import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository'; -export interface UmbTreeDataSource { +export interface UmbTreeDataSource { getRootItems(): Promise>; getChildrenOf(parentUnique: string): Promise>; getItems(unique: Array): Promise>>; From 2a33cf02ee230c41fda8f2a399dc5c23c69d4c10 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 15:00:24 +0100 Subject: [PATCH 074/114] default to any --- src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts b/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts index 3f7440385b..80a366ada5 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/tree-store.interface.ts @@ -1,7 +1,7 @@ import type { Observable } from 'rxjs'; import { TreeItemPresentationModel } from '../backend-api'; -export interface UmbTreeStore { +export interface UmbTreeStore { appendItems: (items: Array) => void; updateItem: (unique: string, item: Partial) => void; removeItem: (unique: string) => void; From 48ce44ba8fcb91cd428a291d0324b1ae7a49ec54 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 15:00:38 +0100 Subject: [PATCH 075/114] update story to pass in tree item --- .../tree-item-base/tree-item-base.stories.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.stories.ts index 1f76f40872..fedf14fccb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.stories.ts @@ -12,16 +12,20 @@ type Story = StoryObj; export const Overview: Story = { args: { - label: 'My Tree Item', - icon: 'umb:home', - hasChildren: false, + item: { + name: 'My Tree Item', + icon: 'umb:home', + hasChildren: false, + }, }, }; export const WithChildren: Story = { args: { - label: 'My Tree Item', - icon: 'umb:home', - hasChildren: true, + item: { + name: 'My Tree Item', + icon: 'umb:home', + hasChildren: true, + }, }, }; From f29a4c86ce80cdf2abfef5eaf0cbfe36c71f8696 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 15:07:26 +0100 Subject: [PATCH 076/114] wip stylesheet workspace context --- .../sources/stylesheet.server.data.ts | 2 +- .../repository/stylesheet.repository.ts | 16 ++++++++++-- .../workspace/stylesheet-workspace.context.ts | 25 +++++++++++-------- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.server.data.ts index 4419399142..bc82863011 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/sources/stylesheet.server.data.ts @@ -32,7 +32,7 @@ export class UmbStylesheetServerDataSource implements UmbDataSource> { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts index f21b6e2067..9d64f38445 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts @@ -1,5 +1,6 @@ import { UmbStylesheetTreeStore, UMB_STYLESHEET_TREE_STORE_CONTEXT_TOKEN } from './stylesheet.tree.store'; import { UmbStylesheetTreeServerDataSource } from './sources/stylesheet.tree.server.data'; +import { UmbStylesheetServerDataSource } from './sources/stylesheet.server.data'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; @@ -12,8 +13,9 @@ import { export class UmbStylesheetRepository implements UmbTreeRepository { - #host: UmbControllerHostInterface; - #treeDataSource: UmbStylesheetTreeServerDataSource; + #host; + #dataSource; + #treeDataSource; #treeStore?: UmbStylesheetTreeStore; #notificationContext?: UmbNotificationContext; #initResolver?: () => void; @@ -21,7 +23,9 @@ export class UmbStylesheetRepository constructor(host: UmbControllerHostInterface) { this.#host = host; + // TODO: figure out how spin up get the correct data source + this.#dataSource = new UmbStylesheetServerDataSource(this.#host); this.#treeDataSource = new UmbStylesheetTreeServerDataSource(this.#host); new UmbContextConsumerController(this.#host, UMB_STYLESHEET_TREE_STORE_CONTEXT_TOKEN, (instance) => { @@ -95,4 +99,12 @@ export class UmbStylesheetRepository await this.#init; return this.#treeStore!.items(paths); } + + // DETAILS + async requestByPath(path: string) { + if (!path) throw new Error('Path is missing'); + await this.#init; + const { data, error } = await this.#dataSource.get(path); + return { data, error }; + } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 324422e1eb..e3be06cf52 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -1,39 +1,42 @@ import { UmbWorkspaceContext } from '../../../shared/components/workspace/workspace-context/workspace-context'; import { UmbStylesheetRepository } from '../repository/stylesheet.repository'; +import { StylesheetDetails } from '..'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace'; +import { ObjectState } from '@umbraco-cms/backoffice/observable-api'; export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext implements UmbWorkspaceContextInterface { + #data = new ObjectState(undefined); + data = this.#data.asObservable(); + constructor(host: UmbControllerHostInterface) { super(host, new UmbStylesheetRepository(host)); } - /* getEntityType(): string { return 'stylesheet'; } - getEntityKey() { - return '1234'; - } - getData() { - return 'fake' as unknown as MemberDetails; + return this.#data.getValue(); } - async save() { - console.log('save'); + getEntityKey() { + return this.getData()?.path || ''; } async load(path: string) { - console.log('load', path); + const { data } = await this.repository.requestByPath(path); + if (data) { + this.setIsNew(false); + this.#data.update(data); + } } public destroy(): void { - console.log('destroy'); + this.#data.complete(); } - */ } From d79680a63ba2b738b9f5527dbf71b99c9faa191b Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 24 Mar 2023 15:14:01 +0100 Subject: [PATCH 077/114] template editor --- .../document-type-picker-modal.stories.ts | 4 +- .../input-template-picker.element.ts | 17 ++- .../template-picker-modal.element.ts | 2 +- .../shared/modals/template/index.ts | 8 +- .../modals/template/template-modal.element.ts | 137 +++++++++++++----- 5 files changed, 119 insertions(+), 49 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.stories.ts index fead1b4ac9..e51a73bc24 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.stories.ts @@ -9,8 +9,8 @@ import type { UmbDocumentTypePickerModalData } from './index'; export default { title: 'API/Modals/Layouts/Content Picker', - component: 'umb-document-picker-modal', - id: 'umb-document-picker-modal', + component: 'umb-document-type-picker-modal', + id: 'umb-document-type-picker-modal', } as Meta; const data: UmbDocumentTypePickerModalData = { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts index 828f13bfe1..90ae4e7cfb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts @@ -76,6 +76,10 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen public set allowedKeys(newKeys: Array) { //this.#observePickedTemplates(); this._allowedKeys = newKeys; + //this._templates = []; + //this._allowedKeys.forEach((key) => { + // this.#setup(key); + //}); } _defaultKey = ''; @@ -140,7 +144,10 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen }); modalHandler?.onSubmit().then((data) => { - console.log(data.selection); + if (!data.selection) return; + this.templates = []; + this.allowedKeys = data.selection; + this.allowedKeys.forEach((key) => this.#setup(key)); this.dispatchEvent(new CustomEvent('change-allowed', { bubbles: true, composed: true })); }); } @@ -181,12 +188,12 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen const key = (e.target as UmbTemplateCardElement).value; const modalHandler = this._modalContext?.open(UMB_TEMPLATE_MODAL_TOKEN, { - multiple: true, - selection: [...this.allowedKeys], + key: key as string, + language: 'razor', }); - modalHandler?.onSubmit().then((res) => { - console.log('save template'); + modalHandler?.onSubmit().then(({ key }) => { + // TODO: update list }); } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts index 503b3113a8..1f85db2a4d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts @@ -62,7 +62,6 @@ export class UmbTemplatePickerModalElement extends UmbModalBaseElement< private _handleSelectionChange(e: CustomEvent) { e.stopPropagation(); const element = e.target as UmbTreeElement; - //TODO: Should multiple property be implemented here or be passed down into umb-tree? this._selection = this._multiple ? element.selection : [element.selection[element.selection.length - 1]]; } @@ -74,6 +73,7 @@ export class UmbTemplatePickerModalElement extends UmbModalBaseElement< this.modalHandler?.reject(); } + // TODO: make umb-tree have a disabled option (string array like selection)? render() { return html` diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/index.ts index 28f1568e30..741a6d67b0 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/index.ts @@ -1,18 +1,18 @@ import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbTemplateModalData { - multiple: boolean; - selection: string[]; + key: string; + language?: 'razor' | 'typescript' | 'javascript' | 'css' | 'markdown' | 'json' | 'html'; } export interface UmbTemplateModalResult { - selection: string[] | undefined; + key: string; } export const UMB_TEMPLATE_MODAL_TOKEN = new UmbModalToken( 'Umb.Modal.Template', { type: 'sidebar', - size: 'large', + size: 'full', } ); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts index 89a6f66061..8d6fa4bf4c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts @@ -1,9 +1,14 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, state } from 'lit/decorators.js'; +import { customElement, query, state } from 'lit/decorators.js'; import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; -import { UmbTreeElement } from '../../components/tree/tree.element'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { UUIInputEvent } from '@umbraco-ui/uui'; +import { UmbCodeEditor } from '../../components/code-editor'; import { UmbTemplateModalData, UmbTemplateModalResult } from '.'; +import { UmbInputEvent } from 'libs/umb-events/input.event'; +import { TemplateResource, TemplateResponseModel } from 'libs/backend-api/src'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; //TODO: make a default tree-picker that can be used across multiple pickers // TODO: make use of UmbPickerLayoutBase @@ -12,78 +17,136 @@ export class UmbTemplateModalElement extends UmbModalBaseElement = []; + _key = ''; @state() - _multiple = true; + _template?: TemplateResponseModel; + + @query('umb-code-editor') + _codeEditor?: UmbCodeEditor; connectedCallback() { super.connectedCallback(); - this._selection = this.data?.selection ?? []; - this._multiple = this.data?.multiple ?? true; + + if (!this.data?.key) return; + + this._key = this.data.key; + this.#getTemplate(); } - private _handleSelectionChange(e: CustomEvent) { - e.stopPropagation(); - const element = e.target as UmbTreeElement; - //TODO: Should multiple property be implemented here or be passed down into umb-tree? - this._selection = this._multiple ? element.selection : [element.selection[element.selection.length - 1]]; + async #getTemplate() { + const { data } = await tryExecuteAndNotify(this, TemplateResource.getTemplateByKey({ key: this._key })); + if (!data) return; + + this._template = data; + } + + async #saveTemplate() { + const { error } = await tryExecuteAndNotify( + this, + TemplateResource.putTemplateByKey({ key: this._key, requestBody: this._template }) + ); + if (!error) { + console.log(`template (${this._key}) saved successfully`); + } } private _submit() { - this.modalHandler?.submit({ selection: this._selection }); + if (!this._template?.key) return; + + this.#saveTemplate(); + this.modalHandler?.submit({ key: this._template.key }); } private _close() { this.modalHandler?.reject(); } + #codeEditorInput(e: UmbInputEvent) { + e.stopPropagation(); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this._template.code = this._codeEditor?.code; + } + + #templateNameInput(e: UUIInputEvent) { + if (!this._template) return; + this._template.name = e.target.value as string; + } + render() { return html` - + +
+ +
${this._template?.alias}
+
+
+ - -
- Code editor? +
+ Master template: To be continued +
+ To be continued + To be continued + To be continued +
+
+
-
+ `; } } From 0068dcd77f4ada42edbe7a0e28acd235ca1edc9e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 24 Mar 2023 15:23:21 +0100 Subject: [PATCH 078/114] fix logic for file system root and children --- .../libs/store/file-system-tree.store.ts | 4 ++-- .../src/core/mocks/data/stylesheet.data.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/store/file-system-tree.store.ts b/src/Umbraco.Web.UI.Client/libs/store/file-system-tree.store.ts index eba5aee290..0d798b71d5 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/file-system-tree.store.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/file-system-tree.store.ts @@ -43,7 +43,7 @@ export class UmbFileSystemTreeStore extends UmbStoreBase implements UmbTreeStore * An observable to observe the root items * @memberof UmbFileSystemTreeStore */ - rootItems = this.#data.getObservablePart((items) => items.filter((item) => item.path === item.name)); + rootItems = this.#data.getObservablePart((items) => items.filter((item) => item.path?.includes('/') === false)); /** * Returns an observable to observe the children of a given parent @@ -52,7 +52,7 @@ export class UmbFileSystemTreeStore extends UmbStoreBase implements UmbTreeStore * @memberof UmbFileSystemTreeStore */ childrenOf(parentPath: string | null) { - return this.#data.getObservablePart((items) => items.filter((item) => item.path?.startsWith(parentPath ?? ''))); + return this.#data.getObservablePart((items) => items.filter((item) => item.path?.startsWith(parentPath + '/'))); } /** diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/stylesheet.data.ts index f5e303b893..f73ee09968 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/stylesheet.data.ts @@ -58,14 +58,14 @@ class UmbStylesheetData extends UmbEntityData { } getTreeRoot(): PagedFileSystemTreeItemPresentationModel { - const items = this.data.filter((item) => item.path === item.name); + const items = this.data.filter((item) => item.path?.includes('/') === false); const treeItems = items.map((item) => createFileSystemTreeItem(item)); const total = items.length; return { items: treeItems, total }; } getTreeItemChildren(parentPath: string): PagedFileSystemTreeItemPresentationModel { - const items = this.data.filter((item) => item.path?.startsWith(parentPath)); + const items = this.data.filter((item) => item.path?.startsWith(parentPath + '/')); const treeItems = items.map((item) => createFileSystemTreeItem(item)); const total = items.length; return { items: treeItems, total }; From 48f238f5a00854223f0aeebc5d5242b013e424d7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 27 Mar 2023 09:37:38 +0200 Subject: [PATCH 079/114] move file system tree item into templating folder --- .../src/backoffice/shared/components/index.ts | 1 - .../tree/tree-item-base/tree-item-base.context.ts | 2 +- .../file-system-tree-item/file-system-tree-item.context.ts | 6 +++--- .../file-system-tree-item/file-system-tree-item.element.ts | 0 .../src/backoffice/templating/components/index.ts | 1 + .../src/backoffice/templating/index.ts | 2 ++ .../stylesheets/workspace/stylesheet-workspace.element.ts | 4 ++-- .../src/backoffice/templating/utils.ts | 4 ++-- 8 files changed, 11 insertions(+), 9 deletions(-) rename src/Umbraco.Web.UI.Client/src/backoffice/{shared/components/tree => templating/components}/file-system-tree-item/file-system-tree-item.context.ts (75%) rename src/Umbraco.Web.UI.Client/src/backoffice/{shared/components/tree => templating/components}/file-system-tree-item/file-system-tree-item.element.ts (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/components/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts index c4e61d4c70..bb743e457d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts @@ -37,7 +37,6 @@ import './table/table.element'; import './tree/tree.element'; import './tree/entity-tree-item/entity-tree-item.element'; -import './tree/file-system-tree-item/file-system-tree-item.element'; import './tree/tree-menu-item/tree-menu-item.element'; import './variantable-property/variantable-property.element'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts index d0e94a4863..b7cfcf7654 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts @@ -14,7 +14,7 @@ import { } from '@umbraco-cms/backoffice/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import type { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; -import { urlFriendlyPathFromServerPath } from 'src/backoffice/templating/utils'; +import { urlFriendlyPathFromServerFilePath } from 'src/backoffice/templating/utils'; // add type for unique function export type UmbTreeItemUniqueFunction = (x: T) => string | null | undefined; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts similarity index 75% rename from src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts index a51b41b87a..35f216062e 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts @@ -1,7 +1,7 @@ -import { UmbTreeItemContextBase } from '../tree-item-base/tree-item-base.context'; +import { UmbTreeItemContextBase } from '../../../shared/components/tree/tree-item-base/tree-item-base.context'; +import { urlFriendlyPathFromServerFilePath } from '../../utils'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { FileSystemTreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; -import { urlFriendlyPathFromServerPath } from 'src/backoffice/templating/utils'; // TODO get unique method from an entity repository static method export class UmbFileSystemTreeItemContext extends UmbTreeItemContextBase { @@ -10,6 +10,6 @@ export class UmbFileSystemTreeItemContext extends UmbTreeItemContextBase) => { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts index 3479aff92c..a0e2ba7e85 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts @@ -2,10 +2,10 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { IRoutingInfo } from 'router-slot'; +import { serverFilePathFromUrlFriendlyPath } from '../../utils'; import { UmbStylesheetWorkspaceEditElement } from './stylesheet-workspace-edit.element'; import { UmbStylesheetWorkspaceContext } from './stylesheet-workspace.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { serverPathFromUrlFriendlyPath } from '../../utils'; @customElement('umb-stylesheet-workspace') export class UmbStylesheetWorkspaceElement extends UmbLitElement { @@ -30,7 +30,7 @@ export class UmbStylesheetWorkspaceElement extends UmbLitElement { component: () => this.#element, setup: (component: HTMLElement, info: IRoutingInfo) => { const path = info.match.params.path; - const serverPath = serverPathFromUrlFriendlyPath(path); + const serverPath = serverFilePathFromUrlFriendlyPath(path); this.#workspaceContext.load(serverPath); }, }, diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts index 76636de368..80214bb7fd 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts @@ -1,5 +1,5 @@ // TODO: we can try and make pretty urls if we want to -export const urlFriendlyPathFromServerPath = (path: string) => encodeURIComponent(path).replace('.', '-'); +export const urlFriendlyPathFromServerFilePath = (path: string) => encodeURIComponent(path).replace('.', '-'); // TODO: we can try and make pretty urls if we want to -export const serverPathFromUrlFriendlyPath = (unique: string) => decodeURIComponent(unique.replace('-', '.')); +export const serverFilePathFromUrlFriendlyPath = (unique: string) => decodeURIComponent(unique.replace('-', '.')); From 55893a054f7c5200dbeb401b83feeb6fb6f5fdc9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 27 Mar 2023 09:43:44 +0200 Subject: [PATCH 080/114] Revert "move file system tree item into templating folder" This reverts commit 48f238f5a00854223f0aeebc5d5242b013e424d7. --- .../src/backoffice/shared/components/index.ts | 1 + .../file-system-tree-item/file-system-tree-item.context.ts | 6 +++--- .../file-system-tree-item/file-system-tree-item.element.ts | 0 .../tree/tree-item-base/tree-item-base.context.ts | 2 +- .../src/backoffice/templating/components/index.ts | 1 - .../src/backoffice/templating/index.ts | 2 -- .../stylesheets/workspace/stylesheet-workspace.element.ts | 4 ++-- .../src/backoffice/templating/utils.ts | 4 ++-- 8 files changed, 9 insertions(+), 11 deletions(-) rename src/Umbraco.Web.UI.Client/src/backoffice/{templating/components => shared/components/tree}/file-system-tree-item/file-system-tree-item.context.ts (75%) rename src/Umbraco.Web.UI.Client/src/backoffice/{templating/components => shared/components/tree}/file-system-tree-item/file-system-tree-item.element.ts (100%) delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/components/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts index bb743e457d..c4e61d4c70 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts @@ -37,6 +37,7 @@ import './table/table.element'; import './tree/tree.element'; import './tree/entity-tree-item/entity-tree-item.element'; +import './tree/file-system-tree-item/file-system-tree-item.element'; import './tree/tree-menu-item/tree-menu-item.element'; import './variantable-property/variantable-property.element'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts similarity index 75% rename from src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts index 35f216062e..a51b41b87a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts @@ -1,7 +1,7 @@ -import { UmbTreeItemContextBase } from '../../../shared/components/tree/tree-item-base/tree-item-base.context'; -import { urlFriendlyPathFromServerFilePath } from '../../utils'; +import { UmbTreeItemContextBase } from '../tree-item-base/tree-item-base.context'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { FileSystemTreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; +import { urlFriendlyPathFromServerPath } from 'src/backoffice/templating/utils'; // TODO get unique method from an entity repository static method export class UmbFileSystemTreeItemContext extends UmbTreeItemContextBase { @@ -10,6 +10,6 @@ export class UmbFileSystemTreeItemContext extends UmbTreeItemContextBase = (x: T) => string | null | undefined; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/index.ts deleted file mode 100644 index 23987fc391..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -import './file-system-tree-item/file-system-tree-item.element'; 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..02854c3770 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/index.ts @@ -4,8 +4,6 @@ import { manifests as stylesheetManifests } from './stylesheets/manifests'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry'; -import './components'; - export const manifests = [...menuManifests, ...templateManifests, ...stylesheetManifests]; const registerExtensions = (manifests: Array) => { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts index a0e2ba7e85..3479aff92c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts @@ -2,10 +2,10 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { IRoutingInfo } from 'router-slot'; -import { serverFilePathFromUrlFriendlyPath } from '../../utils'; import { UmbStylesheetWorkspaceEditElement } from './stylesheet-workspace-edit.element'; import { UmbStylesheetWorkspaceContext } from './stylesheet-workspace.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { serverPathFromUrlFriendlyPath } from '../../utils'; @customElement('umb-stylesheet-workspace') export class UmbStylesheetWorkspaceElement extends UmbLitElement { @@ -30,7 +30,7 @@ export class UmbStylesheetWorkspaceElement extends UmbLitElement { component: () => this.#element, setup: (component: HTMLElement, info: IRoutingInfo) => { const path = info.match.params.path; - const serverPath = serverFilePathFromUrlFriendlyPath(path); + const serverPath = serverPathFromUrlFriendlyPath(path); this.#workspaceContext.load(serverPath); }, }, diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts index 80214bb7fd..76636de368 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts @@ -1,5 +1,5 @@ // TODO: we can try and make pretty urls if we want to -export const urlFriendlyPathFromServerFilePath = (path: string) => encodeURIComponent(path).replace('.', '-'); +export const urlFriendlyPathFromServerPath = (path: string) => encodeURIComponent(path).replace('.', '-'); // TODO: we can try and make pretty urls if we want to -export const serverFilePathFromUrlFriendlyPath = (unique: string) => decodeURIComponent(unique.replace('-', '.')); +export const serverPathFromUrlFriendlyPath = (unique: string) => decodeURIComponent(unique.replace('-', '.')); From 026d45d4769ba273fdf722802e5a63b8939d5a83 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 27 Mar 2023 10:06:11 +0200 Subject: [PATCH 081/114] Revert "Revert "move file system tree item into templating folder"" This reverts commit 55893a054f7c5200dbeb401b83feeb6fb6f5fdc9. --- .../src/backoffice/shared/components/index.ts | 1 - .../tree/tree-item-base/tree-item-base.context.ts | 2 +- .../file-system-tree-item/file-system-tree-item.context.ts | 6 +++--- .../file-system-tree-item/file-system-tree-item.element.ts | 0 .../src/backoffice/templating/components/index.ts | 1 + .../src/backoffice/templating/index.ts | 2 ++ .../stylesheets/workspace/stylesheet-workspace.element.ts | 4 ++-- .../src/backoffice/templating/utils.ts | 4 ++-- 8 files changed, 11 insertions(+), 9 deletions(-) rename src/Umbraco.Web.UI.Client/src/backoffice/{shared/components/tree => templating/components}/file-system-tree-item/file-system-tree-item.context.ts (75%) rename src/Umbraco.Web.UI.Client/src/backoffice/{shared/components/tree => templating/components}/file-system-tree-item/file-system-tree-item.element.ts (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/templating/components/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts index c4e61d4c70..bb743e457d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts @@ -37,7 +37,6 @@ import './table/table.element'; import './tree/tree.element'; import './tree/entity-tree-item/entity-tree-item.element'; -import './tree/file-system-tree-item/file-system-tree-item.element'; import './tree/tree-menu-item/tree-menu-item.element'; import './variantable-property/variantable-property.element'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts index d0e94a4863..b7cfcf7654 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts @@ -14,7 +14,7 @@ import { } from '@umbraco-cms/backoffice/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import type { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; -import { urlFriendlyPathFromServerPath } from 'src/backoffice/templating/utils'; +import { urlFriendlyPathFromServerFilePath } from 'src/backoffice/templating/utils'; // add type for unique function export type UmbTreeItemUniqueFunction = (x: T) => string | null | undefined; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts similarity index 75% rename from src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts index a51b41b87a..35f216062e 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/file-system-tree-item/file-system-tree-item.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts @@ -1,7 +1,7 @@ -import { UmbTreeItemContextBase } from '../tree-item-base/tree-item-base.context'; +import { UmbTreeItemContextBase } from '../../../shared/components/tree/tree-item-base/tree-item-base.context'; +import { urlFriendlyPathFromServerFilePath } from '../../utils'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { FileSystemTreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; -import { urlFriendlyPathFromServerPath } from 'src/backoffice/templating/utils'; // TODO get unique method from an entity repository static method export class UmbFileSystemTreeItemContext extends UmbTreeItemContextBase { @@ -10,6 +10,6 @@ export class UmbFileSystemTreeItemContext extends UmbTreeItemContextBase) => { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts index 3479aff92c..a0e2ba7e85 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.element.ts @@ -2,10 +2,10 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { IRoutingInfo } from 'router-slot'; +import { serverFilePathFromUrlFriendlyPath } from '../../utils'; import { UmbStylesheetWorkspaceEditElement } from './stylesheet-workspace-edit.element'; import { UmbStylesheetWorkspaceContext } from './stylesheet-workspace.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { serverPathFromUrlFriendlyPath } from '../../utils'; @customElement('umb-stylesheet-workspace') export class UmbStylesheetWorkspaceElement extends UmbLitElement { @@ -30,7 +30,7 @@ export class UmbStylesheetWorkspaceElement extends UmbLitElement { component: () => this.#element, setup: (component: HTMLElement, info: IRoutingInfo) => { const path = info.match.params.path; - const serverPath = serverPathFromUrlFriendlyPath(path); + const serverPath = serverFilePathFromUrlFriendlyPath(path); this.#workspaceContext.load(serverPath); }, }, diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts index 76636de368..80214bb7fd 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/utils.ts @@ -1,5 +1,5 @@ // TODO: we can try and make pretty urls if we want to -export const urlFriendlyPathFromServerPath = (path: string) => encodeURIComponent(path).replace('.', '-'); +export const urlFriendlyPathFromServerFilePath = (path: string) => encodeURIComponent(path).replace('.', '-'); // TODO: we can try and make pretty urls if we want to -export const serverPathFromUrlFriendlyPath = (unique: string) => decodeURIComponent(unique.replace('-', '.')); +export const serverFilePathFromUrlFriendlyPath = (unique: string) => decodeURIComponent(unique.replace('-', '.')); From 1ac8a5e1e569ad6eb6ca3c6c0a38032ba32b3f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 27 Mar 2023 10:32:00 +0200 Subject: [PATCH 082/114] fix filter --- .../libs/extensions-api/registry/extension.registry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c380dc602e..32963de61a 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 @@ -47,7 +47,7 @@ export class UmbExtensionRegistry { const nextData = this._kinds .getValue() .filter( - (k) => k.matchType !== (kind as ManifestKind).matchType && k.matchKind !== (kind as ManifestKind).matchKind + (k) => !(k.matchType === (kind as ManifestKind).matchType && k.matchKind === (kind as ManifestKind).matchKind) ); nextData.push(kind as ManifestKind); this._kinds.next(nextData); From 07a1a6cc7863d905ce34fbf445c3b20d9f0800ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 27 Mar 2023 10:32:41 +0200 Subject: [PATCH 083/114] performance optimizing --- .../libs/extensions-api/registry/extension.registry.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 32963de61a..c1279b91f7 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 @@ -125,7 +125,10 @@ export class UmbExtensionRegistry { T extends ManifestBase = SpecificManifestTypeOrManifestBase >(type: Key, alias: string) { return combineLatest([ - this.extensions.pipe(map((exts) => exts.find((ext) => ext.type === type && ext.alias === alias))), + this.extensions.pipe( + map((exts) => exts.find((ext) => ext.type === type && ext.alias === alias)), + distinctUntilChanged(extensionSingleMemoization) + ), this._kindsOfType(type), ]).pipe( map(([ext, kinds]) => { From 3a7ad00706a3eb9ff646387ceebf11d84c954761 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 27 Mar 2023 11:29:53 +0200 Subject: [PATCH 084/114] remove unused store alias from manifest --- .../libs/extensions-registry/tree.models.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/libs/extensions-registry/tree.models.ts b/src/Umbraco.Web.UI.Client/libs/extensions-registry/tree.models.ts index d4eea123a9..8dbce1f603 100644 --- a/src/Umbraco.Web.UI.Client/libs/extensions-registry/tree.models.ts +++ b/src/Umbraco.Web.UI.Client/libs/extensions-registry/tree.models.ts @@ -7,6 +7,5 @@ export interface ManifestTree extends ManifestBase { } export interface MetaTree { - storeAlias?: string; repository?: ClassConstructor; } From 5291d649243273d612f438b5bb7461dcc3a55260 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 27 Mar 2023 11:31:48 +0200 Subject: [PATCH 085/114] add interface for tree-item-context --- .../repository/tree-repository.interface.ts | 34 +++++++++---------- .../repository/document-type.repository.ts | 10 +++--- .../repository/document.repository.ts | 2 +- .../repository/member-type.repository.ts | 3 +- .../repository/data-type.repository.ts | 3 +- .../repository/relation-type.repository.ts | 3 +- .../shared/collection/collection.context.ts | 2 +- .../tree-item-base/tree-item-base.context.ts | 7 ++-- .../tree-item-base/tree-item-base.element.ts | 2 +- .../tree/tree-item.context.interface.ts | 34 +++++++++++++++++++ .../repository/stylesheet.repository.ts | 2 +- .../repository/template.repository.ts | 2 +- 12 files changed, 71 insertions(+), 33 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.context.interface.ts diff --git a/src/Umbraco.Web.UI.Client/libs/repository/tree-repository.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/tree-repository.interface.ts index 6d57205da4..4ef19c3920 100644 --- a/src/Umbraco.Web.UI.Client/libs/repository/tree-repository.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/repository/tree-repository.interface.ts @@ -1,31 +1,29 @@ import type { Observable } from 'rxjs'; -import { - EntityTreeItemResponseModel, - PagedEntityTreeItemResponseModel, - ProblemDetailsModel, -} from '@umbraco-cms/backoffice/backend-api'; +import { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; -export interface UmbTreeRepository< - PagedItemsType = PagedEntityTreeItemResponseModel, - ItemsType = EntityTreeItemResponseModel -> { +export interface UmbPagedData { + total: number; + items: Array; +} + +export interface UmbTreeRepository> { requestRootTreeItems: () => Promise<{ - data: PagedItemsType | undefined; + data: PagedItemType | undefined; error: ProblemDetailsModel | undefined; - asObservable?: () => Observable; + asObservable?: () => Observable; }>; requestTreeItemsOf: (parentUnique: string | null) => Promise<{ - data: PagedItemsType | undefined; + data: PagedItemType | undefined; error: ProblemDetailsModel | undefined; - asObservable?: () => Observable; + asObservable?: () => Observable; }>; requestTreeItems: (uniques: string[]) => Promise<{ - data: Array | undefined; + data: Array | undefined; error: ProblemDetailsModel | undefined; - asObservable?: () => Observable; + asObservable?: () => Observable; }>; - rootTreeItems: () => Promise>; - treeItemsOf: (parentUnique: string | null) => Promise>; - treeItems: (uniques: string[]) => Promise>; + rootTreeItems: () => Promise>; + treeItemsOf: (parentUnique: string | null) => Promise>; + treeItems: (uniques: string[]) => Promise>; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/document-type.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/document-type.repository.ts index c44c9d0601..aae1b52131 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/document-type.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/repository/document-type.repository.ts @@ -1,16 +1,16 @@ +import { DocumentTypeTreeServerDataSource } from './sources/document-type.tree.server.data'; +import { UmbDocumentTypeServerDataSource } from './sources/document-type.server.data'; +import { UmbDocumentTypeTreeStore, UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN } from './document-type.tree.store'; +import { UmbDocumentTypeStore, UMB_DOCUMENT_TYPE_STORE_CONTEXT_TOKEN } from './document-type.store'; import type { UmbTreeDataSource, UmbTreeRepository, UmbDetailRepository } from '@umbraco-cms/backoffice/repository'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { ProblemDetailsModel, DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; -import { DocumentTypeTreeServerDataSource } from './sources/document-type.tree.server.data'; -import { UmbDocumentTypeServerDataSource } from './sources/document-type.server.data'; -import { UmbDocumentTypeTreeStore, UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN } from './document-type.tree.store'; -import { UmbDocumentTypeStore, UMB_DOCUMENT_TYPE_STORE_CONTEXT_TOKEN } from './document-type.store'; type ItemType = DocumentTypeResponseModel; -export class UmbDocumentTypeRepository implements UmbTreeRepository, UmbDetailRepository { +export class UmbDocumentTypeRepository implements UmbTreeRepository, UmbDetailRepository { #init!: Promise; #host: UmbControllerHostInterface; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.repository.ts index a0f9397790..5e80ce51f9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/document.repository.ts @@ -10,7 +10,7 @@ import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco type ItemType = DocumentResponseModel; -export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailRepository { +export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailRepository { #init!: Promise; #host: UmbControllerHostInterface; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/member-type.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/member-type.repository.ts index 6aaa528dd0..ffa47cbd04 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/member-type.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/repository/member-type.repository.ts @@ -11,8 +11,9 @@ import type { MemberTypeDetails } from '@umbraco-cms/backoffice/models'; // TODO => use correct type when available type ItemType = any; +type TreeItemType = any; -export class UmbMemberTypeRepository implements UmbTreeRepository, UmbDetailRepository { +export class UmbMemberTypeRepository implements UmbTreeRepository, UmbDetailRepository { #init!: Promise; #host: UmbControllerHostInterface; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/data-type.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/data-type.repository.ts index f6519a85df..bc5c68b8f9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/data-type.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/data-type.repository.ts @@ -9,12 +9,13 @@ import { UmbDataTypeStore, UMB_DATA_TYPE_STORE_CONTEXT_TOKEN } from './data-type import { DataTypeTreeServerDataSource } from './sources/data-type.tree.server.data'; type ItemType = DataTypeResponseModel; +type TreeItemType = any; // Move to documentation / JSdoc /* We need to create a new instance of the repository from within the element context. We want the notifications to be displayed in the right context. */ // element -> context -> repository -> (store) -> data source // All methods should be async and return a promise. Some methods might return an observable as part of the promise response. -export class UmbDataTypeRepository implements UmbTreeRepository, UmbDetailRepository { +export class UmbDataTypeRepository implements UmbTreeRepository, UmbDetailRepository { #init!: Promise; #host: UmbControllerHostInterface; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/repository/relation-type.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/repository/relation-type.repository.ts index 5ba5077140..2c277ac890 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/repository/relation-type.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/repository/relation-type.repository.ts @@ -11,12 +11,13 @@ import { UmbDetailRepository } from '@umbraco-cms/backoffice/repository'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; type ItemType = RelationTypeResponseModel; +type TreeItemType = any; // Move to documentation / JSdoc /* We need to create a new instance of the repository from within the element context. We want the notifications to be displayed in the right context. */ // element -> context -> repository -> (store) -> data source // All methods should be async and return a promise. Some methods might return an observable as part of the promise response. -export class UmbRelationTypeRepository implements UmbTreeRepository, UmbDetailRepository { +export class UmbRelationTypeRepository implements UmbTreeRepository, UmbDetailRepository { #init!: Promise; #host: UmbControllerHostInterface; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/collection/collection.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/collection/collection.context.ts index d698ed1f71..3979c74ad9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/collection/collection.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/collection/collection.context.ts @@ -13,7 +13,7 @@ export class UmbCollectionContext; private _store?: any; protected _dataObserver?: UmbObserverController; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts index b7cfcf7654..d366587003 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts @@ -5,6 +5,7 @@ import { } from '../../section/section-sidebar/section-sidebar.context'; import { UmbSectionContext, UMB_SECTION_CONTEXT_TOKEN } from '../../section/section.context'; import { UmbTreeContextBase } from '../tree.context'; +import { UmbTreeItemContext } from '../tree-item.context.interface'; import { BooleanState, StringState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { @@ -14,12 +15,13 @@ import { } from '@umbraco-cms/backoffice/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import type { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; -import { urlFriendlyPathFromServerFilePath } from 'src/backoffice/templating/utils'; // add type for unique function export type UmbTreeItemUniqueFunction = (x: T) => string | null | undefined; -export class UmbTreeItemContextBase { +export class UmbTreeItemContextBase + implements UmbTreeItemContext +{ public host: UmbControllerHostInterface; public treeItem: T; public unique: string; @@ -144,6 +146,7 @@ export class UmbTreeItemContextBase { + this.observe(asObservable(), (childItems: any) => { this._childItems = childItems; }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.context.interface.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.context.interface.ts new file mode 100644 index 0000000000..02f4087bcc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.context.interface.ts @@ -0,0 +1,34 @@ +import { Observable } from 'rxjs'; +import { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; +import { UmbControllerHostInterface } from 'libs/controller/controller-host.mixin'; + +// TODO: temp type. Add paged response type to the repository interface +interface PagedResponse { + total: number; + items: Array; +} + +export interface UmbTreeItemContext { + host: UmbControllerHostInterface; + treeItem: T; + unique: string; + type: string; + + hasChildren: Observable; + isLoading: Observable; + isSelectable: Observable; + isSelected: Observable; + isActive: Observable; + hasActions: Observable; + path: Observable; + + requestChildren(): Promise<{ + data: PagedResponse | undefined; + error: ProblemDetailsModel | undefined; + asObservable?: () => Observable; + }>; + toggleContextMenu(): void; + select(): void; + deselect(): void; + constructPath(pathname: string, entityType: string, unique: string): string; +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts index 9d64f38445..a045817b57 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/repository/stylesheet.repository.ts @@ -11,7 +11,7 @@ import { } from '@umbraco-cms/backoffice/backend-api'; export class UmbStylesheetRepository - implements UmbTreeRepository + implements UmbTreeRepository { #host; #dataSource; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/repository/template.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/repository/template.repository.ts index ef0bb4852e..b8f1044c21 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/repository/template.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/repository/template.repository.ts @@ -9,7 +9,7 @@ import { ProblemDetailsModel, TemplateResponseModel } from '@umbraco-cms/backoff import { UmbDetailRepository } from 'libs/repository/detail-repository.interface'; import { UmbTreeRepository } from 'libs/repository/tree-repository.interface'; -export class UmbTemplateRepository implements UmbTreeRepository, UmbDetailRepository { +export class UmbTemplateRepository implements UmbTreeRepository, UmbDetailRepository { #init; #host: UmbControllerHostInterface; From 7ca21588c47f2c1c517dea8631a3b675bf88f72f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 27 Mar 2023 12:05:29 +0200 Subject: [PATCH 086/114] fix duplicate storybook ids --- .../workspace/stylesheet-workspace.stories.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.stories.ts index 09b9cdb96d..9642c1b6bb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/workspace/stylesheet-workspace.stories.ts @@ -3,16 +3,14 @@ import './stylesheet-workspace.element'; import { Meta, Story } from '@storybook/web-components'; import { html } from 'lit'; -import { data } from '../../../../core/mocks/data/member.data'; - import type { UmbStylesheetWorkspaceElement } from './stylesheet-workspace.element'; export default { - title: 'Workspaces/Member', - component: 'umb-member-workspace', - id: 'umb-member-workspace', + title: 'Workspaces/Stylesheet', + component: 'umb-stylesheet-workspace', + id: 'umb-stylesheet-workspace', } as Meta; export const AAAOverview: Story = () => - html` `; + html` `; AAAOverview.storyName = 'Overview'; From 408f4eb17da99765d930cf0ef45072f92af1d6f7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 27 Mar 2023 12:05:44 +0200 Subject: [PATCH 087/114] add tree docs scaffold --- .../src/stories/extending/tree.mdx | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/stories/extending/tree.mdx diff --git a/src/Umbraco.Web.UI.Client/src/stories/extending/tree.mdx b/src/Umbraco.Web.UI.Client/src/stories/extending/tree.mdx new file mode 100644 index 0000000000..eb0e1c810d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/stories/extending/tree.mdx @@ -0,0 +1,127 @@ +import { Meta } from '@storybook/addon-docs'; + + + +# Trees + +// TODO: add description of trees. +Rough notes: +The tree is a hierarchical structure of nodes. The tree is registered in the Backoffice extension registry. A tree can be rendered anywhere in the Backoffice with the help of the umb-tree element. + +## Registering a tree + +Tree Manifest + +```json +// TODO: add interface +{ + "type": "tree", + "alias": "My.Tree.Alias", + "name": "My Tree", + "meta": { + "repositoryAlias": "My.Repository.Alias" + } +}, +{ + "type": "treeItem", + "kind": "entity", + "alias": "My.TreeItem.Alias", + "name": "My Tree Item", + "conditions": { + "entityType": "my-entity-type", + }, +} +``` + +The backoffice comes with two different tree item kinds out of the box: +entity and fileSystem + +## Rendering a tree + +```html + +``` + +## Render a Custom Tree Item + +The Tree Item Manifest + +```json +{ + "type": "treeItem", + "alias": "Umb.TreeItem.Alias", + "name": "My Tree Item", + "js": "./my-tree-item.element.js", + "conditions": { + "entityType": "my-entity-type", + }, +}; +``` + +### The Tree Item Element + +```typescript +import { css, html, nothing } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { UmbElementMixin } from '@umbraco-cms/backoffice/element'; +import { UmbMyTreeItemContext, MyTreeItemDataModel } from './my-tree-item.context'; + +@customElement('my-tree-item') +export class MyTreeItemElement extends UmbElementMixin(LitElement) { + @property({ type: Object, attribute: false }) + public item?: MyTreeItemDataModel; + + render() { + if (!this.item) return nothing; + new UmbMyTreeItemContext(this, this.item); + return html` Some custom markup `; + } +} + +export default MyTreeItemElement; +``` + +### The Tree Item Context + +```typescript +// TODO: auto generate this from the interface +export interface UmbTreeItemContext { + host: UmbControllerHostInterface; + treeItem: T; + unique: string; + type: string; + + hasChildren: Observable; + isLoading: Observable; + isSelectable: Observable; + isSelected: Observable; + isActive: Observable; + hasActions: Observable; + path: Observable; + + requestChildren(): Promise<{ + data: PagedResponse | undefined; + error: ProblemDetailsModel | undefined; + asObservable?: () => Observable; + }>; + + toggleContextMenu(): void; + select(): void; + deselect(): void; + constructPath(pathname: string, entityType: string, unique: string): string; +} +``` + +### Extending the Tree Item Context base + +We provide a base class for the tree item context. This class provides some default implementations for the context. You can extend this class to overwrite any of the default implementations. + +```typescript +export class UmbMyTreeItemContext extends UmbTreeItemContextBase { + constructor(host: UmbControllerHostInterface, treeItem: MyTreeItemDataModel) { + super(host, treeItem, (x: MyTreeItemDataModel) => x.unique); + } + + // overwrite any methods or properties here if needed +} +``` From 9d4b0a76679ec8ca8e487d1942020f86621b4d11 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 27 Mar 2023 12:06:52 +0200 Subject: [PATCH 088/114] add tree to intro links --- src/Umbraco.Web.UI.Client/src/stories/extending/intro.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/stories/extending/intro.mdx b/src/Umbraco.Web.UI.Client/src/stories/extending/intro.mdx index c0ede6a70b..dbb9dcb584 100644 --- a/src/Umbraco.Web.UI.Client/src/stories/extending/intro.mdx +++ b/src/Umbraco.Web.UI.Client/src/stories/extending/intro.mdx @@ -16,3 +16,4 @@ The Umbraco Backoffice currently support the following extension types: - [Property Editor](?path=/docs/guides-extending-the-backoffice-property-editors--docs) - [Repository](?path=/docs/guides-extending-the-backoffice-property-editors--docs) - [Menu](?path=/docs/guides-extending-the-backoffice-menu--docs) +- [Tree](?path=/docs/guides-extending-the-backoffice-trees--docs) From cf361b2dd390d1a3d0b121ae9adc98f2078a8ff4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 27 Mar 2023 13:25:58 +0200 Subject: [PATCH 089/114] use repository alias in tree manifest --- .../libs/extensions-registry/tree.models.ts | 3 +- .../document-types/tree/manifests.ts | 4 +- .../documents/documents/tree/manifests.ts | 4 +- .../media/media-types/tree/manifests.ts | 4 +- .../backoffice/media/media/tree/manifests.ts | 4 +- .../members/member-groups/tree/manifests.ts | 4 +- .../members/member-types/tree/manifests.ts | 4 +- .../members/members/tree/manifests.ts | 4 +- .../settings/data-types/tree/manifests.ts | 4 +- .../settings/relation-types/tree/manifests.ts | 4 +- .../tree-item-base/tree-item-base.context.ts | 2 +- .../shared/components/tree/tree.context.ts | 57 +++++++++++++++---- .../templating/stylesheets/tree/manifests.ts | 4 +- .../templating/templates/tree/manifests.ts | 4 +- .../translation/dictionary/tree/manifests.ts | 4 +- 15 files changed, 72 insertions(+), 38 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/extensions-registry/tree.models.ts b/src/Umbraco.Web.UI.Client/libs/extensions-registry/tree.models.ts index 8dbce1f603..49e8387bb4 100644 --- a/src/Umbraco.Web.UI.Client/libs/extensions-registry/tree.models.ts +++ b/src/Umbraco.Web.UI.Client/libs/extensions-registry/tree.models.ts @@ -1,5 +1,4 @@ import type { ManifestBase } from './models'; -import type { ClassConstructor } from '@umbraco-cms/backoffice/models'; export interface ManifestTree extends ManifestBase { type: 'tree'; @@ -7,5 +6,5 @@ export interface ManifestTree extends ManifestBase { } export interface MetaTree { - repository?: ClassConstructor; + repositoryAlias: string; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/tree/manifests.ts index 30b9f1493a..5a5ccaa08d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/tree/manifests.ts @@ -1,4 +1,4 @@ -import { UmbDocumentTypeRepository } from '../repository/document-type.repository'; +import { DOCUMENT_TYPE_REPOSITORY_ALIAS } from '../repository/manifests'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { @@ -6,7 +6,7 @@ const tree: ManifestTree = { alias: 'Umb.Tree.DocumentTypes', name: 'Document Types Tree', meta: { - repository: UmbDocumentTypeRepository, + repositoryAlias: DOCUMENT_TYPE_REPOSITORY_ALIAS, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts index ee92e43e8d..a5dbe90321 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/manifests.ts @@ -1,4 +1,4 @@ -import { UmbDocumentRepository } from '../repository/document.repository'; +import { DOCUMENT_REPOSITORY_ALIAS } from '../repository/manifests'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const treeAlias = 'Umb.Tree.Documents'; @@ -8,7 +8,7 @@ const tree: ManifestTree = { alias: treeAlias, name: 'Documents Tree', meta: { - repository: UmbDocumentRepository, // TODO: use alias instead of class + repositoryAlias: DOCUMENT_REPOSITORY_ALIAS, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/tree/manifests.ts index 164fec3904..fff9c37137 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media-types/tree/manifests.ts @@ -1,4 +1,4 @@ -import { UmbMediaTypeRepository } from '../repository/media-type.repository'; +import { MEDIA_TYPE_REPOSITORY_ALIAS } from '../repository/manifests'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { @@ -6,7 +6,7 @@ const tree: ManifestTree = { alias: 'Umb.Tree.MediaTypes', name: 'Media Types Tree', meta: { - repository: UmbMediaTypeRepository, + repositoryAlias: MEDIA_TYPE_REPOSITORY_ALIAS, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/tree/manifests.ts index b3aa588fdf..b66042c3ba 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/tree/manifests.ts @@ -1,4 +1,4 @@ -import { UmbMediaRepository } from '../repository/media.repository'; +import { MEDIA_REPOSITORY_ALIAS } from '../repository/manifests'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const treeAlias = 'Umb.Tree.Media'; @@ -8,7 +8,7 @@ const tree: ManifestTree = { alias: treeAlias, name: 'Media Tree', meta: { - repository: UmbMediaRepository, // TODO: use alias instead of class + repositoryAlias: MEDIA_REPOSITORY_ALIAS, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/tree/manifests.ts index f4e3c2bb10..5d379a3782 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/tree/manifests.ts @@ -1,4 +1,4 @@ -import { UmbMemberGroupRepository } from '../repository/member-group.repository'; +import { MEMBER_GROUP_REPOSITORY_ALIAS } from '../repository/manifests'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const treeAlias = 'Umb.Tree.MemberGroups'; @@ -9,7 +9,7 @@ const tree: ManifestTree = { name: 'Member Groups Tree', weight: 100, meta: { - repository: UmbMemberGroupRepository, + repositoryAlias: MEMBER_GROUP_REPOSITORY_ALIAS, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/tree/manifests.ts index e15489ab38..6781a419f4 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-types/tree/manifests.ts @@ -1,4 +1,4 @@ -import { UmbMemberTypeRepository } from '../repository/member-type.repository'; +import { MEMBER_TYPES_REPOSITORY_ALIAS } from '../repository/manifests'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const treeAlias = 'Umb.Tree.MemberTypes'; @@ -8,7 +8,7 @@ const tree: ManifestTree = { alias: treeAlias, name: 'Member Types Tree', meta: { - repository: UmbMemberTypeRepository, + repositoryAlias: MEMBER_TYPES_REPOSITORY_ALIAS, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/members/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/members/tree/manifests.ts index 00ee74f8c0..e30a124927 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/members/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/members/tree/manifests.ts @@ -1,4 +1,4 @@ -import { UmbMemberRepository } from '../repository/member.repository'; +import { MEMBER_REPOSITORY_ALIAS } from '../repository/manifests'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { @@ -7,7 +7,7 @@ const tree: ManifestTree = { name: 'Members Tree', weight: 10, meta: { - repository: UmbMemberRepository, + repositoryAlias: MEMBER_REPOSITORY_ALIAS, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/tree/manifests.ts index 253a74a011..49c0a602a4 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/tree/manifests.ts @@ -1,4 +1,4 @@ -import { UmbDataTypeRepository } from '../repository/data-type.repository'; +import { DATA_TYPE_REPOSITORY_ALIAS } from '../repository/manifests'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { @@ -6,7 +6,7 @@ const tree: ManifestTree = { alias: 'Umb.Tree.DataTypes', name: 'Data Types Tree', meta: { - repository: UmbDataTypeRepository, + repositoryAlias: DATA_TYPE_REPOSITORY_ALIAS, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/tree/manifests.ts index c362124d31..42dc1f26cf 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/relation-types/tree/manifests.ts @@ -1,4 +1,4 @@ -import { UmbRelationTypeRepository } from '../repository/relation-type.repository'; +import { RELATION_TYPE_REPOSITORY_ALIAS } from '../repository/manifests'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { @@ -6,7 +6,7 @@ const tree: ManifestTree = { alias: 'Umb.Tree.RelationTypes', name: 'Relation Types Tree', meta: { - repository: UmbRelationTypeRepository, + repositoryAlias: RELATION_TYPE_REPOSITORY_ALIAS, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts index d366587003..796cabce56 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts @@ -73,7 +73,7 @@ export class UmbTreeItemContextBase>[]); public readonly selection = this.#selection.asObservable(); - repository!: UmbTreeRepository; + repository?: UmbTreeRepository; + + #initResolver?: () => void; + #initialized = false; + + #init = new Promise((resolve) => { + this.#initialized ? resolve() : (this.#initResolver = resolve); + }); constructor(host: UmbControllerHostInterface, tree: ManifestTree) { - this.#host = host; + this.host = host; this.tree = tree; - if (this.tree.meta.repository) { - // TODO: should be using the right extension and the createExtensionClass method. - this.repository = new this.tree.meta.repository(this.#host) as any; + const repositoryAlias = this.tree.meta.repositoryAlias; + if (!repositoryAlias) throw new Error('Tree must have a repository alias.'); + + new UmbObserverController( + this.host, + umbExtensionsRegistry.getByTypeAndAlias('repository', this.tree.meta.repositoryAlias), + async (repositoryManifest) => { + if (!repositoryManifest) return; + + try { + const result = await createExtensionClass(repositoryManifest, [this.host]); + this.repository = result; + this.#checkIfInitialized(); + } catch (error) { + throw new Error('Could not create repository with alias: ' + repositoryAlias + ''); + } + } + ); + } + + // TODO: find a generic way to do this + #checkIfInitialized() { + if (this.repository) { + this.#initialized = true; + this.#initResolver?.(); } } @@ -58,18 +89,22 @@ export class UmbTreeContextBase implements UmbTreeContext { } public async requestRootItems() { - return this.repository.requestRootTreeItems(); + await this.#init; + return this.repository!.requestRootTreeItems(); } public async requestChildrenOf(parentKey: string | null) { - return this.repository.requestTreeItemsOf(parentKey); + await this.#init; + return this.repository!.requestTreeItemsOf(parentKey); } public async rootItems() { - return this.repository.rootTreeItems(); + await this.#init; + return this.repository!.rootTreeItems(); } public async childrenOf(parentKey: string | null) { - return this.repository.treeItemsOf(parentKey); + await this.#init; + return this.repository!.treeItemsOf(parentKey); } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/tree/manifests.ts index f3430be1ec..c93536bd70 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/stylesheets/tree/manifests.ts @@ -1,5 +1,5 @@ -import { UmbStylesheetRepository } from '../repository/stylesheet.repository'; import { STYLESHEET_ENTITY_TYPE } from '..'; +import { STYLESHEET_REPOSITORY_ALIAS } from '../repository/manifests'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; export const STYLESHEET_TREE_ALIAS = 'Umb.Tree.Stylesheet'; @@ -10,7 +10,7 @@ const tree: ManifestTree = { name: 'Stylesheet Tree', weight: 10, meta: { - repository: UmbStylesheetRepository, + repositoryAlias: STYLESHEET_REPOSITORY_ALIAS, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/tree/manifests.ts index 0a9f6a445a..466a222f9d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/templates/tree/manifests.ts @@ -1,4 +1,4 @@ -import { UmbTemplateRepository } from '../repository/template.repository'; +import { TEMPLATE_REPOSITORY_ALIAS } from '../repository/manifests'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { @@ -6,7 +6,7 @@ const tree: ManifestTree = { alias: 'Umb.Tree.Templates', name: 'Templates Tree', meta: { - repository: UmbTemplateRepository, + repositoryAlias: TEMPLATE_REPOSITORY_ALIAS, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/tree/manifests.ts index db5158f921..dcfeba9411 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/tree/manifests.ts @@ -1,4 +1,4 @@ -import { UmbDictionaryRepository } from '../repository/dictionary.repository'; +import { DICTIONARY_REPOSITORY_ALIAS } from '../repository/manifests'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extensions-registry'; const tree: ManifestTree = { @@ -6,7 +6,7 @@ const tree: ManifestTree = { alias: 'Umb.Tree.Dictionary', name: 'Dictionary Tree', meta: { - repository: UmbDictionaryRepository, + repositoryAlias: DICTIONARY_REPOSITORY_ALIAS, }, }; From 632a5d1a09ff9036e52963791e28d7f0437b6037 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 27 Mar 2023 13:35:21 +0200 Subject: [PATCH 090/114] fix route --- .../components/tree/tree-item-base/tree-item-base.context.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts index 796cabce56..43212da66f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts @@ -148,7 +148,7 @@ export class UmbTreeItemContextBase Date: Tue, 28 Mar 2023 10:22:01 +0200 Subject: [PATCH 091/114] todo --- .../input-template-picker/input-template-picker.element.ts | 4 ++-- .../shared/modals/template/template-modal.element.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts index 90ae4e7cfb..7eac9a58c5 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts @@ -137,7 +137,6 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen } #openPicker() { - //TODO: Tree-picker modal? const modalHandler = this._modalContext?.open(UMB_TEMPLATE_PICKER_MODAL_TOKEN, { multiple: true, selection: [...this.allowedKeys], @@ -145,6 +144,7 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen modalHandler?.onSubmit().then((data) => { if (!data.selection) return; + //TODO: a better way to do this? this.templates = []; this.allowedKeys = data.selection; this.allowedKeys.forEach((key) => this.#setup(key)); @@ -193,7 +193,7 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen }); modalHandler?.onSubmit().then(({ key }) => { - // TODO: update list + // TODO: update template }); } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts index 8d6fa4bf4c..a3e156f832 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts @@ -38,7 +38,7 @@ export class UmbTemplateModalElement extends UmbModalBaseElement Date: Tue, 28 Mar 2023 10:31:20 +0200 Subject: [PATCH 092/114] build err --- .../input-document-type-picker.element.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts index 6eb5872571..acf5977054 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts @@ -99,7 +99,7 @@ export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitEl }); } - private async _removeItem(item: EntityTreeItemResponseModel) { + private async _removeItem(item: DocumentTypeResponseModel) { const modalHandler = this._modalContext?.open(UMB_CONFIRM_MODAL_TOKEN, { color: 'danger', headline: `Remove ${item.name}?`, @@ -129,9 +129,9 @@ export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitEl `; } - private _renderItem(item: EntityTreeItemResponseModel) { + private _renderItem(item: DocumentTypeResponseModel) { // TODO: remove when we have a way to handle trashed items - const tempItem = item as EntityTreeItemResponseModel & { isTrashed: boolean }; + const tempItem = item as DocumentTypeResponseModel & { isTrashed: boolean }; return html` From afc1e8098363d675c1fe52fa191e442906272a09 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 28 Mar 2023 10:59:47 +0200 Subject: [PATCH 093/114] Update libs/store/file-system-tree.store.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Niels Lyngsø --- src/Umbraco.Web.UI.Client/libs/store/file-system-tree.store.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/libs/store/file-system-tree.store.ts b/src/Umbraco.Web.UI.Client/libs/store/file-system-tree.store.ts index 0d798b71d5..384ff4d883 100644 --- a/src/Umbraco.Web.UI.Client/libs/store/file-system-tree.store.ts +++ b/src/Umbraco.Web.UI.Client/libs/store/file-system-tree.store.ts @@ -27,7 +27,7 @@ export class UmbFileSystemTreeStore extends UmbStoreBase implements UmbTreeStore * @memberof UmbFileSystemTreeStore */ updateItem(path: string, data: Partial) { - this.#data.next(partialUpdateFrozenArray(this.#data.getValue(), data, (entry) => entry.path === path)); + this.#data.appendOne(data) } /** From ee7be0472ca65656e71e1e899bba5a8b48cb6787 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 28 Mar 2023 13:17:53 +0200 Subject: [PATCH 094/114] add setTreeItem method on TreeItemContext instead of setting it in the constructor --- .../tree-item/document-tree-item.context.ts | 4 +- .../tree-item/document-tree-item.element.ts | 16 +++-- .../entity-tree-item.context.ts | 4 +- .../entity-tree-item.element.ts | 14 +++- .../tree-item-base/tree-item-base.context.ts | 66 +++++++++++++------ .../tree-item-base/tree-item-base.element.ts | 24 +++---- .../tree-item-base/tree-item-base.stories.ts | 17 +---- .../tree/tree-item.context.interface.ts | 11 ++-- .../file-system-tree-item.context.ts | 4 +- .../file-system-tree-item.element.ts | 14 +++- 10 files changed, 103 insertions(+), 71 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.context.ts index 49c2653424..19cfaf1ccd 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.context.ts @@ -4,7 +4,7 @@ import { DocumentTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-a // TODO get unique method from an document repository static method export class UmbDocumentTreeItemContext extends UmbTreeItemContextBase { - constructor(host: UmbControllerHostInterface, treeItem: DocumentTreeItemResponseModel) { - super(host, treeItem, (x: DocumentTreeItemResponseModel) => x.key); + constructor(host: UmbControllerHostInterface) { + super(host, (x: DocumentTreeItemResponseModel) => x.key); } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts index 68ab99af32..e71f162a4b 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/tree/tree-item/document-tree-item.element.ts @@ -31,16 +31,22 @@ export class UmbDocumentTreeItemElement extends UmbLitElement { `, ]; + private _item?: DocumentTreeItemResponseModel; @property({ type: Object, attribute: false }) - public item?: DocumentTreeItemResponseModel; + public get item() { + return this._item; + } + public set item(value: DocumentTreeItemResponseModel | undefined) { + this._item = value; + this.#context.setTreeItem(value); + } + + #context = new UmbDocumentTreeItemContext(this); render() { if (!this.item) return nothing; - new UmbDocumentTreeItemContext(this, this.item); return html` - - ${this.#renderIconWithStatusSymbol()} ${this.#renderLabel()} - + ${this.#renderIconWithStatusSymbol()} ${this.#renderLabel()} `; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.context.ts index 934cd4b874..2b014d81c1 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.context.ts @@ -4,7 +4,7 @@ import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api // TODO get unique method from an entity repository static method export class UmbEntityTreeItemContext extends UmbTreeItemContextBase { - constructor(host: UmbControllerHostInterface, treeItem: EntityTreeItemResponseModel) { - super(host, treeItem, (x: EntityTreeItemResponseModel) => x.key); + constructor(host: UmbControllerHostInterface) { + super(host, (x: EntityTreeItemResponseModel) => x.key); } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.element.ts index 7540c8156c..11fd1f40f3 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/entity-tree-item/entity-tree-item.element.ts @@ -24,13 +24,21 @@ umbExtensionsRegistry.register(manifest); export class UmbEntityTreeItemElement extends UmbLitElement { static styles = [UUITextStyles, css``]; + private _item?: EntityTreeItemResponseModel; @property({ type: Object, attribute: false }) - item?: EntityTreeItemResponseModel; + public get item() { + return this._item; + } + public set item(value: EntityTreeItemResponseModel | undefined) { + this._item = value; + this.#context.setTreeItem(value); + } + + #context = new UmbEntityTreeItemContext(this); render() { if (!this.item) return nothing; - new UmbEntityTreeItemContext(this, this.item); - return html``; + return html``; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts index 43212da66f..25c3a500cb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts @@ -6,7 +6,7 @@ import { import { UmbSectionContext, UMB_SECTION_CONTEXT_TOKEN } from '../../section/section.context'; import { UmbTreeContextBase } from '../tree.context'; import { UmbTreeItemContext } from '../tree-item.context.interface'; -import { BooleanState, StringState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; +import { BooleanState, DeepState, StringState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbContextConsumerController, @@ -23,9 +23,11 @@ export class UmbTreeItemContextBase { public host: UmbControllerHostInterface; - public treeItem: T; - public unique: string; - public type: string; + public unique?: string; + public type?: string; + + #treeItem = new DeepState(undefined); + treeItem = this.#treeItem.asObservable(); #hasChildren = new BooleanState(false); hasChildren = this.#hasChildren.asObservable(); @@ -51,26 +53,36 @@ export class UmbTreeItemContextBase; - constructor(host: UmbControllerHostInterface, treeItem: T, getUniqueFunction: UmbTreeItemUniqueFunction) { + constructor(host: UmbControllerHostInterface, getUniqueFunction: UmbTreeItemUniqueFunction) { this.host = host; - this.treeItem = treeItem; - - const unique = getUniqueFunction(this.treeItem); - if (!unique) throw new Error('Could not create tree item context, unique key is missing'); - this.unique = unique; - - if (!this.treeItem.type) throw new Error('Could not create tree item context, tree item type is missing'); - this.type = this.treeItem.type; - + this.#getUniqueFunction = getUniqueFunction; this.#observeTreeItemActions(); - this.#hasChildren.next(this.treeItem.hasChildren || false); - this.#consumeContexts(); new UmbContextProviderController(host, UMB_TREE_ITEM_CONTEXT_TOKEN, this); } + public setTreeItem(treeItem: T | undefined) { + if (!treeItem) { + this.#treeItem.next(undefined); + return; + } + + const unique = this.#getUniqueFunction(treeItem); + if (!unique) throw new Error('Could not create tree item context, unique key is missing'); + this.unique = unique; + + if (!treeItem.type) throw new Error('Could not create tree item context, tree item type is missing'); + this.type = treeItem.type; + + this.#hasChildren.next(treeItem.hasChildren || false); + this.#treeItem.next(treeItem); + } + public async requestChildren() { + if (!this.unique) throw new Error('Could not request children, unique key is missing'); + // TODO: wait for tree context to be ready this.#isLoading.next(true); const response = await this.treeContext!.requestChildrenOf(this.unique); @@ -79,14 +91,20 @@ export class UmbTreeItemContextBase this.#isSelectable.next(value)); } #observeIsSelected() { - if (!this.treeContext) return; + if (!this.treeContext) throw new Error('Could not request children, tree context is missing'); + if (!this.unique) throw new Error('Could not request children, unique key is missing'); new UmbObserverController( this.host, - this.treeContext.selection.pipe(map((selection) => selection.includes(this.unique))), + this.treeContext.selection.pipe(map((selection) => selection.includes(this.unique!))), (isSelected) => { this.#isSelected.next(isSelected); } @@ -129,6 +152,9 @@ export class UmbTreeItemContextBase { if (!pathname) return; + if (!this.type) throw new Error('Cant construct path, entity type is missing'); + if (!this.unique) throw new Error('Cant construct path, unique is missing'); + const path = this.constructPath(pathname, this.type, this.unique); this.#path.next(path); }); @@ -152,4 +178,4 @@ export class UmbTreeItemContextBase('UmbTreeItemContext'); +export const UMB_TREE_ITEM_CONTEXT_TOKEN = new UmbContextToken('UmbTreeItemContext'); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts index b07e42dbae..a2b059421c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.element.ts @@ -1,9 +1,10 @@ import { css, html, nothing } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, property, state } from 'lit/decorators.js'; +import { customElement, state } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { repeat } from 'lit/directives/repeat.js'; -import { UmbTreeItemContextBase, UMB_TREE_ITEM_CONTEXT_TOKEN } from './tree-item-base.context'; +import { UmbTreeItemContext } from '../tree-item.context.interface'; +import { UMB_TREE_ITEM_CONTEXT_TOKEN } from './tree-item-base.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; @@ -11,16 +12,8 @@ import { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; export class UmbTreeItemBaseElement extends UmbLitElement { static styles = [UUITextStyles, css``]; + @state() private _item?: TreeItemPresentationModel; - @property({ type: Object, attribute: false }) - get item() { - return this._item; - } - set item(newVal) { - const oldVal = this._item; - this._item = newVal; - this.requestUpdate('item', oldVal); - } @state() private _childItems?: TreeItemPresentationModel[]; @@ -46,7 +39,7 @@ export class UmbTreeItemBaseElement extends UmbLitElement { @state() private _iconSlotHasChildren = false; - #treeItemContext?: UmbTreeItemContextBase; + #treeItemContext?: UmbTreeItemContext; constructor() { super(); @@ -55,6 +48,7 @@ export class UmbTreeItemBaseElement extends UmbLitElement { this.#treeItemContext = instance; if (!this.#treeItemContext) return; // TODO: investigate if we can make an observe decorator + this.observe(this.#treeItemContext.treeItem, (value) => (this._item = value)); this.observe(this.#treeItemContext.hasChildren, (value) => (this._hasChildren = value)); this.observe(this.#treeItemContext.isLoading, (value) => (this._isLoading = value)); this.observe(this.#treeItemContext.isSelectable, (value) => (this._isSelectable = value)); @@ -109,7 +103,7 @@ export class UmbTreeItemBaseElement extends UmbLitElement { ?selected=${this._isSelected} .loading=${this._isLoading} .hasChildren=${this._hasChildren} - label="${ifDefined(this.item?.name)}" + label="${ifDefined(this._item?.name)}" href="${ifDefined(this._href)}"> ${this.#renderIcon()} ${this.#renderLabel()} ${this.#renderActions()} ${this.#renderChildItems()} @@ -129,8 +123,8 @@ export class UmbTreeItemBaseElement extends UmbLitElement { @slotchange=${(e: Event) => { this._iconSlotHasChildren = this.#hasNodes(e); }}> - ${this.item?.icon && !this._iconSlotHasChildren - ? html` ` + ${this._item?.icon && !this._iconSlotHasChildren + ? html` ` : nothing} `; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.stories.ts index fedf14fccb..f81fe83f46 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.stories.ts @@ -2,6 +2,7 @@ import { Meta, StoryObj } from '@storybook/web-components'; import './tree-item-base.element'; import type { UmbTreeItemBaseElement } from './tree-item-base.element'; +// TODO: provide tree item context to make this element render properly const meta: Meta = { title: 'Components/Tree/Tree Item', component: 'umb-tree-item', @@ -11,21 +12,9 @@ export default meta; type Story = StoryObj; export const Overview: Story = { - args: { - item: { - name: 'My Tree Item', - icon: 'umb:home', - hasChildren: false, - }, - }, + args: {}, }; export const WithChildren: Story = { - args: { - item: { - name: 'My Tree Item', - icon: 'umb:home', - hasChildren: true, - }, - }, + args: {}, }; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.context.interface.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.context.interface.ts index 02f4087bcc..0144422f76 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item.context.interface.ts @@ -1,5 +1,5 @@ import { Observable } from 'rxjs'; -import { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; +import { ProblemDetailsModel, TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostInterface } from 'libs/controller/controller-host.mixin'; // TODO: temp type. Add paged response type to the repository interface @@ -8,12 +8,12 @@ interface PagedResponse { items: Array; } -export interface UmbTreeItemContext { +export interface UmbTreeItemContext { host: UmbControllerHostInterface; - treeItem: T; - unique: string; - type: string; + unique?: string; + type?: string; + treeItem: Observable; hasChildren: Observable; isLoading: Observable; isSelectable: Observable; @@ -22,6 +22,7 @@ export interface UmbTreeItemContext { hasActions: Observable; path: Observable; + setTreeItem(treeItem: T | undefined): void; requestChildren(): Promise<{ data: PagedResponse | undefined; error: ProblemDetailsModel | undefined; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts index 35f216062e..92d1f20549 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.context.ts @@ -5,8 +5,8 @@ import { FileSystemTreeItemPresentationModel } from '@umbraco-cms/backoffice/bac // TODO get unique method from an entity repository static method export class UmbFileSystemTreeItemContext extends UmbTreeItemContextBase { - constructor(host: UmbControllerHostInterface, treeItem: FileSystemTreeItemPresentationModel) { - super(host, treeItem, (x: FileSystemTreeItemPresentationModel) => x.path); + constructor(host: UmbControllerHostInterface) { + super(host, (x: FileSystemTreeItemPresentationModel) => x.path); } constructPath(pathname: string, entityType: string, path: string) { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.element.ts index 3572e6dccc..1d18dc610a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/templating/components/file-system-tree-item/file-system-tree-item.element.ts @@ -24,13 +24,21 @@ umbExtensionsRegistry.register(manifest); export class UmbFileSystemTreeItemElement extends UmbLitElement { static styles = [UUITextStyles, css``]; + private _item?: FileSystemTreeItemPresentationModel; @property({ type: Object, attribute: false }) - item?: FileSystemTreeItemPresentationModel; + public get item() { + return this._item; + } + public set item(value: FileSystemTreeItemPresentationModel | undefined) { + this._item = value; + this.#context.setTreeItem(value); + } + + #context = new UmbFileSystemTreeItemContext(this); render() { if (!this.item) return nothing; - new UmbFileSystemTreeItemContext(this, this.item); - return html``; + return html``; } } From ca2baab3f7aff185547b61c28d860a7c80150a0c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 28 Mar 2023 13:26:16 +0200 Subject: [PATCH 095/114] update story book docs --- .../src/stories/extending/tree.mdx | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/stories/extending/tree.mdx b/src/Umbraco.Web.UI.Client/src/stories/extending/tree.mdx index eb0e1c810d..98b44058f9 100644 --- a/src/Umbraco.Web.UI.Client/src/stories/extending/tree.mdx +++ b/src/Umbraco.Web.UI.Client/src/stories/extending/tree.mdx @@ -68,13 +68,21 @@ import { UmbMyTreeItemContext, MyTreeItemDataModel } from './my-tree-item.contex @customElement('my-tree-item') export class MyTreeItemElement extends UmbElementMixin(LitElement) { + private _item?: MyTreeItemDataModel; @property({ type: Object, attribute: false }) - public item?: MyTreeItemDataModel; + public get item() { + return this._item; + } + public set item(value: MyTreeItemDataModel | undefined) { + this._item = value; + this.#context.setTreeItem(value); + } + + #context = new UmbMyTreeItemContext(this); render() { if (!this.item) return nothing; - new UmbMyTreeItemContext(this, this.item); - return html` Some custom markup `; + return html` Some custom markup `; } } @@ -87,10 +95,10 @@ export default MyTreeItemElement; // TODO: auto generate this from the interface export interface UmbTreeItemContext { host: UmbControllerHostInterface; - treeItem: T; - unique: string; - type: string; + unique?: string; + type?: string; + treeItem: Observable; hasChildren: Observable; isLoading: Observable; isSelectable: Observable; @@ -99,12 +107,13 @@ export interface UmbTreeItemContext { hasActions: Observable; path: Observable; + setTreeItem(treeItem: T | undefined): void; + requestChildren(): Promise<{ data: PagedResponse | undefined; error: ProblemDetailsModel | undefined; asObservable?: () => Observable; }>; - toggleContextMenu(): void; select(): void; deselect(): void; @@ -118,8 +127,8 @@ We provide a base class for the tree item context. This class provides some defa ```typescript export class UmbMyTreeItemContext extends UmbTreeItemContextBase { - constructor(host: UmbControllerHostInterface, treeItem: MyTreeItemDataModel) { - super(host, treeItem, (x: MyTreeItemDataModel) => x.unique); + constructor(host: UmbControllerHostInterface) { + super(host, (x: MyTreeItemDataModel) => x.unique); } // overwrite any methods or properties here if needed From dfac9ade835d5c6e64f9cd501a7f3dcd5152b724 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 28 Mar 2023 13:30:47 +0200 Subject: [PATCH 096/114] don't render anything if there is no item --- .../shared/components/tree/tree-item/tree-item.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts index d91f31c020..9cecba3412 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item/tree-item.element.ts @@ -1,4 +1,4 @@ -import { css, html } from 'lit'; +import { css, html, nothing } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property } from 'lit/decorators.js'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @@ -13,6 +13,7 @@ export class UmbTreeItemElement extends UmbLitElement { item?: TreeItemPresentationModel; render() { + if (!this.item) return nothing; return html` manifests.conditions.entityType === this.item?.type} From dc10f4ccc8b88e47f11192cef6672afe7e581e1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 14:00:35 +0200 Subject: [PATCH 097/114] some style adjustment to property action menu --- .../shared/property-action-menu/property-action-menu.element.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-actions/shared/property-action-menu/property-action-menu.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-actions/shared/property-action-menu/property-action-menu.element.ts index 2a49f5beb7..ff51de4e4d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-actions/shared/property-action-menu/property-action-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-actions/shared/property-action-menu/property-action-menu.element.ts @@ -26,6 +26,8 @@ export class UmbPropertyActionMenuElement extends UmbLitElement { #popover-trigger { --uui-button-padding-top-factor: 0.5; --uui-button-padding-bottom-factor: 0.1; + --uui-button-height: 18px; + --uui-button-border-radius: 6px; } #dropdown { From 36f6a525e23abf6f6970e832be03e48bb18773f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 14:00:53 +0200 Subject: [PATCH 098/114] clean up document types in document workspace (#623) * clean up document types in document workspace * add missing import --------- Co-authored-by: Mads Rasmussen --- .../workspace-property-structure-manager.class.ts | 4 ++-- .../workspace/workspace-variant/workspace-variant.element.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-property-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-property-structure-manager.class.ts index 6b1201a965..bf46f4dc6b 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-property-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/workspace/workspace-context/workspace-property-structure-manager.class.ts @@ -32,8 +32,8 @@ export class UmbWorkspacePropertyStructureManager Date: Tue, 28 Mar 2023 14:07:06 +0200 Subject: [PATCH 099/114] style for add group button --- .../views/design/workspace-view-document-type-design.element.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts index a27bfb57fb..d78404631f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts @@ -63,6 +63,7 @@ export class UmbWorkspaceViewDocumentTypeDesignElement extends UmbLitElement { #add-group { margin-top: var(--uui-size-layout-1); width: 100%; + --uui-button-height: var(--uui-size-layout-4); } .group-headline { From 2c5a81c7713cd41dc32437673a3e9b1f803e1796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 14:26:23 +0200 Subject: [PATCH 100/114] todo and clean up --- .../design/workspace-view-document-type-design.element.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts index d78404631f..f66d0a878b 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts @@ -2,10 +2,10 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, query, state } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; +import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; import '../../../../../shared/property-creator/property-creator.element.ts'; -import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; @customElement('umb-workspace-view-document-type-design') export class UmbWorkspaceViewDocumentTypeDesignElement extends UmbLitElement { @@ -15,6 +15,7 @@ export class UmbWorkspaceViewDocumentTypeDesignElement extends UmbLitElement { :host { display: block; } + /* TODO: This should be replaced with a general workspace bar — naming is hard */ #workspace-tab-bar { padding: 0 var(--uui-size-layout-1); display: flex; @@ -84,9 +85,6 @@ export class UmbWorkspaceViewDocumentTypeDesignElement extends UmbLitElement { @state() private _tabs: any[] = []; - @query('uui-tab-group') - private _tabgroup?: HTMLElement; - constructor() { super(); From 4c8962caad12cdfe43f92020ae4649258fde9950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 14:29:48 +0200 Subject: [PATCH 101/114] comment --- .../input-template-picker/input-template-picker.element.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts index 7eac9a58c5..3b9a800080 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts @@ -194,6 +194,7 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen modalHandler?.onSubmit().then(({ key }) => { // TODO: update template + // Hopefully our Template Repository will make sure this happens automatically, But lets follow up. }); } } From 96a1d49a4947e691bdfb88e7a4906734ecc66d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 14:30:02 +0200 Subject: [PATCH 102/114] left out code --- .../input-template-picker/input-template-picker.element.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts index 3b9a800080..ab7f4e4620 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts @@ -192,10 +192,12 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen language: 'razor', }); + /* modalHandler?.onSubmit().then(({ key }) => { // TODO: update template // Hopefully our Template Repository will make sure this happens automatically, But lets follow up. }); + */ } } From 36de4f2d2e8616282ac855877dc07740ed16e979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 14:35:16 +0200 Subject: [PATCH 103/114] UX comment --- .../input-template-picker.element.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts index ab7f4e4620..ad5272d884 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts @@ -153,7 +153,15 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen } #removeTemplate(key: string) { - console.log('picker: remove', key); + /* + TODO: We need to follow up on this experience. + Could we test if this document type is in use, if so we should have a dialog notifying the user(Dialog, are you sure...) about that we might will break something? + If thats the case, Im not why if a template will be removed from an actual document. + If if its just the option that will go away. + (Comment by Niels) + In current backoffice we just prevent deleting a default when there are other templates. But if its the only one its okay. This is a weird experience, so we should make something that makes more sense. + BTW. its weird cause the damage of removing the default template is equally bad when there is one or more templates. + */ const templateIndex = this.templates.findIndex((x) => x.key === key); this.templates.splice(templateIndex, 1); this.templates = [...this._templates]; From 0cbc2052fd85431fc367ef0ff80d8a3946fa5181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 14:36:55 +0200 Subject: [PATCH 104/114] fix imports --- .../input-template-picker/input-template-picker.element.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts index ad5272d884..7a3f8545f9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts @@ -2,13 +2,13 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, state } from 'lit/decorators.js'; import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; +import { UmbTemplateCardElement } from '../template-card/template-card.element'; +import { UMB_TEMPLATE_PICKER_MODAL_TOKEN } from '../../modals/template-picker'; +import { UMB_TEMPLATE_MODAL_TOKEN } from '../../modals/template'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { TemplateResource, TemplateResponseModel } from '@umbraco-cms/backoffice/backend-api'; -import { UmbTemplateCardElement } from '../template-card/template-card.element'; -import { UMB_TEMPLATE_PICKER_MODAL_TOKEN } from '../../modals/template-picker'; -import { UMB_TEMPLATE_MODAL_TOKEN } from '../../modals/template'; @customElement('umb-input-template-picker') export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElement) { From d4499017fc274f77b6fd323e82ffbcf4af9fc13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 14:38:08 +0200 Subject: [PATCH 105/114] lint fixes --- .../provide/context-provider.controller.test.ts | 2 +- .../libs/context-api/token/context-token.test.ts | 2 +- .../workspace/document-type-workspace.element.ts | 4 ++-- ...workspace-view-document-type-permissions.element.ts | 2 +- .../workspace-view-document-type-templates.element.ts | 2 +- .../document-type-picker-modal.element.ts | 2 +- .../documents/documents/workspace/manifests.ts | 8 ++++---- .../views/info/document-info-workspace-view.element.ts | 2 +- .../media-grid-collection-view.element.ts | 2 +- .../media/media/repository/media.repository.ts | 10 +++++----- .../backoffice/media/media/repository/media.store.ts | 2 +- .../src/backoffice/media/media/workspace/manifests.ts | 2 +- .../media/workspace/media-workspace-edit.element.ts | 2 +- .../media/media/workspace/media-workspace.context.ts | 2 +- .../media/media/workspace/media-workspace.element.ts | 4 ++-- .../workspace/member-group-workspace-edit.element.ts | 4 ++-- .../views/health-check-overview.element.ts | 2 +- .../data-types/repository/data-type.repository.ts | 8 ++++---- .../backoffice-frame/backoffice-main.element.ts | 6 +++--- .../components/code-editor/code-editor.controller.ts | 2 +- .../shared/components/debug/debug.element.ts | 2 +- .../input-document-type-picker.element.ts | 8 ++++---- .../template-picker/template-picker-modal.element.ts | 2 +- .../shared/modals/template/template-modal.element.ts | 2 +- .../dictionary/repository/dictionary.repository.ts | 10 +++++----- .../dictionary/repository/dictionary.store.ts | 2 +- .../sources/dictionary.detail.server.data.ts | 4 ++-- .../workspace/dictionary-workspace.context.ts | 4 ++-- src/Umbraco.Web.UI.Client/src/core/mocks/browser.ts | 2 +- .../src/core/mocks/data/dictionary.data.ts | 2 +- .../src/core/mocks/data/media.data.ts | 2 +- .../src/core/mocks/domains/dictionary.handlers.ts | 2 +- .../src/core/mocks/domains/rte-embed.handlers.ts | 2 +- 33 files changed, 57 insertions(+), 57 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provider.controller.test.ts b/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provider.controller.test.ts index 481a916122..7946d8b30b 100644 --- a/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provider.controller.test.ts +++ b/src/Umbraco.Web.UI.Client/libs/context-api/provide/context-provider.controller.test.ts @@ -1,7 +1,7 @@ import { expect, fixture, defineCE } from '@open-wc/testing'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbContextConsumer } from '../consume/context-consumer'; import { UmbContextProviderController } from './context-provider.controller'; -import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; class MyClass { prop = 'value from provider'; diff --git a/src/Umbraco.Web.UI.Client/libs/context-api/token/context-token.test.ts b/src/Umbraco.Web.UI.Client/libs/context-api/token/context-token.test.ts index 4493b739d6..f8b0a2046d 100644 --- a/src/Umbraco.Web.UI.Client/libs/context-api/token/context-token.test.ts +++ b/src/Umbraco.Web.UI.Client/libs/context-api/token/context-token.test.ts @@ -1,7 +1,7 @@ import { expect } from '@open-wc/testing'; import { UmbContextConsumer } from '../consume/context-consumer'; -import { UmbContextToken } from './context-token'; import { UmbContextProvider } from '../provide/context-provider'; +import { UmbContextToken } from './context-token'; const testContextAlias = 'my-test-context'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/document-type-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/document-type-workspace.element.ts index b5b31f70a8..efdaab0cdd 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/document-type-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/document-type-workspace.element.ts @@ -1,10 +1,10 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; -import { IRoutingInfo } from '@umbraco-cms/internal/router'; -import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbWorkspaceDocumentTypeContext } from './document-type-workspace.context'; import { UmbDocumentTypeWorkspaceEditElement } from './document-type-workspace-edit.element'; +import { IRoutingInfo } from '@umbraco-cms/internal/router'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @customElement('umb-document-type-workspace') export class UmbDocumentTypeWorkspaceElement extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts index 8479c0bbd0..876c142cb7 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts @@ -1,9 +1,9 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, state } from 'lit/decorators.js'; +import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; -import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; import '../../../../../shared/property-creator/property-creator.element.ts'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts index cc89db1358..5e9086943d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts @@ -1,9 +1,9 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, state } from 'lit/decorators.js'; +import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; -import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; import '../../../../../shared/property-creator/property-creator.element.ts'; @customElement('umb-workspace-view-document-type-templates') diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.element.ts index ee3540f564..0e26fd7588 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/modals/document-type-picker/document-type-picker-modal.element.ts @@ -1,9 +1,9 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, state } from 'lit/decorators.js'; -import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; import type { UmbTreeElement } from '../../../../shared/components/tree/tree.element'; import { UmbDocumentTypePickerModalData, UmbDocumentTypePickerModalResult } from '.'; +import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; // TODO: make use of UmbPickerLayoutBase @customElement('umb-document-type-picker-modal') diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/manifests.ts index bc08b979de..d8ada1659b 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/manifests.ts @@ -1,13 +1,13 @@ +import { UmbDocumentSaveAndPublishWorkspaceAction } from './actions/save-and-publish.action'; +import { UmbDocumentSaveAndPreviewWorkspaceAction } from './actions/save-and-preview.action'; +import { UmbSaveAndScheduleDocumentWorkspaceAction } from './actions/save-and-schedule.action'; +import { UmbSaveWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; import type { ManifestWorkspace, ManifestWorkspaceAction, ManifestWorkspaceView, ManifestWorkspaceViewCollection, } from '@umbraco-cms/backoffice/extensions-registry'; -import { UmbSaveWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; -import { UmbDocumentSaveAndPublishWorkspaceAction } from './actions/save-and-publish.action'; -import { UmbDocumentSaveAndPreviewWorkspaceAction } from './actions/save-and-preview.action'; -import { UmbSaveAndScheduleDocumentWorkspaceAction } from './actions/save-and-schedule.action'; const workspace: ManifestWorkspace = { type: 'workspace', diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/views/info/document-info-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/views/info/document-info-workspace-view.element.ts index 439a076c13..fbf7e3544b 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/views/info/document-info-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/views/info/document-info-workspace-view.element.ts @@ -3,9 +3,9 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { repeat } from 'lit/directives/repeat.js'; import { customElement, state } from 'lit/decorators.js'; import { UUIPaginationEvent } from '@umbraco-ui/uui'; +import { UmbEntityWorkspaceContextInterface } from '../../../../../shared/components/workspace/workspace-context/workspace-entity-context.interface'; import type { DocumentResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { UmbEntityWorkspaceContextInterface } from '../../../../../shared/components/workspace/workspace-context/workspace-entity-context.interface'; interface HistoryNode { userId?: number; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/collection-view/media-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/collection-view/media-grid-collection-view.element.ts index 22ffd35e91..50fb77a885 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/collection-view/media-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/collection-view/media-grid-collection-view.element.ts @@ -2,10 +2,10 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; +import { UmbCollectionContext, UMB_COLLECTION_CONTEXT_TOKEN } from '../../../shared/collection/collection.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; // TODO: this should be a lib import -import { UmbCollectionContext, UMB_COLLECTION_CONTEXT_TOKEN } from '../../../shared/collection/collection.context'; @customElement('umb-media-grid-collection-view') export class UmbMediaGridCollectionViewElement extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.repository.ts index bab50b24b8..cacafa2709 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.repository.ts @@ -1,14 +1,14 @@ +import type { MediaDetails } from '../'; +import { MediaTreeServerDataSource } from './sources/media.tree.server.data'; +import { UmbMediaTreeStore, UMB_MEDIA_TREE_STORE_CONTEXT_TOKEN } from './media.tree.store'; +import { UmbMediaStore, UMB_MEDIA_STORE_CONTEXT_TOKEN } from './media.store'; +import { UmbMediaDetailServerDataSource } from './sources/media.detail.server.data'; import type { UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbDetailRepository } from '@umbraco-cms/backoffice/repository'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; -import type { MediaDetails } from '../'; -import { MediaTreeServerDataSource } from './sources/media.tree.server.data'; -import { UmbMediaTreeStore, UMB_MEDIA_TREE_STORE_CONTEXT_TOKEN } from './media.tree.store'; -import { UmbMediaStore, UMB_MEDIA_STORE_CONTEXT_TOKEN } from './media.store'; -import { UmbMediaDetailServerDataSource } from './sources/media.detail.server.data'; import type { UmbTreeRepository } from 'libs/repository/tree-repository.interface'; type ItemDetailType = MediaDetails; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.store.ts index a34e9e8da0..2d5dfc4c4c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.store.ts @@ -1,8 +1,8 @@ +import type { MediaDetails } from '../'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { ArrayState } from '@umbraco-cms/backoffice/observable-api'; import { UmbStoreBase } from '@umbraco-cms/backoffice/store'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; -import type { MediaDetails } from '../'; /** * @export diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/manifests.ts index c58ae9fbf1..7dbf6b198f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { MEDIA_REPOSITORY_ALIAS } from '../repository/manifests'; import { UmbSaveWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; import type { ManifestWorkspace, @@ -5,7 +6,6 @@ import type { ManifestWorkspaceView, ManifestWorkspaceViewCollection, } from '@umbraco-cms/backoffice/extensions-registry'; -import { MEDIA_REPOSITORY_ALIAS } from '../repository/manifests'; const workspace: ManifestWorkspace = { type: 'workspace', diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/media-workspace-edit.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/media-workspace-edit.element.ts index 264902479b..5d59761c98 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/media-workspace-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/media-workspace-edit.element.ts @@ -1,8 +1,8 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html, nothing } from 'lit'; import { customElement, state } from 'lit/decorators.js'; -import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbMediaWorkspaceContext } from './media-workspace.context'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @customElement('umb-media-workspace-edit') export class UmbMediaWorkspaceEditElement extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/media-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/media-workspace.context.ts index 7bffe8f9af..399b057a61 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/media-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/media-workspace.context.ts @@ -1,9 +1,9 @@ import { UmbWorkspaceContext } from '../../../shared/components/workspace/workspace-context/workspace-context'; import { UmbMediaRepository } from '../repository/media.repository'; import type { UmbEntityWorkspaceContextInterface } from '../../../shared/components/workspace/workspace-context/workspace-entity-context.interface'; +import type { MediaDetails } from '../'; import { appendToFrozenArray, ObjectState } from '@umbraco-cms/backoffice/observable-api'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; -import type { MediaDetails } from '../'; type EntityType = MediaDetails; export class UmbMediaWorkspaceContext diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/media-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/media-workspace.element.ts index a2595863bf..cc3e954a76 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/media-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/workspace/media-workspace.element.ts @@ -1,10 +1,10 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; -import { IRoute, IRoutingInfo } from '@umbraco-cms/internal/router'; -import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbMediaWorkspaceContext } from './media-workspace.context'; import { UmbMediaWorkspaceEditElement } from './media-workspace-edit.element'; +import { IRoute, IRoutingInfo } from '@umbraco-cms/internal/router'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @customElement('umb-media-workspace') export class UmbMediaWorkspaceElement extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/workspace/member-group-workspace-edit.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/workspace/member-group-workspace-edit.element.ts index b4d65802a2..29149724d4 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/workspace/member-group-workspace-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/members/member-groups/workspace/member-group-workspace-edit.element.ts @@ -1,10 +1,10 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; -import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import type { MemberGroupDetails } from '@umbraco-cms/backoffice/models'; import { UUIInputElement, UUIInputEvent } from '@umbraco-ui/uui'; import { UmbWorkspaceMemberGroupContext } from './member-group-workspace.context'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import type { MemberGroupDetails } from '@umbraco-cms/backoffice/models'; /** * @element umb-member-group-edit-workspace diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/dashboards/health-check/views/health-check-overview.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/dashboards/health-check/views/health-check-overview.element.ts index 71114fb667..dddf878b38 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/dashboards/health-check/views/health-check-overview.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/dashboards/health-check/views/health-check-overview.element.ts @@ -3,11 +3,11 @@ import { css, html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { UUIButtonState } from '@umbraco-ui/uui'; -import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbHealthCheckDashboardContext, UMB_HEALTHCHECK_DASHBOARD_CONTEXT_TOKEN, } from '../health-check-dashboard.context'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import './health-check-group-box-overview.element'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/data-type.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/data-type.repository.ts index bc5c68b8f9..3922a1a665 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/data-type.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/repository/data-type.repository.ts @@ -1,12 +1,12 @@ +import { UmbDataTypeTreeStore, UMB_DATA_TYPE_TREE_STORE_CONTEXT_TOKEN } from './data-type.tree.store'; +import { UmbDataTypeServerDataSource } from './sources/data-type.server.data'; +import { UmbDataTypeStore, UMB_DATA_TYPE_STORE_CONTEXT_TOKEN } from './data-type.store'; +import { DataTypeTreeServerDataSource } from './sources/data-type.tree.server.data'; import type { UmbTreeDataSource, UmbTreeRepository, UmbDetailRepository } from '@umbraco-cms/backoffice/repository'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { ProblemDetailsModel, DataTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; -import { UmbDataTypeTreeStore, UMB_DATA_TYPE_TREE_STORE_CONTEXT_TOKEN } from './data-type.tree.store'; -import { UmbDataTypeServerDataSource } from './sources/data-type.server.data'; -import { UmbDataTypeStore, UMB_DATA_TYPE_STORE_CONTEXT_TOKEN } from './data-type.store'; -import { DataTypeTreeServerDataSource } from './sources/data-type.tree.server.data'; type ItemType = DataTypeResponseModel; type TreeItemType = any; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/backoffice-frame/backoffice-main.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/backoffice-frame/backoffice-main.element.ts index e4b2dde68b..405d17304d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/backoffice-frame/backoffice-main.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/backoffice-frame/backoffice-main.element.ts @@ -2,13 +2,13 @@ import { defineElement } from '@umbraco-ui/uui-base/lib/registration'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html } from 'lit'; import { state } from 'lit/decorators.js'; +import { UmbSectionElement } from '../section/section.element'; +import { UmbSectionContext, UMB_SECTION_CONTEXT_TOKEN } from '../section/section.context'; +import { UmbBackofficeContext, UMB_BACKOFFICE_CONTEXT_TOKEN } from './backoffice.context'; import type { UmbRouterSlotChangeEvent } from '@umbraco-cms/internal/router'; import type { ManifestSection } from '@umbraco-cms/backoffice/extensions-registry'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { createExtensionElementOrFallback } from '@umbraco-cms/backoffice/extensions-api'; -import { UmbSectionElement } from '../section/section.element'; -import { UmbSectionContext, UMB_SECTION_CONTEXT_TOKEN } from '../section/section.context'; -import { UmbBackofficeContext, UMB_BACKOFFICE_CONTEXT_TOKEN } from './backoffice.context'; @defineElement('umb-backoffice-main') export class UmbBackofficeMain extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/code-editor/code-editor.controller.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/code-editor/code-editor.controller.ts index f79acaeace..525e4442ef 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/code-editor/code-editor.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/code-editor/code-editor.controller.ts @@ -1,4 +1,3 @@ -import { UmbChangeEvent, UmbInputEvent } from '@umbraco-cms/backoffice/events'; import * as monaco from 'monaco-editor'; import { CodeEditorConstructorOptions, @@ -12,6 +11,7 @@ import { UmbCodeEditorSelection, } from './code-editor.model'; import themes from './themes'; +import { UmbChangeEvent, UmbInputEvent } from '@umbraco-cms/backoffice/events'; //TODO - consider firing change event on blur diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/debug/debug.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/debug/debug.element.ts index 559f490972..128dbb33bb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/debug/debug.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/debug/debug.element.ts @@ -1,10 +1,10 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html, nothing, TemplateResult } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; +import { UMB_CONTEXT_DEBUGGER_MODAL_TOKEN } from './modals/debug'; import { UmbContextDebugRequest } from '@umbraco-cms/backoffice/context-api'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; -import { UMB_CONTEXT_DEBUGGER_MODAL_TOKEN } from './modals/debug'; @customElement('umb-debug') export class UmbDebug extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts index acf5977054..b30071bad0 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-type-picker/input-document-type-picker.element.ts @@ -3,16 +3,16 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit-html/directives/if-defined.js'; import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; -import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { DocumentTypeResponseModel, EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; -import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; -import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; import { UmbDocumentTypeTreeStore, UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN, } from '../../../documents/document-types/repository/document-type.tree.store'; import { UMB_CONFIRM_MODAL_TOKEN } from '../../modals/confirm'; import { UMB_DOCUMENT_TYPE_PICKER_MODAL_TOKEN } from '../../../documents/documents/modals/document-type-picker'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { DocumentTypeResponseModel, EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; +import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; @customElement('umb-input-document-type-picker') export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitElement) { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts index 1f85db2a4d..bffb7ff596 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts @@ -1,9 +1,9 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, state } from 'lit/decorators.js'; -import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; import { UmbTreeElement } from '../../components/tree/tree.element'; import { UmbTemplatePickerModalData, UmbTemplatePickerModalResult } from '.'; +import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; //TODO: make a default tree-picker that can be used across multiple pickers // TODO: make use of UmbPickerLayoutBase diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts index a3e156f832..6ba041187c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts @@ -1,11 +1,11 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, query, state } from 'lit/decorators.js'; -import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; import { ifDefined } from 'lit/directives/if-defined.js'; import { UUIInputEvent } from '@umbraco-ui/uui'; import { UmbCodeEditor } from '../../components/code-editor'; import { UmbTemplateModalData, UmbTemplateModalResult } from '.'; +import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; import { UmbInputEvent } from 'libs/umb-events/input.event'; import { TemplateResource, TemplateResponseModel } from 'libs/backend-api/src'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/dictionary.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/dictionary.repository.ts index a420b1ffc8..ac680847b3 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/dictionary.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/dictionary.repository.ts @@ -1,13 +1,13 @@ -import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; -import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; -import { UmbTreeDataSource, UmbDetailRepository, UmbTreeRepository } from '@umbraco-cms/backoffice/repository'; -import { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; -import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; import type { DictionaryDetails } from '../'; import { UmbDictionaryStore, UMB_DICTIONARY_STORE_CONTEXT_TOKEN } from './dictionary.store'; import { UmbDictionaryDetailServerDataSource } from './sources/dictionary.detail.server.data'; import { UmbDictionaryTreeStore, UMB_DICTIONARY_TREE_STORE_CONTEXT_TOKEN } from './dictionary.tree.store'; import { DictionaryTreeServerDataSource } from './sources/dictionary.tree.server.data'; +import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; +import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; +import { UmbTreeDataSource, UmbDetailRepository, UmbTreeRepository } from '@umbraco-cms/backoffice/repository'; +import { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api'; +import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; export class UmbDictionaryRepository implements UmbTreeRepository, UmbDetailRepository { #init!: Promise; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/dictionary.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/dictionary.store.ts index f549e112b4..210f98c8dc 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/dictionary.store.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/dictionary.store.ts @@ -1,8 +1,8 @@ +import type { DictionaryDetails } from '../'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { UmbStoreBase } from '@umbraco-cms/backoffice/store'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { ArrayState } from '@umbraco-cms/backoffice/observable-api'; -import type { DictionaryDetails } from '../'; /** * @export diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/sources/dictionary.detail.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/sources/dictionary.detail.server.data.ts index 1fb529a992..8a972cc326 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/sources/dictionary.detail.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/repository/sources/dictionary.detail.server.data.ts @@ -1,3 +1,5 @@ +import type { DictionaryDetails } from '../../'; +import { DictionaryDetailDataSource } from './dictionary.details.server.data.interface'; import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; import { @@ -6,8 +8,6 @@ import { LanguageResource, ProblemDetailsModel, } from '@umbraco-cms/backoffice/backend-api'; -import type { DictionaryDetails } from '../../'; -import { DictionaryDetailDataSource } from './dictionary.details.server.data.interface'; /** * @description - A data source for the Dictionary detail that fetches data from the server diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/workspace/dictionary-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/workspace/dictionary-workspace.context.ts index fceb0e11ba..0692a4ffe9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/workspace/dictionary-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/translation/dictionary/workspace/dictionary-workspace.context.ts @@ -1,9 +1,9 @@ -import { ObjectState } from '@umbraco-cms/backoffice/observable-api'; -import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; import { UmbDictionaryRepository } from '../repository/dictionary.repository'; import { UmbWorkspaceContext } from '../../../../backoffice/shared/components/workspace/workspace-context/workspace-context'; import { UmbEntityWorkspaceContextInterface } from '../../../../backoffice/shared/components/workspace/workspace-context/workspace-entity-context.interface'; import type { DictionaryDetails } from '../'; +import { UmbControllerHostInterface } from '@umbraco-cms/backoffice/controller'; +import { ObjectState } from '@umbraco-cms/backoffice/observable-api'; type EntityType = DictionaryDetails; diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/browser.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/browser.ts index 030c9bd69a..980b6cbecf 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/browser.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/browser.ts @@ -1,6 +1,6 @@ import { MockedRequest, setupWorker } from 'msw'; -import { umbracoPath } from '@umbraco-cms/backoffice/utils'; import { handlers } from './browser-handlers'; +import { umbracoPath } from '@umbraco-cms/backoffice/utils'; const worker = setupWorker(...handlers); diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/dictionary.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/dictionary.data.ts index c3b27857dd..8a76f7c398 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/dictionary.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/dictionary.data.ts @@ -1,7 +1,7 @@ -import type { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; import type { DictionaryDetails } from '../../../backoffice/translation/dictionary'; import { UmbEntityData } from './entity.data'; import { createEntityTreeItem } from './utils'; +import type { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; export const data: Array = [ { diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/media.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/media.data.ts index b7f70f41b9..82f1c4d25a 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/media.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/media.data.ts @@ -1,7 +1,7 @@ -import { ContentTreeItemResponseModel, PagedContentTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; import type { MediaDetails } from '../../../backoffice/media/media'; import { UmbEntityData } from './entity.data'; import { createContentTreeItem } from './utils'; +import { ContentTreeItemResponseModel, PagedContentTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; export const data: Array = [ { diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/dictionary.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/dictionary.handlers.ts index e4b837534d..25df97d47a 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/dictionary.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/dictionary.handlers.ts @@ -1,7 +1,7 @@ import { rest } from 'msw'; -import { ImportDictionaryRequestModel, DictionaryOverviewResponseModel } from '@umbraco-cms/backoffice/backend-api'; import type { DictionaryDetails } from '../../../backoffice/translation/dictionary'; import { umbDictionaryData } from '../data/dictionary.data'; +import { ImportDictionaryRequestModel, DictionaryOverviewResponseModel } from '@umbraco-cms/backoffice/backend-api'; const uploadResponse: ImportDictionaryRequestModel = { fileName: 'c:/path/to/tempfilename.udt', diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/rte-embed.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/rte-embed.handlers.ts index b99050a812..3a8b1247e1 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/rte-embed.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/rte-embed.handlers.ts @@ -1,6 +1,6 @@ import { rest } from "msw"; -import { umbracoPath } from "@umbraco-cms/backoffice/utils"; import { OEmbedResult, OEmbedStatus } from "../../../backoffice/shared/modals/embedded-media"; +import { umbracoPath } from "@umbraco-cms/backoffice/utils"; export const handlers = [ rest.get(umbracoPath('/rteembed'), (req, res, ctx) => { From 017e1d8154a29cff3ddefbe713bc351038996789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 15:18:08 +0200 Subject: [PATCH 106/114] refactor input template picker --- .../.vscode/settings.json | 2 +- .../input-template-picker.element.ts | 118 +++++++----------- 2 files changed, 48 insertions(+), 72 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/.vscode/settings.json b/src/Umbraco.Web.UI.Client/.vscode/settings.json index 196b1d2b83..badd3c2f00 100644 --- a/src/Umbraco.Web.UI.Client/.vscode/settings.json +++ b/src/Umbraco.Web.UI.Client/.vscode/settings.json @@ -1,6 +1,6 @@ { "cssVariables.lookupFiles": ["node_modules/@umbraco-ui/uui-css/dist/custom-properties.css"], - "cSpell.words": ["combobox", "variantable"], + "cSpell.words": ["combobox", "templating", "variantable"], "exportall.config.folderListener": [], "exportall.config.relExclusion": [] } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts index 7a3f8545f9..ca6480f1db 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-template-picker/input-template-picker.element.ts @@ -5,33 +5,13 @@ import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; import { UmbTemplateCardElement } from '../template-card/template-card.element'; import { UMB_TEMPLATE_PICKER_MODAL_TOKEN } from '../../modals/template-picker'; import { UMB_TEMPLATE_MODAL_TOKEN } from '../../modals/template'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { UmbTemplateRepository } from '../../../templating/templates/repository/template.repository'; import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { TemplateResource, TemplateResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { TemplateResponseModel } from '@umbraco-cms/backoffice/backend-api'; @customElement('umb-input-template-picker') export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElement) { - static styles = [ - UUITextStyles, - css` - #add-button { - width: 100%; - } - :host { - box-sizing: border-box; - display: flex; - gap: var(--uui-size-space-4); - flex-wrap: wrap; - } - - :host > * { - max-width: 180px; - min-width: 180px; - min-height: 150px; - } - `, - ]; /** * This is a minimum amount of selected items in this input. * @type {number} @@ -74,12 +54,8 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen return this._allowedKeys; } public set allowedKeys(newKeys: Array) { - //this.#observePickedTemplates(); this._allowedKeys = newKeys; - //this._templates = []; - //this._allowedKeys.forEach((key) => { - // this.#setup(key); - //}); + this.#observePickedTemplates(); } _defaultKey = ''; @@ -93,47 +69,38 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen } private _modalContext?: UmbModalContext; - //private _templateStore?: UmbTemplateTreeStore; - //private _pickedItemsObserver?: UmbObserverController; + private _templateRepository: UmbTemplateRepository = new UmbTemplateRepository(this); @state() - _templates: TemplateResponseModel[] = []; - - public get templates(): TemplateResponseModel[] { - return this._templates; - } - public set templates(newTemplates: TemplateResponseModel[]) { - this._templates = newTemplates; - this.allowedKeys = newTemplates.map((template) => template.key ?? ''); - } + _pickedTemplates: TemplateResponseModel[] = []; constructor() { super(); + this.consumeContext(UMB_MODAL_CONTEXT_TOKEN, (instance) => { this._modalContext = instance; }); } - connectedCallback(): void { - super.connectedCallback(); - this.allowedKeys.forEach((key) => this.#setup(key)); - } - - async #setup(templateKey: string) { - const { data } = await tryExecuteAndNotify(this, TemplateResource.getTemplateByKey({ key: templateKey })); - if (!data) return; - this.templates = [...this.templates, data]; + async #observePickedTemplates() { + this.observe( + await this._templateRepository.treeItems(this._allowedKeys), + (data) => { + this._pickedTemplates = data; + }, + '_templateRepositoryTreeItems' + ); } protected getFormElement() { - return undefined; + return this; } #changeDefault(e: CustomEvent) { e.stopPropagation(); const newKey = (e.target as UmbTemplateCardElement).value as string; this.defaultKey = newKey; - this.dispatchEvent(new CustomEvent('change-default', { bubbles: true, composed: true })); + this.dispatchEvent(new CustomEvent('change-default')); } #openPicker() { @@ -144,11 +111,8 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen modalHandler?.onSubmit().then((data) => { if (!data.selection) return; - //TODO: a better way to do this? - this.templates = []; this.allowedKeys = data.selection; - this.allowedKeys.forEach((key) => this.#setup(key)); - this.dispatchEvent(new CustomEvent('change-allowed', { bubbles: true, composed: true })); + this.dispatchEvent(new CustomEvent('change-allowed')); }); } @@ -162,14 +126,21 @@ export class UmbInputTemplatePickerElement extends FormControlMixin(UmbLitElemen In current backoffice we just prevent deleting a default when there are other templates. But if its the only one its okay. This is a weird experience, so we should make something that makes more sense. BTW. its weird cause the damage of removing the default template is equally bad when there is one or more templates. */ - const templateIndex = this.templates.findIndex((x) => x.key === key); - this.templates.splice(templateIndex, 1); - this.templates = [...this._templates]; + this.allowedKeys = this.allowedKeys.filter((x) => x !== key); + } + + #openTemplate(e: CustomEvent) { + const key = (e.target as UmbTemplateCardElement).value; + + this._modalContext?.open(UMB_TEMPLATE_MODAL_TOKEN, { + key: key as string, + language: 'razor', + }); } render() { return html` - ${this.templates.map( + ${this._pickedTemplates.map( (template) => html` { - // TODO: update template - // Hopefully our Template Repository will make sure this happens automatically, But lets follow up. - }); - */ - } + :host > * { + max-width: 180px; + min-width: 180px; + min-height: 150px; + } + `, + ]; } export default UmbInputTemplatePickerElement; From 8d10047b41f8ebb93db9ae0ef373e91a3d9a1847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 15:27:40 +0200 Subject: [PATCH 107/114] move style down --- .../modals/template/template-modal.element.ts | 86 +++++++++---------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts index 6ba041187c..a50dc39341 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts @@ -14,49 +14,6 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; // TODO: make use of UmbPickerLayoutBase @customElement('umb-template-modal') export class UmbTemplateModalElement extends UmbModalBaseElement { - static styles = [ - UUITextStyles, - css` - uui-box { - position: relative; - display: block; - height: 100%; - margin: var(--uui-size-layout-1); - } - - #layout-header { - display: flex; - width: 100%; - align-items: center; - margin: 0 var(--uui-size-layout-1); - } - - #template-name { - align-items: center; - padding: 0 var(--uui-size-space-3); - flex-grow: 1; - } - - umb-code-editor { - position: absolute; /** Umb-code-editor has issues with height, this is the temp solution on this case */ - top: 75px; - left: 0; - bottom: 0; - width: 100%; - } - - #button-group { - display: flex; - justify-content: space-between; - } - - #secondary-group { - display: flex; - gap: var(--uui-size-space-4); - } - `, - ]; - @state() _key = ''; @@ -149,6 +106,49 @@ export class UmbTemplateModalElement extends UmbModalBaseElement `; } + + static styles = [ + UUITextStyles, + css` + uui-box { + position: relative; + display: block; + height: 100%; + margin: var(--uui-size-layout-1); + } + + #layout-header { + display: flex; + width: 100%; + align-items: center; + margin: 0 var(--uui-size-layout-1); + } + + #template-name { + align-items: center; + padding: 0 var(--uui-size-space-3); + flex-grow: 1; + } + + umb-code-editor { + position: absolute; /** Umb-code-editor has issues with height, this is the temp solution on this case */ + top: 75px; + left: 0; + bottom: 0; + width: 100%; + } + + #button-group { + display: flex; + justify-content: space-between; + } + + #secondary-group { + display: flex; + gap: var(--uui-size-space-4); + } + `, + ]; } export default UmbTemplateModalElement; From cc6a0d4c8cfe5552c05d64e7c3d24fbb4e98156a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 15:30:14 +0200 Subject: [PATCH 108/114] todos --- .../backoffice/shared/modals/template/template-modal.element.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts index a50dc39341..57086d24eb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template/template-modal.element.ts @@ -28,6 +28,8 @@ export class UmbTemplateModalElement extends UmbModalBaseElement Date: Tue, 28 Mar 2023 15:31:06 +0200 Subject: [PATCH 109/114] TODO --- .../template-picker-modal.element.ts | 95 ++++++++++--------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts index bffb7ff596..49a14aa0d0 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/modals/template-picker/template-picker-modal.element.ts @@ -12,6 +12,54 @@ export class UmbTemplatePickerModalElement extends UmbModalBaseElement< UmbTemplatePickerModalData, UmbTemplatePickerModalResult > { + @state() + _selection: Array = []; + + @state() + _multiple = true; + + connectedCallback() { + super.connectedCallback(); + this._selection = this.data?.selection ?? []; + this._multiple = this.data?.multiple ?? true; + } + + private _handleSelectionChange(e: CustomEvent) { + e.stopPropagation(); + const element = e.target as UmbTreeElement; + this._selection = this._multiple ? element.selection : [element.selection[element.selection.length - 1]]; + } + + private _submit() { + this.modalHandler?.submit({ selection: this._selection }); + } + + private _close() { + this.modalHandler?.reject(); + } + + // TODO: implement search + // TODO: make umb-tree have a disabled option (string array like selection)? + render() { + return html` + + + +
+ +
+
+ + +
+
+ `; + } + static styles = [ UUITextStyles, css` @@ -46,53 +94,6 @@ export class UmbTemplatePickerModalElement extends UmbModalBaseElement< } `, ]; - - @state() - _selection: Array = []; - - @state() - _multiple = true; - - connectedCallback() { - super.connectedCallback(); - this._selection = this.data?.selection ?? []; - this._multiple = this.data?.multiple ?? true; - } - - private _handleSelectionChange(e: CustomEvent) { - e.stopPropagation(); - const element = e.target as UmbTreeElement; - this._selection = this._multiple ? element.selection : [element.selection[element.selection.length - 1]]; - } - - private _submit() { - this.modalHandler?.submit({ selection: this._selection }); - } - - private _close() { - this.modalHandler?.reject(); - } - - // TODO: make umb-tree have a disabled option (string array like selection)? - render() { - return html` - - - -
- -
-
- - -
-
- `; - } } export default UmbTemplatePickerModalElement; From b493345fe93afe1ee0d83522d7adc311924c0fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 15:34:27 +0200 Subject: [PATCH 110/114] remove comments --- .../views/design/workspace-view-document-type-design.element.ts | 1 - .../listview/workspace-view-document-type-listview.element.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts index f66d0a878b..0d8f2b1e15 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/design/workspace-view-document-type-design.element.ts @@ -104,7 +104,6 @@ export class UmbWorkspaceViewDocumentTypeDesignElement extends UmbLitElement { } render() { - //this._documentType?.name return html`
${this.renderTabBar()} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts index d5449abd95..3a1d45593c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts @@ -34,7 +34,6 @@ export class UmbWorkspaceViewDocumentTypeListviewElement extends UmbLitElement { } render() { - //this._documentType?.name return html` Listview `; } } From 1c240e4e47cba1fbdb2c69aa89f3755120219c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 15:36:06 +0200 Subject: [PATCH 111/114] clean up imports --- .../listview/workspace-view-document-type-listview.element.ts | 1 - .../workspace-view-document-type-permissions.element.ts | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts index 3a1d45593c..d2a445c6ba 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts @@ -2,7 +2,6 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, state } from 'lit/decorators.js'; import type { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; -import '../../../../../shared/property-creator/property-creator.element.ts'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts index 876c142cb7..27284e7c24 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/permissions/workspace-view-document-type-permissions.element.ts @@ -5,8 +5,6 @@ import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.c import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; -import '../../../../../shared/property-creator/property-creator.element.ts'; - @customElement('umb-workspace-view-document-type-permissions') export class UmbWorkspaceViewDocumentTypePermissionsElement extends UmbLitElement { static styles = [ From 1145c332e4ba419c804a6b372f07c194bc6c8541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 28 Mar 2023 15:36:21 +0200 Subject: [PATCH 112/114] re order imports --- .../listview/workspace-view-document-type-listview.element.ts | 2 +- .../templates/workspace-view-document-type-templates.element.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts index d2a445c6ba..b6c89a8d1d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/listview/workspace-view-document-type-listview.element.ts @@ -1,9 +1,9 @@ import { css, html } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, state } from 'lit/decorators.js'; +import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; import type { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; @customElement('umb-workspace-view-document-type-listview') export class UmbWorkspaceViewDocumentTypeListviewElement extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts index 5e9086943d..5b53aef5e6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/document-types/workspace/views/templates/workspace-view-document-type-templates.element.ts @@ -4,7 +4,6 @@ import { customElement, state } from 'lit/decorators.js'; import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; -import '../../../../../shared/property-creator/property-creator.element.ts'; @customElement('umb-workspace-view-document-type-templates') export class UmbWorkspaceViewDocumentTypeTemplatesElement extends UmbLitElement { From e384a2687a0b4588021a51ed7e125d13e3f477ce Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 29 Mar 2023 10:46:13 +0200 Subject: [PATCH 113/114] fix observe actions when the tree item is set --- .../tree/tree-item-base/tree-item-base.context.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts index 25c3a500cb..7216fb0683 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts @@ -15,6 +15,7 @@ import { } from '@umbraco-cms/backoffice/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api'; import type { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; +import { ManifestEntityAction } from 'libs/extensions-registry/entity-action.models'; // add type for unique function export type UmbTreeItemUniqueFunction = (x: T) => string | null | undefined; @@ -54,11 +55,11 @@ export class UmbTreeItemContextBase; + #actionObserver?: UmbObserverController; constructor(host: UmbControllerHostInterface, getUniqueFunction: UmbTreeItemUniqueFunction) { this.host = host; this.#getUniqueFunction = getUniqueFunction; - this.#observeTreeItemActions(); this.#consumeContexts(); new UmbContextProviderController(host, UMB_TREE_ITEM_CONTEXT_TOKEN, this); } @@ -77,6 +78,7 @@ export class UmbTreeItemContextBase Date: Wed, 29 Mar 2023 11:25:01 +0200 Subject: [PATCH 114/114] context controllers doesn't return a promise. add temp initialisation --- .../media/repository/media.repository.ts | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.repository.ts index cacafa2709..ab2d992be6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/media/media/repository/media.repository.ts @@ -14,8 +14,6 @@ import type { UmbTreeRepository } from 'libs/repository/tree-repository.interfac type ItemDetailType = MediaDetails; export class UmbMediaRepository implements UmbTreeRepository, UmbDetailRepository { - #init!: Promise; - #host: UmbControllerHostInterface; #treeSource: UmbTreeDataSource; @@ -26,6 +24,9 @@ export class UmbMediaRepository implements UmbTreeRepository, UmbDetailRepositor #notificationContext?: UmbNotificationContext; + #initResolver?: () => void; + #initialized = false; + constructor(host: UmbControllerHostInterface) { this.#host = host; @@ -33,19 +34,32 @@ export class UmbMediaRepository implements UmbTreeRepository, UmbDetailRepositor this.#treeSource = new MediaTreeServerDataSource(this.#host); this.#detailDataSource = new UmbMediaDetailServerDataSource(this.#host); - this.#init = Promise.all([ - new UmbContextConsumerController(this.#host, UMB_MEDIA_TREE_STORE_CONTEXT_TOKEN, (instance) => { - this.#treeStore = instance; - }), + new UmbContextConsumerController(this.#host, UMB_MEDIA_TREE_STORE_CONTEXT_TOKEN, (instance) => { + this.#treeStore = instance; + this.#checkIfInitialized(); + }); - new UmbContextConsumerController(this.#host, UMB_MEDIA_STORE_CONTEXT_TOKEN, (instance) => { - this.#store = instance; - }), + new UmbContextConsumerController(this.#host, UMB_MEDIA_STORE_CONTEXT_TOKEN, (instance) => { + this.#store = instance; + this.#checkIfInitialized(); + }); - new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => { - this.#notificationContext = instance; - }), - ]); + new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => { + this.#notificationContext = instance; + this.#checkIfInitialized(); + }); + } + + // TODO: make a generic way to wait for initialization + #init = new Promise((resolve) => { + this.#initialized ? resolve() : (this.#initResolver = resolve); + }); + + #checkIfInitialized() { + if (this.#treeStore && this.#store && this.#notificationContext) { + this.#initialized = true; + this.#initResolver?.(); + } } async requestRootTreeItems() {