From 31dcbb9e6ea9e9646d4ec9026455aaa1aa489484 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 10:21:48 +0100 Subject: [PATCH 001/223] add media temp data --- .../src/core/mocks/data/media.data.ts | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/data/media.data.ts 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 new file mode 100644 index 0000000000..40e3ae0dbb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/media.data.ts @@ -0,0 +1,77 @@ +import { UmbData } from './data'; +import { ContentTreeItem, PagedContentTreeItem } from '@umbraco-cms/backend-api'; +import type { MediaDetails } from '@umbraco-cms/models'; + +export const data: Array = [ + { + key: 'f2f81a40-c989-4b6b-84e2-057cecd3adc1', + name: 'Media 1', + type: 'media', + icon: 'picture', + parentKey: 'c0858d71-52be-4bb2-822f-42fa0c9a1ea5', + hasChildren: false, + properties: [ + { + alias: 'myMediaHeadline', + label: 'Media Headline', + description: 'Text string property', + dataTypeKey: 'dt-1', + }, + ], + data: [ + { + alias: 'myMediaHeadline', + value: 'The daily life at Umbraco HQ', + }, + ], + variants: [], + }, + { + key: '69431027-8867-45bf-a93b-72bbdabfb177', + type: 'media', + name: 'Media 2', + icon: 'picture', + parentKey: 'c0858d71-52be-4bb2-822f-42fa0c9a1ea5', + hasChildren: false, + properties: [ + { + alias: 'myMediaDescription', + label: 'Description', + description: 'Textarea property', + dataTypeKey: 'dt-2', + }, + ], + data: [ + { + alias: 'myMediaDescription', + value: 'Every day, a rabbit in a military costume greets me at the front door', + }, + ], + variants: [], + }, +]; + +// Temp mocked database +class UmbDataTypeData extends UmbData { + constructor() { + super(data); + } + + getTreeRoot(): PagedContentTreeItem { + const items = this.data.filter((item) => item.parentKey === null); + const total = items.length; + return { items, total }; + } + + getTreeItemChildren(key: string): PagedContentTreeItem { + const items = this.data.filter((item) => item.key === null); + const total = items.length; + return { items, total }; + } + + getTreeItem(keys: Array): Array { + return this.data.filter((item) => keys.includes(item.key ?? '')); + } +} + +export const umbDataTypeData = new UmbDataTypeData(); From f37c866718def360cb305ebfad65e50c310a4038 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 10:22:23 +0100 Subject: [PATCH 002/223] add member type temp data --- .../src/core/mocks/data/member-type.data.ts | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/data/member-type.data.ts diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/member-type.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/member-type.data.ts new file mode 100644 index 0000000000..1c010558d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/member-type.data.ts @@ -0,0 +1,38 @@ +import { UmbData } from './data'; +import { EntityTreeItem } from '@umbraco-cms/backend-api'; +import type { MemberTypeDetails } from '@umbraco-cms/models'; + +export const data: Array = [ + { + key: 'd59be02f-1df9-4228-aa1e-01917d806cda', + isContainer: false, + parentKey: null, + name: 'Member', + type: 'member-type', + icon: 'icon-user', + hasChildren: false, + alias: 'memberType1', + properties: [], + }, +]; + +// Temp mocked database +class UmbMemberTypeData extends UmbData { + constructor() { + super(data); + } + + getTreeRoot(): Array { + return this.data.filter((item) => item.parentKey === null); + } + + getTreeItemChildren(key: string): Array { + return this.data.filter((item) => item.parentKey === key); + } + + getTreeItem(keys: Array): Array { + return this.data.filter((item) => keys.includes(item.key ?? '')); + } +} + +export const umbMemberTypeData = new UmbMemberTypeData(); From b3a583bb122aae5cefe58b2a972a28cbd56eca3c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 10:22:58 +0100 Subject: [PATCH 003/223] add document temp data --- .../src/core/mocks/data/document.data.ts | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/data/document.data.ts 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 new file mode 100644 index 0000000000..36950c82cb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/document.data.ts @@ -0,0 +1,77 @@ +import { UmbData } from './data'; +import { DocumentTreeItem, PagedDocumentTreeItem } from '@umbraco-cms/backend-api'; +import type { DocumentDetails } from '@umbraco-cms/models'; + +export const data: Array = [ + { + key: 'f2f81a40-c989-4b6b-84e2-057cecd3adc1', + name: 'Media 1', + type: 'media', + icon: 'picture', + parentKey: 'c0858d71-52be-4bb2-822f-42fa0c9a1ea5', + hasChildren: false, + properties: [ + { + alias: 'myMediaHeadline', + label: 'Media Headline', + description: 'Text string property', + dataTypeKey: 'dt-1', + }, + ], + data: [ + { + alias: 'myMediaHeadline', + value: 'The daily life at Umbraco HQ', + }, + ], + variants: [], + }, + { + key: '69431027-8867-45bf-a93b-72bbdabfb177', + type: 'media', + name: 'Media 2', + icon: 'picture', + parentKey: 'c0858d71-52be-4bb2-822f-42fa0c9a1ea5', + hasChildren: false, + properties: [ + { + alias: 'myMediaDescription', + label: 'Description', + description: 'Textarea property', + dataTypeKey: 'dt-2', + }, + ], + data: [ + { + alias: 'myMediaDescription', + value: 'Every day, a rabbit in a military costume greets me at the front door', + }, + ], + variants: [], + }, +]; + +// Temp mocked database +class UmbDocumentData extends UmbData { + constructor() { + super(data); + } + + getTreeRoot(): PagedDocumentTreeItem { + const items = this.data.filter((item) => item.parentKey === null); + const total = items.length; + return { items, total }; + } + + getTreeItemChildren(key: string): PagedDocumentTreeItem { + const items = this.data.filter((item) => item.parentKey === key); + const total = items.length; + return { items, total }; + } + + getTreeItem(keys: Array): Array { + return this.data.filter((item) => keys.includes(item.key ?? '')); + } +} + +export const umbDocumentData = new UmbDocumentData(); From 86cfe2416e31b3afa48d52c6375413b67a5f6957 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 10:23:53 +0100 Subject: [PATCH 004/223] add data type tree handlers --- .../mocks/domains/data-type-tree.handlers.ts | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type-tree.handlers.ts diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type-tree.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type-tree.handlers.ts new file mode 100644 index 0000000000..f803acdf02 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type-tree.handlers.ts @@ -0,0 +1,37 @@ +import { rest } from 'msw'; +import { umbDataTypeData } from '../data/data-type.data'; + +// TODO: add schema +export const handlers = [ + rest.get('/umbraco/management/api/v1/data-type/tree/root', (req, res, ctx) => { + const rootItems = umbDataTypeData.getTreeRoot(); + const response = { + total: rootItems.length, + items: rootItems, + }; + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/data-type/tree/children', (req, res, ctx) => { + const key = req.params.key as string; + if (!key) return; + + const children = umbDataTypeData.getTreeItemChildren(key); + + const response = { + total: children.length, + items: children, + }; + + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/data-type/tree/item', (req, res, ctx) => { + const keys = req.params.keys as string; + if (!keys) return; + + const items = umbDataTypeData.getTreeItem(keys); + + return res(ctx.status(200), ctx.json(items)); + }), +]; From ace451d880f5d3c0e9fc16673a61f1029ce79c8d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 10:24:13 +0100 Subject: [PATCH 005/223] add document tree handlers --- .../mocks/domains/document-tree.handlers.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-tree.handlers.ts diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-tree.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-tree.handlers.ts new file mode 100644 index 0000000000..6843aae79f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-tree.handlers.ts @@ -0,0 +1,26 @@ +import { rest } from 'msw'; +import { umbDocumentData } from '../data/document.data'; + +// TODO: add schema +export const handlers = [ + rest.get('/umbraco/management/api/v1/tree/document/root', (req, res, ctx) => { + const response = umbDocumentData.getTreeRoot(); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/tree/document/children', (req, res, ctx) => { + const key = req.params.key as string; + if (!key) return; + const response = umbDocumentData.getTreeItemChildren(key); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/tree/document/item', (req, res, ctx) => { + const keys = req.params.keys as string; + if (!keys) return; + + const items = umbDocumentData.getTreeItem(keys); + + return res(ctx.status(200), ctx.json(items)); + }), +]; From a51fd6f74020055a1f3e290e738f391cdd3cd7f6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 10:24:38 +0100 Subject: [PATCH 006/223] add document type tree handlers --- .../domains/document-type-tree.handlers.ts | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type-tree.handlers.ts diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type-tree.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type-tree.handlers.ts new file mode 100644 index 0000000000..155bfac2c6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type-tree.handlers.ts @@ -0,0 +1,37 @@ +import { rest } from 'msw'; +import { umbDocumentTypeData } from '../data/document-type.data'; + +// TODO: add schema +export const handlers = [ + rest.get('/umbraco/management/api/v1/tree/document-type/root', (req, res, ctx) => { + const rootItems = umbDocumentTypeData.getTreeRoot(); + const response = { + total: rootItems.length, + items: rootItems, + }; + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/tree/document-type/children', (req, res, ctx) => { + const key = req.params.key as string; + if (!key) return; + + const children = umbDocumentTypeData.getTreeItemChildren(key); + + const response = { + total: children.length, + items: children, + }; + + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/tree/document-type/item', (req, res, ctx) => { + const keys = req.params.keys as string; + if (!keys) return; + + const items = umbDocumentTypeData.getTreeItem(keys); + + return res(ctx.status(200), ctx.json(items)); + }), +]; From 61dc14146ada789b1f5732f2b05644e62780fd37 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 10:25:29 +0100 Subject: [PATCH 007/223] add label and icon to tree manifest --- .../src/backoffice/trees/manifests.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts index 9fbbb25f78..9d13a0fad3 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts @@ -8,6 +8,8 @@ export const manifests: Array> = [ loader: () => import('./extensions/tree-extensions.element'), weight: 400, meta: { + label: 'Extensions', + icon: 'umb:favorite', sections: ['Umb.Section.Settings'], }, }, @@ -18,6 +20,8 @@ export const manifests: Array> = [ loader: () => import('./data-types/tree-data-types.element'), weight: 300, meta: { + label: 'Data Types', + icon: 'umb:folder', sections: ['Umb.Section.Settings'], }, }, @@ -28,6 +32,8 @@ export const manifests: Array> = [ loader: () => import('./document-types/tree-document-types.element'), weight: 200, meta: { + label: 'Document Types', + icon: 'umb:folder', sections: ['Umb.Section.Settings'], }, }, @@ -38,6 +44,8 @@ export const manifests: Array> = [ loader: () => import('./members/tree-members.element'), weight: 0, meta: { + label: 'Members', + icon: 'umb:folder', sections: ['Umb.Section.Members'], }, }, @@ -48,6 +56,8 @@ export const manifests: Array> = [ loader: () => import('./member-groups/tree-member-groups.element'), weight: 1, meta: { + label: 'Member Groups', + icon: 'umb:folder', sections: ['Umb.Section.Members'], }, }, @@ -58,6 +68,8 @@ export const manifests: Array> = [ loader: () => import('./media/tree-media.element'), weight: 100, meta: { + label: 'Media', + icon: 'umb:folder', sections: ['Umb.Section.Media'], }, }, @@ -68,6 +80,8 @@ export const manifests: Array> = [ loader: () => import('./documents/tree-documents.element'), weight: 100, meta: { + label: 'Documents', + icon: 'umb:folder', sections: ['Umb.Section.Content'], }, }, From 4e089a62ba138ad5dcc268973463a0a86251ec9b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 10:27:08 +0100 Subject: [PATCH 008/223] update entity type to match backend --- .../src/backoffice/editors/manifests.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/manifests.ts index 976fc97c47..46b9711134 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/manifests.ts @@ -16,7 +16,7 @@ export const manifests: Array> = [ name: 'Member Group Editor', loader: () => import('./member-group/editor-member-group.element'), meta: { - entityType: 'memberGroup', + entityType: 'member-group', }, }, { @@ -25,7 +25,7 @@ export const manifests: Array> = [ name: 'Data Type Editor', loader: () => import('./data-type/editor-data-type.element'), meta: { - entityType: 'dataType', + entityType: 'data-type', }, }, { @@ -34,7 +34,7 @@ export const manifests: Array> = [ name: 'Document Type Editor', loader: () => import('./document-type/editor-document-type.element'), meta: { - entityType: 'documentType', + entityType: 'document-type', }, }, { @@ -43,7 +43,7 @@ export const manifests: Array> = [ name: 'Extensions Editor', loader: () => import('./extensions/editor-extensions.element'), meta: { - entityType: 'extensionsList', + entityType: 'extensions-list', }, }, { @@ -79,7 +79,7 @@ export const manifests: Array> = [ name: 'User Group Editor', loader: () => import('./user-group/editor-user-group.element'), meta: { - entityType: 'userGroup', + entityType: 'user-group', }, }, { @@ -97,7 +97,7 @@ export const manifests: Array> = [ name: 'Package Builder Editor', loader: () => import('./package-builder/editor-package-builder.element'), meta: { - entityType: 'packageBuilder', + entityType: 'package-builder', }, }, ]; From 4075a6e38d6cd441f90683a53a288fc149032344 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 10:29:22 +0100 Subject: [PATCH 009/223] add label and icon to tree extension model --- .../src/core/extensions-registry/tree.models.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/tree.models.ts b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/tree.models.ts index f8bbd44541..ccb1543be6 100644 --- a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/tree.models.ts +++ b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/tree.models.ts @@ -6,5 +6,7 @@ export interface ManifestTree extends ManifestElement { } export interface MetaTree { + label: string; + icon: string; sections: Array; } From 5f428a7a14a578db69f49396dee4335f1555a19f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 10:32:42 +0100 Subject: [PATCH 010/223] add models --- .../src/core/models/index.ts | 84 ++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/models/index.ts b/src/Umbraco.Web.UI.Client/src/core/models/index.ts index cf15523979..73a22711f2 100644 --- a/src/Umbraco.Web.UI.Client/src/core/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/core/models/index.ts @@ -1,6 +1,11 @@ -import { Entity } from '../mocks/data/entities'; - import type { UserStatus } from '../../backoffice/sections/users/user-extensions'; +import { + ContentTreeItem, + DocumentTreeItem, + DocumentTypeTreeItem, + EntityTreeItem, + FolderTreeItem, +} from '@umbraco-cms/backend-api'; // Extension Manifests export * from '../extensions-registry/models'; @@ -9,6 +14,16 @@ export * from '../extensions-registry/models'; export type HTMLElementConstructor = new (...args: any[]) => T; // Users +export interface Entity { + key: string; + name: string; + icon: string; + type: string; + hasChildren: boolean; + parentKey: string; + isTrashed: boolean; +} + export interface UserEntity extends Entity { type: 'user'; } @@ -38,3 +53,68 @@ export interface UserGroupDetails extends UserGroupEntity { contentStartNode?: string; mediaStartNode?: string; } + +// Data Types +export interface DataTypeDetails extends FolderTreeItem { + key: string; // TODO: Remove this when the backend is fixed + propertyEditorModelAlias: string | null; + propertyEditorUIAlias: string | null; + data: Array; +} + +export interface DataTypePropertyData { + alias: string; + value: any; +} + +// Document Types +export interface DocumentTypeDetails extends DocumentTypeTreeItem { + key: string; // TODO: Remove this when the backend is fixed + alias: string; + properties: []; +} + +export interface MemberTypeDetails extends EntityTreeItem { + key: string; // TODO: Remove this when the backend is fixed + alias: string; + properties: []; +} + +// Content +export interface ContentProperty { + alias: string; + label: string; + description: string; + dataTypeKey: string; +} + +export interface ContentPropertyData { + alias: string; + value: any; +} + +// Documents +export interface DocumentDetails extends DocumentTreeItem { + key: string; // TODO: Remove this when the backend is fixed + properties: Array; + data: Array; + variants: Array; // TODO: define variant data + //layout?: any; // TODO: define layout type - make it non-optional +} + +// Media +export interface MediaDetails extends ContentTreeItem { + key: string; // TODO: Remove this when the backend is fixed + properties: Array; + data: Array; + variants: Array; // TODO: define variant data + //layout?: any; // TODO: define layout type - make it non-optional +} + +// Media Types + +export interface MediaTypeDetails extends EntityTreeItem { + key: string; // TODO: Remove this when the backend is fixed + alias: string; + properties: []; +} From f69d9894c9c731e3a03744240953a4a6c1aa0b6c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 10:40:30 +0100 Subject: [PATCH 011/223] add member type tree handlers --- .../domains/member-type-tree.handlers.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/domains/member-type-tree.handlers.ts diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/member-type-tree.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/member-type-tree.handlers.ts new file mode 100644 index 0000000000..02ddb621d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/member-type-tree.handlers.ts @@ -0,0 +1,19 @@ +import { rest } from 'msw'; +import { umbMemberTypeData } from '../data/member-type.data'; + +// TODO: add schema +export const handlers = [ + rest.get('/umbraco/management/api/v1/tree/member-type/root', (req, res, ctx) => { + const response = umbMemberTypeData.getTreeRoot(); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/tree/member-type/item', (req, res, ctx) => { + const keys = req.params.keys as string; + if (!keys) return; + + const items = umbMemberTypeData.getTreeItem(keys); + + return res(ctx.status(200), ctx.json(items)); + }), +]; From cd2f0030cf21db511fb66ff40dc911f701df15a9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 13:45:41 +0100 Subject: [PATCH 012/223] add tree methods to data type data --- .../src/core/mocks/data/data-type.data.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts index d131329499..bd844f9760 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts @@ -98,6 +98,18 @@ class UmbDataTypeData extends UmbEntityData { constructor() { super(data); } + + getTreeRoot(): Array { + return this.data.filter((item) => item.parentKey === null); + } + + getTreeItemChildren(key: string): Array { + return this.data.filter((item) => item.parentKey === key); + } + + getTreeItem(keys: Array): Array { + return this.data.filter((item) => keys.includes(item.key ?? '')); + } } export const umbDataTypeData = new UmbDataTypeData(); From 92f55fedc15abec9c4705fc2a7902cbb7ab3aa24 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 13:56:48 +0100 Subject: [PATCH 013/223] split keys --- .../src/core/mocks/domains/data-type-tree.handlers.ts | 2 +- .../src/core/mocks/domains/document-tree.handlers.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type-tree.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type-tree.handlers.ts index f803acdf02..f8af07e9fb 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type-tree.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type-tree.handlers.ts @@ -30,7 +30,7 @@ export const handlers = [ const keys = req.params.keys as string; if (!keys) return; - const items = umbDataTypeData.getTreeItem(keys); + const items = umbDataTypeData.getTreeItem(keys.split(',')); return res(ctx.status(200), ctx.json(items)); }), diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-tree.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-tree.handlers.ts index 6843aae79f..e17871717c 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-tree.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-tree.handlers.ts @@ -19,7 +19,7 @@ export const handlers = [ const keys = req.params.keys as string; if (!keys) return; - const items = umbDocumentData.getTreeItem(keys); + const items = umbDocumentData.getTreeItem(keys.split(',')); return res(ctx.status(200), ctx.json(items)); }), From 184bc3fdf6c35e4a872265ed1305da897094adef Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 13:57:14 +0100 Subject: [PATCH 014/223] import type --- src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts index bd844f9760..7151864c06 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts @@ -1,5 +1,6 @@ import { Entity } from './entities'; import { UmbEntityData } from './entity.data'; +import { FolderTreeItem } from '@umbraco-cms/backend-api'; export interface DataTypeEntity extends Entity { type: 'dataType'; From 91c925325b27c8805ebd6e7d00c1804963300a88 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 13:59:36 +0100 Subject: [PATCH 015/223] add tree methods --- .../src/core/mocks/data/document-type.data.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 b73f80cf54..b0408342e8 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 @@ -1,5 +1,6 @@ import { Entity } from './entities'; import { UmbEntityData } from './entity.data'; +import { DocumentTypeTreeItem } from '@umbraco-cms/backend-api'; export interface DocumentTypeEntity extends Entity { key: string; @@ -42,6 +43,18 @@ class UmbDocumentTypeData extends UmbEntityData { constructor() { super(data); } + + getTreeRoot(): Array { + return this.data.filter((item) => item.parentKey === null); + } + + getTreeItemChildren(key: string): Array { + return this.data.filter((item) => item.parentKey === key); + } + + getTreeItem(keys: Array): Array { + return this.data.filter((item) => keys.includes(item.key ?? '')); + } } export const umbDocumentTypeData = new UmbDocumentTypeData(); From 428b7d4679c0a1cf4e761a3804d9210cfbf977a1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 13:59:58 +0100 Subject: [PATCH 016/223] split keys --- .../src/core/mocks/domains/member-type-tree.handlers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/member-type-tree.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/member-type-tree.handlers.ts index 02ddb621d1..21acb5d242 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/member-type-tree.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/member-type-tree.handlers.ts @@ -12,7 +12,7 @@ export const handlers = [ const keys = req.params.keys as string; if (!keys) return; - const items = umbMemberTypeData.getTreeItem(keys); + const items = umbMemberTypeData.getTreeItem(keys.split(',')); return res(ctx.status(200), ctx.json(items)); }), From d3bb20f91155bfc5c1efe62f8d7406d8ab265c8a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 14:00:55 +0100 Subject: [PATCH 017/223] split keys --- .../src/core/mocks/domains/document-type-tree.handlers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type-tree.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type-tree.handlers.ts index 155bfac2c6..0524138e3f 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type-tree.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type-tree.handlers.ts @@ -30,7 +30,7 @@ export const handlers = [ const keys = req.params.keys as string; if (!keys) return; - const items = umbDocumentTypeData.getTreeItem(keys); + const items = umbDocumentTypeData.getTreeItem(keys.split(',')); return res(ctx.status(200), ctx.json(items)); }), From 4c4eedf5be19186e9eaca9cc825bfd413998f397 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 14:17:13 +0100 Subject: [PATCH 018/223] remove dataType entity --- .../editors/data-type/editor-data-type.element.ts | 2 +- .../src/core/mocks/data/data-type.data.ts | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/editor-data-type.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/editor-data-type.element.ts index 89d2e53c79..9133eaafc3 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/editor-data-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/editor-data-type.element.ts @@ -116,7 +116,7 @@ export class UmbEditorDataTypeElement extends UmbContextProviderMixin( this.observe(this._dataTypeContext.data, (dataType) => { if (dataType && dataType.name !== this._dataTypeName) { - this._dataTypeName = dataType.name; + this._dataTypeName = dataType.name ?? ''; } }); }); diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts index 7151864c06..3231143d01 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts @@ -1,12 +1,9 @@ -import { Entity } from './entities'; import { UmbEntityData } from './entity.data'; import { FolderTreeItem } from '@umbraco-cms/backend-api'; -export interface DataTypeEntity extends Entity { - type: 'dataType'; -} - -export interface DataTypeDetails extends DataTypeEntity { +export interface DataTypeDetails extends FolderTreeItem { + key: string; // TODO: remove when server is fixed + isTrashed: boolean; // TODO: remove only temp part of refactor propertyEditorModelAlias: string | null; propertyEditorUIAlias: string | null; data: Array; From 5e9f4ac180f36654018b061c96ca21ddcff31a96 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 14:26:01 +0100 Subject: [PATCH 019/223] fix import path --- .../editors/data-type/data-type.context.ts | 2 +- .../editors/data-type/editor-data-type.element.ts | 2 +- .../edit/editor-view-data-type-edit.element.ts | 3 +-- .../info/editor-view-data-type-info.element.ts | 2 +- .../src/core/mocks/data/data-type.data.ts | 14 +------------- .../src/core/mocks/domains/data-type.handlers.ts | 4 ++-- src/Umbraco.Web.UI.Client/src/core/models/index.ts | 1 + .../src/core/stores/data-type/data-type.store.ts | 2 +- 8 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/data-type.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/data-type.context.ts index 492b5ea985..25f5fb2b7c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/data-type.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/data-type.context.ts @@ -1,5 +1,5 @@ import { BehaviorSubject, Observable } from 'rxjs'; -import { DataTypeDetails } from '../../../core/mocks/data/data-type.data'; +import type { DataTypeDetails } from '@umbraco-cms/models'; export class UmbDataTypeContext { // TODO: figure out how fine grained we want to make our observables. diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/editor-data-type.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/editor-data-type.element.ts index 9133eaafc3..a8db696e39 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/editor-data-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/editor-data-type.element.ts @@ -3,8 +3,8 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html, LitElement } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { UmbDataTypeStore } from '../../../core/stores/data-type/data-type.store'; -import type { DataTypeDetails } from '../../../core/mocks/data/data-type.data'; import { UmbDataTypeContext } from './data-type.context'; +import type { DataTypeDetails } from '@umbraco-cms/models'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextProviderMixin, UmbContextConsumerMixin } from '@umbraco-cms/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/views/edit/editor-view-data-type-edit.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/views/edit/editor-view-data-type-edit.element.ts index 5bc1d3ac74..a28cbaa0c8 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/views/edit/editor-view-data-type-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/views/edit/editor-view-data-type-edit.element.ts @@ -3,10 +3,9 @@ import { css, html, LitElement, nothing } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { UmbModalService } from '../../../../../core/services/modal'; import { UmbDataTypeContext } from '../../data-type.context'; -import type { DataTypeDetails } from '../../../../../core/mocks/data/data-type.data'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; -import type { ManifestPropertyEditorUI } from '@umbraco-cms/models'; +import type { ManifestPropertyEditorUI, DataTypeDetails } from '@umbraco-cms/models'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import '../../../../property-editor-uis/shared/property-editor-config/property-editor-config.element'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/views/info/editor-view-data-type-info.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/views/info/editor-view-data-type-info.element.ts index 0a28def5f2..9d93dd1046 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/views/info/editor-view-data-type-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/views/info/editor-view-data-type-info.element.ts @@ -3,7 +3,7 @@ import { css, html, LitElement } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { distinctUntilChanged } from 'rxjs'; import { UmbDataTypeContext } from '../../data-type.context'; -import type { DataTypeDetails } from '../../../../../core/mocks/data/data-type.data'; +import type { DataTypeDetails } from '@umbraco-cms/models'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts index 3231143d01..89476fa32e 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts @@ -1,18 +1,6 @@ import { UmbEntityData } from './entity.data'; import { FolderTreeItem } from '@umbraco-cms/backend-api'; - -export interface DataTypeDetails extends FolderTreeItem { - key: string; // TODO: remove when server is fixed - isTrashed: boolean; // TODO: remove only temp part of refactor - propertyEditorModelAlias: string | null; - propertyEditorUIAlias: string | null; - data: Array; -} - -export interface DataTypePropertyData { - alias: string; - value: any; -} +import type { DataTypeDetails } from '@umbraco-cms/models'; export const data: Array = [ { diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type.handlers.ts index f2a6b59429..77f912ee7d 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type.handlers.ts @@ -1,6 +1,6 @@ import { rest } from 'msw'; - -import { DataTypeDetails, umbDataTypeData } from '../data/data-type.data'; +import { umbDataTypeData } from '../data/data-type.data'; +import type { DataTypeDetails } from '@umbraco-cms/models'; // TODO: add schema export const handlers = [ diff --git a/src/Umbraco.Web.UI.Client/src/core/models/index.ts b/src/Umbraco.Web.UI.Client/src/core/models/index.ts index 73a22711f2..1e6eb0c185 100644 --- a/src/Umbraco.Web.UI.Client/src/core/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/core/models/index.ts @@ -57,6 +57,7 @@ export interface UserGroupDetails extends UserGroupEntity { // Data Types export interface DataTypeDetails extends FolderTreeItem { key: string; // TODO: Remove this when the backend is fixed + isTrashed: boolean; // TODO: remove only temp part of refactor propertyEditorModelAlias: string | null; propertyEditorUIAlias: string | null; data: Array; diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts index 9c57c8b7f0..f0123524ca 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts @@ -1,7 +1,7 @@ import { map, Observable } from 'rxjs'; -import { DataTypeDetails } from '../../mocks/data/data-type.data'; import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; +import type { DataTypeDetails } from '@umbraco-cms/models'; /** * @export From 5ed61acf3d327ffdda53cbc7e38a3f32b11c7c5d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 14:32:46 +0100 Subject: [PATCH 020/223] update data type data --- .../src/core/mocks/data/data-type.data.ts | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts index 89476fa32e..41e742ad20 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts @@ -4,13 +4,15 @@ import type { DataTypeDetails } from '@umbraco-cms/models'; export const data: Array = [ { - key: 'dt-1', name: 'Text', - type: 'dataType', + type: 'data-type', + icon: 'umb:autofill', + hasChildren: false, + key: 'dt-1', + isContainer: false, parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', isTrashed: false, - hasChildren: false, - icon: 'umb:autofill', + isFolder: false, propertyEditorModelAlias: 'Umbraco.TextBox', propertyEditorUIAlias: 'Umb.PropertyEditorUI.TextBox', data: [ @@ -21,13 +23,15 @@ export const data: Array = [ ], }, { - key: 'dt-2', name: 'Textarea', - type: 'dataType', + type: 'data-type', + icon: 'umb:autofill', + hasChildren: false, + key: 'dt-2', + isContainer: false, parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', isTrashed: false, - hasChildren: false, - icon: 'umb:autofill', + isFolder: false, propertyEditorModelAlias: 'Umbraco.TextArea', propertyEditorUIAlias: 'Umb.PropertyEditorUI.Textarea', data: [ @@ -42,37 +46,43 @@ export const data: Array = [ ], }, { - key: 'dt-3', name: 'My JS Property Editor', - type: 'dataType', + type: 'data-type', + icon: 'umb:autofill', + hasChildren: false, + key: 'dt-3', + isContainer: false, parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', isTrashed: false, - hasChildren: false, - icon: 'umb:autofill', + isFolder: false, propertyEditorModelAlias: 'Umbraco.Custom', propertyEditorUIAlias: 'My.PropertyEditorUI.Custom', data: [], }, { - key: 'dt-5', name: 'Content Picker (DataType)', - type: 'dataType', + type: 'data-type', + icon: 'umb:autofill', + hasChildren: false, + key: 'dt-5', + isContainer: false, parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', isTrashed: false, - hasChildren: false, - icon: 'umb:autofill', + isFolder: false, propertyEditorModelAlias: 'Umbraco.ContentPicker', propertyEditorUIAlias: 'Umb.PropertyEditorUI.ContentPicker', data: [], }, { - key: 'dt-6', name: 'Empty', - type: 'dataType', + type: 'data-type', + icon: 'umb:autofill', + hasChildren: false, + key: 'dt-6', + isContainer: false, parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', isTrashed: false, - hasChildren: false, - icon: 'umb:autofill', + isFolder: false, propertyEditorModelAlias: '', propertyEditorUIAlias: '', data: [], From 45cf97a65a03739a5fec4f72f94661d31f28b6ab Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 14:47:27 +0100 Subject: [PATCH 021/223] add tree methods to data type store --- .../core/stores/data-type/data-type.store.ts | 47 +++++++++++++++++-- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts index f0123524ca..b9383becd6 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts @@ -2,6 +2,7 @@ import { map, Observable } from 'rxjs'; import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; import type { DataTypeDetails } from '@umbraco-cms/models'; +import { ApiError, DataTypeResource, FolderTreeItem, ProblemDetails } from '@umbraco-cms/backend-api'; /** * @export @@ -9,7 +10,7 @@ import type { DataTypeDetails } from '@umbraco-cms/models'; * @extends {UmbDataStoreBase} * @description - Data Store for Data Types */ -export class UmbDataTypeStore extends UmbDataStoreBase { +export class UmbDataTypeStore extends UmbDataStoreBase { private _entityStore: UmbEntityStore; constructor(entityStore: UmbEntityStore) { @@ -23,7 +24,7 @@ export class UmbDataTypeStore extends UmbDataStoreBase { * @return {*} {(Observable)} * @memberof UmbDataTypeStore */ - getByKey(key: string): Observable { + getByKey(key: string): Observable { // TODO: use Fetcher API. // TODO: only fetch if the data type is not in the store? fetch(`/umbraco/backoffice/data-type/details/${key}`) @@ -32,9 +33,7 @@ export class UmbDataTypeStore extends UmbDataStoreBase { this.update(data); }); - return this.items.pipe( - map((dataTypes: Array) => dataTypes.find((node: DataTypeDetails) => node.key === key) || null) - ); + return this.items.pipe(map((dataTypes) => dataTypes.find((dataType) => dataType.key === key) || null)); } /** @@ -79,4 +78,42 @@ export class UmbDataTypeStore extends UmbDataStoreBase { this.update(data); this._entityStore.update(data); } + + getTreeRoot(): Observable> { + DataTypeResource.getTreeDataTypeRoot({}).then( + (res) => { + this.update(res.items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null))); + } + + getTreeItemChildren(key: string): Observable> { + DataTypeResource.getTreeDataTypeChildren({ + parentKey: key, + }).then( + (res) => { + this.update(res.items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === key))); + } } From 532c5afc82c24c01a193ee1fb9d5cc9f439f8bd3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 15:03:02 +0100 Subject: [PATCH 022/223] render tree extensions --- .../data-types/tree-data-types.element.ts | 11 +++-------- .../trees/shared/tree-navigator.element.ts | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.element.ts index 0343a46485..51312da84f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.element.ts @@ -1,13 +1,12 @@ import { html } from 'lit'; import { customElement } from 'lit/decorators.js'; -import { UmbEntityStore } from '../../../core/stores/entity.store'; import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbTreeDataTypesDataContext } from './tree-data-types-data.context'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import type { ManifestTreeItemAction, ManifestWithLoader } from '@umbraco-cms/models'; import '../shared/tree-navigator.element'; +import { UmbDataTypeStore } from 'src/core/stores/data-type/data-type.store'; @customElement('umb-tree-data-types') export class UmbTreeDataTypesElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { @@ -16,12 +15,8 @@ export class UmbTreeDataTypesElement extends UmbContextProviderMixin(UmbContextC this._registerTreeItemActions(); - this.consumeContext('umbEntityStore', (entityStore: UmbEntityStore) => { - this._entityStore = entityStore; - if (!this._entityStore) return; - - this._treeDataContext = new UmbTreeDataTypesDataContext(this._entityStore); - this.provideContext('umbTreeDataContext', this._treeDataContext); + this.consumeContext('umbDataTypeStore', (dataTypeStore: UmbDataTypeStore) => { + this.provideContext('umbTreeStore', dataTypeStore); }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts index aff505a456..f97466f086 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts @@ -2,10 +2,13 @@ import { css, html, LitElement } from 'lit'; import { repeat } from 'lit/directives/repeat.js'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, state } from 'lit/decorators.js'; +import { ifDefined } from 'lit-html/directives/if-defined.js'; import { Entity } from '../../../core/mocks/data/entities'; import { UmbTreeDataContextBase } from '../tree-data.context'; +import { UmbTreeContext } from '../tree.context'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import type { ManifestTree } from '@umbraco-cms/models'; import './tree-item.element'; @@ -19,6 +22,9 @@ export class UmbTreeNavigator extends UmbContextConsumerMixin(UmbObserverMixin(L @state() private _items: Entity[] = []; + @state() + private _tree?: ManifestTree; + private _treeDataContext?: UmbTreeDataContextBase; constructor() { @@ -28,6 +34,10 @@ export class UmbTreeNavigator extends UmbContextConsumerMixin(UmbObserverMixin(L this._treeDataContext = treeDataContext; this._observeTreeRoot(); }); + + this.consumeContext('umbTreeContext', (treeContext: UmbTreeContext) => { + this._tree = treeContext.tree; + }); } private _observeTreeRoot() { @@ -43,6 +53,14 @@ export class UmbTreeNavigator extends UmbContextConsumerMixin(UmbObserverMixin(L } render() { + // TODO: how do we know if a tree has children? + return html` + + ${this._renderRootItems()} + `; + } + + private _renderRootItems() { return html` ${repeat( this._items, From 877ee0cb16c38ae3a194f42bca398602882eba44 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 16:51:01 +0100 Subject: [PATCH 023/223] rename data-type-tree handler file --- ...ata-type-tree.handlers.ts => tree-data-type.handlers.ts} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename src/Umbraco.Web.UI.Client/src/core/mocks/domains/{data-type-tree.handlers.ts => tree-data-type.handlers.ts} (80%) diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type-tree.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-data-type.handlers.ts similarity index 80% rename from src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type-tree.handlers.ts rename to src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-data-type.handlers.ts index f8af07e9fb..a0e6b1a269 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/data-type-tree.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-data-type.handlers.ts @@ -3,7 +3,7 @@ import { umbDataTypeData } from '../data/data-type.data'; // TODO: add schema export const handlers = [ - rest.get('/umbraco/management/api/v1/data-type/tree/root', (req, res, ctx) => { + rest.get('/umbraco/management/api/v1/tree/data-type/root', (req, res, ctx) => { const rootItems = umbDataTypeData.getTreeRoot(); const response = { total: rootItems.length, @@ -12,7 +12,7 @@ export const handlers = [ return res(ctx.status(200), ctx.json(response)); }), - rest.get('/umbraco/management/api/v1/data-type/tree/children', (req, res, ctx) => { + rest.get('/umbraco/management/api/v1/tree/data-type/children', (req, res, ctx) => { const key = req.params.key as string; if (!key) return; @@ -26,7 +26,7 @@ export const handlers = [ return res(ctx.status(200), ctx.json(response)); }), - rest.get('/umbraco/management/api/v1/data-type/tree/item', (req, res, ctx) => { + rest.get('/umbraco/management/api/v1/tree/data-type/item', (req, res, ctx) => { const keys = req.params.keys as string; if (!keys) return; From 1c1075b12e58ea146d4486ade550f53469aeecce Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 16:51:15 +0100 Subject: [PATCH 024/223] import data type tree handlers --- src/Umbraco.Web.UI.Client/src/core/mocks/browser-handlers.ts | 5 +++++ 1 file changed, 5 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 9bc24774cf..d1846ef1dc 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 @@ -12,6 +12,9 @@ import { handlers as telemetryHandlers } from './domains/telemetry.handlers'; import { handlers as usersHandlers } from './domains/users.handlers'; import { handlers as userGroupsHandlers } from './domains/user-groups.handlers'; +// treeHandlers +import { handlers as treeDataTypeHandlers } from './domains/tree-data-type.handlers'; + const handlers = [ serverHandlers.serverVersionHandler, ...contentHandlers, @@ -26,6 +29,8 @@ const handlers = [ ...publishedStatusHandlers, ...usersHandlers, ...userGroupsHandlers, + + ...treeDataTypeHandlers, ]; switch (import.meta.env.VITE_UMBRACO_INSTALL_STATUS) { From 3316b2e69f48630cd553265af6e98ae33aacbc71 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 16:51:32 +0100 Subject: [PATCH 025/223] add tree methods to store interface --- src/Umbraco.Web.UI.Client/src/core/stores/store.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/store.ts index 8da1cdd170..76f2d9949f 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/store.ts @@ -8,6 +8,8 @@ export interface UmbDataStoreIdentifiers { export interface UmbDataStore { readonly items: Observable>; update(items: Array): void; + getTreeRoot?(): Observable>; + getTreeItemChildren?(key: string): Observable>; } /** From 8c0e525ae0f5c0a6c02e489b3b22e82e852d7c09 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 16:51:54 +0100 Subject: [PATCH 026/223] set parent key on root items to null --- .../src/core/mocks/data/data-type.data.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts index 41e742ad20..49eb113b98 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts @@ -10,7 +10,7 @@ export const data: Array = [ hasChildren: false, key: 'dt-1', isContainer: false, - parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', + parentKey: null, isTrashed: false, isFolder: false, propertyEditorModelAlias: 'Umbraco.TextBox', @@ -29,7 +29,7 @@ export const data: Array = [ hasChildren: false, key: 'dt-2', isContainer: false, - parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', + parentKey: null, isTrashed: false, isFolder: false, propertyEditorModelAlias: 'Umbraco.TextArea', @@ -52,7 +52,7 @@ export const data: Array = [ hasChildren: false, key: 'dt-3', isContainer: false, - parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', + parentKey: null, isTrashed: false, isFolder: false, propertyEditorModelAlias: 'Umbraco.Custom', @@ -66,7 +66,7 @@ export const data: Array = [ hasChildren: false, key: 'dt-5', isContainer: false, - parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', + parentKey: null, isTrashed: false, isFolder: false, propertyEditorModelAlias: 'Umbraco.ContentPicker', @@ -80,7 +80,7 @@ export const data: Array = [ hasChildren: false, key: 'dt-6', isContainer: false, - parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', + parentKey: null, isTrashed: false, isFolder: false, propertyEditorModelAlias: '', From 571d2235954bed82e6c97bd828414e8baf25b38a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 16:52:24 +0100 Subject: [PATCH 027/223] consume tree store and get root items --- .../trees/shared/tree-navigator.element.ts | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts index f97466f086..dbce267179 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts @@ -4,11 +4,11 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, state } from 'lit/decorators.js'; import { ifDefined } from 'lit-html/directives/if-defined.js'; import { Entity } from '../../../core/mocks/data/entities'; -import { UmbTreeDataContextBase } from '../tree-data.context'; import { UmbTreeContext } from '../tree.context'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; import type { ManifestTree } from '@umbraco-cms/models'; +import { UmbDataStore } from 'src/core/stores/store'; import './tree-item.element'; @@ -25,14 +25,13 @@ export class UmbTreeNavigator extends UmbContextConsumerMixin(UmbObserverMixin(L @state() private _tree?: ManifestTree; - private _treeDataContext?: UmbTreeDataContextBase; + private _treeStore?: UmbDataStore; constructor() { super(); - this.consumeContext('umbTreeDataContext', (treeDataContext) => { - this._treeDataContext = treeDataContext; - this._observeTreeRoot(); + this.consumeContext('umbTreeStore', (treeStore) => { + this._treeStore = treeStore; }); this.consumeContext('umbTreeContext', (treeContext: UmbTreeContext) => { @@ -40,12 +39,16 @@ export class UmbTreeNavigator extends UmbContextConsumerMixin(UmbObserverMixin(L }); } + private _onShowRoot() { + this._observeTreeRoot(); + } + private _observeTreeRoot() { - if (!this._treeDataContext?.rootChanges?.()) return; + if (!this._treeStore?.getTreeRoot) return; this._loading = true; - this.observe(this._treeDataContext.rootChanges(), (rootItems) => { + this.observe(this._treeStore.getTreeRoot(), (rootItems) => { if (rootItems?.length === 0) return; this._items = rootItems; this._loading = false; @@ -54,7 +57,10 @@ export class UmbTreeNavigator extends UmbContextConsumerMixin(UmbObserverMixin(L render() { // TODO: how do we know if a tree has children? - return html` + return html` ${this._renderRootItems()} `; From ac4c9eea9381eb91568edf6da70b616114cfb08d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 17:03:14 +0100 Subject: [PATCH 028/223] delete data type tree data context --- .../tree-data-types-data.context.ts | 30 ------------------- 1 file changed, 30 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types-data.context.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types-data.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types-data.context.ts deleted file mode 100644 index 91cb6ae396..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types-data.context.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { UmbTreeDataContextBase } from '../tree-data.context'; - -export class UmbTreeDataTypesDataContext extends UmbTreeDataContextBase { - public rootKey = '29d78e6c-c1bf-4c15-b820-d511c237ffae'; - - public rootChanges() { - const data = { - key: this.rootKey, - name: 'Data Types', - hasChildren: true, - type: 'dataTypeRoot', - icon: 'folder', - parentKey: '', - isTrashed: false, - }; - this.entityStore.update([data]); - return super.rootChanges(); - } - - public childrenChanges(key = '') { - // TODO: figure out url structure - fetch(`/umbraco/backoffice/entities/data-types?parentKey=${key}`) - .then((res) => res.json()) - .then((data) => { - this.entityStore.update(data); - }); - - return super.childrenChanges(key); - } -} From 05dc1e348ed353112687c8ecf456f71f304c2b6e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 17:03:25 +0100 Subject: [PATCH 029/223] move document type store into folder --- .../src/backoffice/backoffice.element.ts | 2 +- .../save/editor-action-document-type-save.element.ts | 2 +- .../editors/document-type/editor-document-type.element.ts | 2 +- .../core/stores/{ => document-type}/document-type.store.ts | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) rename src/Umbraco.Web.UI.Client/src/core/stores/{ => document-type}/document-type.store.ts (87%) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index e4969b2511..2330015f52 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -18,7 +18,7 @@ import { css, html, LitElement } from 'lit'; import { UmbModalService } from '../core/services/modal'; import { UmbNotificationService } from '../core/services/notification'; import { UmbDataTypeStore } from '../core/stores/data-type/data-type.store'; -import { UmbDocumentTypeStore } from '../core/stores/document-type.store'; +import { UmbDocumentTypeStore } from '../core/stores/document-type/document-type.store'; import { UmbNodeStore } from '../core/stores/node.store'; import { UmbSectionStore } from '../core/stores/section.store'; import { UmbEntityStore } from '../core/stores/entity.store'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/actions/save/editor-action-document-type-save.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/actions/save/editor-action-document-type-save.element.ts index 0a0294f066..475e887a9a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/actions/save/editor-action-document-type-save.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/actions/save/editor-action-document-type-save.element.ts @@ -4,7 +4,7 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import type { UUIButtonState } from '@umbraco-ui/uui'; import type { UmbNotificationDefaultData } from '../../../../../core/services/notification/layouts/default'; import type { UmbNotificationService } from '../../../../../core/services/notification'; -import { UmbDocumentTypeStore } from '../../../../../core/stores/document-type.store'; +import { UmbDocumentTypeStore } from '../../../../../core/stores/document-type/document-type.store'; import { UmbDocumentTypeContext } from '../../document-type.context'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/editor-document-type.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/editor-document-type.element.ts index 85cdfc0d28..c64fd67621 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/editor-document-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/editor-document-type.element.ts @@ -3,7 +3,7 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html, LitElement } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { distinctUntilChanged } from 'rxjs'; -import { UmbDocumentTypeStore } from '../../../core/stores/document-type.store'; +import { UmbDocumentTypeStore } from '../../../core/stores/document-type/document-type.store'; import { DocumentTypeEntity } from '../../../core/mocks/data/document-type.data'; import { UmbDocumentTypeContext } from './document-type.context'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts similarity index 87% rename from src/Umbraco.Web.UI.Client/src/core/stores/document-type.store.ts rename to src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts index a51d5a3678..b55df96a9f 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/document-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts @@ -1,7 +1,7 @@ import { map, Observable } from 'rxjs'; -import { DocumentTypeEntity } from '../mocks/data/document-type.data'; -import { UmbEntityStore } from './entity.store'; -import { UmbDataStoreBase } from './store'; +import { DocumentTypeEntity } from '../../mocks/data/document-type.data'; +import { UmbEntityStore } from '../entity.store'; +import { UmbDataStoreBase } from '../store'; export class UmbDocumentTypeStore extends UmbDataStoreBase { private _entityStore: UmbEntityStore; From 2d356e2b9255dc20dfe1f29ddaf29563f206a13b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 17:07:53 +0100 Subject: [PATCH 030/223] Rename document type entity to details --- .../document-type/document-type.context.ts | 10 +++++----- .../editor-document-type.element.ts | 8 ++++---- .../editor-view-document-type-design.element.ts | 6 +++--- .../src/core/mocks/data/document-type.data.ts | 17 +++-------------- .../mocks/domains/document-type.handlers.ts | 4 ++-- .../src/core/models/index.ts | 1 + .../stores/document-type/document-type.store.ts | 12 ++++++------ 7 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/document-type.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/document-type.context.ts index 707e9afe52..f9a41ab96c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/document-type.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/document-type.context.ts @@ -1,9 +1,9 @@ import { BehaviorSubject, Observable } from 'rxjs'; -import { DocumentTypeEntity } from '../../../core/mocks/data/document-type.data'; +import { DocumentTypeDetails } from '../../../core/mocks/data/document-type.data'; export class UmbDocumentTypeContext { // TODO: figure out how fine grained we want to make our observables. - private _data = new BehaviorSubject({ + private _data = new BehaviorSubject({ key: '', name: '', icon: '', @@ -14,15 +14,15 @@ export class UmbDocumentTypeContext { alias: '', properties: [], }); - public readonly data: Observable = this._data.asObservable(); + public readonly data: Observable = this._data.asObservable(); - constructor(documentType?: DocumentTypeEntity) { + constructor(documentType?: DocumentTypeDetails) { if (!documentType) return; this._data.next(documentType); } // TODO: figure out how we want to update data - public update(data: Partial) { + public update(data: Partial) { this._data.next({ ...this._data.getValue(), ...data }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/editor-document-type.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/editor-document-type.element.ts index c64fd67621..e34d9ff1ef 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/editor-document-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/editor-document-type.element.ts @@ -4,7 +4,7 @@ import { css, html, LitElement } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { distinctUntilChanged } from 'rxjs'; import { UmbDocumentTypeStore } from '../../../core/stores/document-type/document-type.store'; -import { DocumentTypeEntity } from '../../../core/mocks/data/document-type.data'; +import { DocumentTypeDetails } from '../../../core/mocks/data/document-type.data'; import { UmbDocumentTypeContext } from './document-type.context'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; @@ -40,7 +40,7 @@ export class UmbEditorDocumentTypeElement extends UmbContextProviderMixin( entityKey!: string; @state() - private _documentType?: DocumentTypeEntity; + private _documentType?: DocumentTypeDetails; private _documentTypeContext?: UmbDocumentTypeContext; private _documentTypeStore?: UmbDocumentTypeStore; @@ -92,7 +92,7 @@ export class UmbEditorDocumentTypeElement extends UmbContextProviderMixin( if (!this._documentTypeStore) return; // TODO: This should be done in a better way, but for now it works. - this.observe(this._documentTypeStore.getByKey(this.entityKey), (documentType) => { + this.observe(this._documentTypeStore.getByKey(this.entityKey), (documentType) => { if (!documentType) return; // TODO: Handle nicely if there is no document type if (!this._documentTypeContext) { @@ -102,7 +102,7 @@ export class UmbEditorDocumentTypeElement extends UmbContextProviderMixin( this._documentTypeContext.update(documentType); } - this.observe(this._documentTypeContext.data.pipe(distinctUntilChanged()), (data) => { + this.observe(this._documentTypeContext.data.pipe(distinctUntilChanged()), (data) => { this._documentType = data; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/views/design/editor-view-document-type-design.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/views/design/editor-view-document-type-design.element.ts index 7655e16cc7..770b12ecd8 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/views/design/editor-view-document-type-design.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document-type/views/design/editor-view-document-type-design.element.ts @@ -2,7 +2,7 @@ import { css, html, LitElement } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, state } from 'lit/decorators.js'; import { distinctUntilChanged } from 'rxjs'; -import type { DocumentTypeEntity } from '../../../../../core/mocks/data/document-type.data'; +import type { DocumentTypeDetails } from '../../../../../core/mocks/data/document-type.data'; import { UmbDocumentTypeContext } from '../../document-type.context'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; @@ -12,7 +12,7 @@ export class UmbEditorViewDocumentTypeDesignElement extends UmbContextConsumerMi static styles = [UUITextStyles, css``]; @state() - _documentType?: DocumentTypeEntity; + _documentType?: DocumentTypeDetails; private _documentTypeContext?: UmbDocumentTypeContext; @@ -28,7 +28,7 @@ export class UmbEditorViewDocumentTypeDesignElement extends UmbContextConsumerMi private _observeDocumentType() { if (!this._documentTypeContext) return; - this.observe(this._documentTypeContext.data.pipe(distinctUntilChanged()), (documentType) => { + this.observe(this._documentTypeContext.data.pipe(distinctUntilChanged()), (documentType) => { this._documentType = documentType; }); } 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 b0408342e8..8322d44ae2 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 @@ -1,19 +1,8 @@ -import { Entity } from './entities'; import { UmbEntityData } from './entity.data'; import { DocumentTypeTreeItem } from '@umbraco-cms/backend-api'; +import type { DocumentTypeDetails } from '@umbraco-cms/models'; -export interface DocumentTypeEntity extends Entity { - key: string; - name: string; - alias: string; - type: string; - parentKey: string; - isTrashed: boolean; - hasChildren: boolean; - properties: []; -} - -export const data: Array = [ +export const data: Array = [ { key: 'd81c7957-153c-4b5a-aa6f-b434a4964624', name: 'Document Type 1', @@ -39,7 +28,7 @@ export const data: Array = [ ]; // Temp mocked database -class UmbDocumentTypeData extends UmbEntityData { +class UmbDocumentTypeData extends UmbEntityData { constructor() { super(data); } diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type.handlers.ts index 555f20177f..0c2fc9375e 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type.handlers.ts @@ -1,6 +1,6 @@ import { rest } from 'msw'; -import { DocumentTypeEntity, umbDocumentTypeData } from '../data/document-type.data'; +import { DocumentTypeDetails, umbDocumentTypeData } from '../data/document-type.data'; // TODO: add schema export const handlers = [ @@ -13,7 +13,7 @@ export const handlers = [ return res(ctx.status(200), ctx.json([document])); }), - rest.post('/umbraco/backoffice/document-type/save', (req, res, ctx) => { + rest.post('/umbraco/backoffice/document-type/save', (req, res, ctx) => { const data = req.body; if (!data) return; diff --git a/src/Umbraco.Web.UI.Client/src/core/models/index.ts b/src/Umbraco.Web.UI.Client/src/core/models/index.ts index 1e6eb0c185..75f7eb2922 100644 --- a/src/Umbraco.Web.UI.Client/src/core/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/core/models/index.ts @@ -71,6 +71,7 @@ export interface DataTypePropertyData { // Document Types export interface DocumentTypeDetails extends DocumentTypeTreeItem { key: string; // TODO: Remove this when the backend is fixed + isTrashed: boolean; // TODO: remove only temp part of refactor alias: string; properties: []; } diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts index b55df96a9f..73b5b8925b 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts @@ -1,9 +1,9 @@ import { map, Observable } from 'rxjs'; -import { DocumentTypeEntity } from '../../mocks/data/document-type.data'; +import { DocumentTypeDetails } from '../../mocks/data/document-type.data'; import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; -export class UmbDocumentTypeStore extends UmbDataStoreBase { +export class UmbDocumentTypeStore extends UmbDataStoreBase { private _entityStore: UmbEntityStore; constructor(entityStore: UmbEntityStore) { @@ -11,7 +11,7 @@ export class UmbDocumentTypeStore extends UmbDataStoreBase { this._entityStore = entityStore; } - getByKey(key: string): Observable { + getByKey(key: string): Observable { // TODO: use Fetcher API. // TODO: only fetch if the data type is not in the store? fetch(`/umbraco/backoffice/document-type/${key}`) @@ -22,13 +22,13 @@ export class UmbDocumentTypeStore extends UmbDataStoreBase { return this.items.pipe( map( - (documentTypes: Array) => - documentTypes.find((documentType: DocumentTypeEntity) => documentType.key === key) || null + (documentTypes: Array) => + documentTypes.find((documentType: DocumentTypeDetails) => documentType.key === key) || null ) ); } - async save(documentTypes: Array) { + async save(documentTypes: Array) { // TODO: use Fetcher API. try { const res = await fetch('/umbraco/backoffice/document-type/save', { From dfa949f4d023d232234beb09be86be15b3c68f82 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 18:27:14 +0100 Subject: [PATCH 031/223] set up document type store --- .../tree-document-types-data.context.ts | 30 ----------- .../tree-document-types.element.ts | 11 ++-- .../src/core/mocks/browser-handlers.ts | 2 + .../src/core/mocks/data/document-type.data.ts | 22 +++++--- .../mocks/domains/document-type.handlers.ts | 4 +- ...lers.ts => tree-document-type.handlers.ts} | 0 .../core/stores/data-type/data-type.store.ts | 4 +- .../document-type/document-type.store.ts | 50 ++++++++++++++++--- 8 files changed, 66 insertions(+), 57 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types-data.context.ts rename src/Umbraco.Web.UI.Client/src/core/mocks/domains/{document-type-tree.handlers.ts => tree-document-type.handlers.ts} (100%) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types-data.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types-data.context.ts deleted file mode 100644 index 42b23908e9..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types-data.context.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { UmbTreeDataContextBase } from '../tree-data.context'; - -export class UmbTreeDocumentTypesDataContext extends UmbTreeDataContextBase { - public rootKey = 'f50eb86d-3ef2-4011-8c5d-c56c04eec0da'; - - public rootChanges() { - const data = { - key: this.rootKey, - name: 'Document Types', - hasChildren: true, - type: 'documentTypeRoot', - icon: 'folder', - parentKey: '', - isTrashed: false, - }; - this.entityStore.update([data]); - return super.rootChanges(); - } - - public childrenChanges(key: string) { - // TODO: figure out url structure - fetch(`/umbraco/backoffice/entities/document-types?parentKey=${key}`) - .then((res) => res.json()) - .then((data) => { - this.entityStore.update(data); - }); - - return super.childrenChanges(key); - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.element.ts index a5d173e499..b436ba4c46 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.element.ts @@ -1,23 +1,18 @@ import { html } from 'lit'; import { customElement } from 'lit/decorators.js'; -import { UmbEntityStore } from '../../../core/stores/entity.store'; import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbTreeDocumentTypesDataContext } from './tree-document-types-data.context'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import '../shared/tree-navigator.element'; +import { UmbDocumentTypeStore } from 'src/core/stores/document-type/document-type.store'; @customElement('umb-tree-document-types') export class UmbTreeDocumentTypes extends UmbContextConsumerMixin(UmbContextProviderMixin(UmbTreeBase)) { constructor() { super(); - this.consumeContext('umbEntityStore', (entityStore: UmbEntityStore) => { - this._entityStore = entityStore; - if (!this._entityStore) return; - - this._treeDataContext = new UmbTreeDocumentTypesDataContext(this._entityStore); - this.provideContext('umbTreeDataContext', this._treeDataContext); + this.consumeContext('umbDocumentTypeStore', (store: UmbDocumentTypeStore) => { + this.provideContext('umbTreeStore', store); }); } 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 d1846ef1dc..0a45bd9652 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 @@ -14,6 +14,7 @@ import { handlers as userGroupsHandlers } from './domains/user-groups.handlers'; // treeHandlers import { handlers as treeDataTypeHandlers } from './domains/tree-data-type.handlers'; +import { handlers as treeDocumentTypeHandlers } from './domains/tree-document-type.handlers'; const handlers = [ serverHandlers.serverVersionHandler, @@ -31,6 +32,7 @@ const handlers = [ ...userGroupsHandlers, ...treeDataTypeHandlers, + ...treeDocumentTypeHandlers, ]; switch (import.meta.env.VITE_UMBRACO_INSTALL_STATUS) { 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 8322d44ae2..0f23f2f541 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 @@ -4,25 +4,31 @@ import type { DocumentTypeDetails } from '@umbraco-cms/models'; export const data: Array = [ { - key: 'd81c7957-153c-4b5a-aa6f-b434a4964624', name: 'Document Type 1', - alias: 'documentType1', type: 'documentType', - parentKey: 'f50eb86d-3ef2-4011-8c5d-c56c04eec0da', - isTrashed: false, hasChildren: false, + key: 'd81c7957-153c-4b5a-aa6f-b434a4964624', + isContainer: false, + parentKey: null, + isFolder: false, + isElement: false, + isTrashed: false, icon: '', + alias: 'documentType1', properties: [], }, { - key: 'a99e4018-3ffc-486b-aa76-eecea9593d17', name: 'Document Type 2', - alias: 'documentType2', type: 'documentType', - parentKey: 'f50eb86d-3ef2-4011-8c5d-c56c04eec0da', - isTrashed: false, hasChildren: false, + key: 'a99e4018-3ffc-486b-aa76-eecea9593d17', + isContainer: false, + parentKey: null, + isFolder: false, + isElement: false, + isTrashed: false, icon: '', + alias: 'documentType2', properties: [], }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type.handlers.ts index 0c2fc9375e..a5b3582a33 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type.handlers.ts @@ -1,6 +1,6 @@ import { rest } from 'msw'; - -import { DocumentTypeDetails, umbDocumentTypeData } from '../data/document-type.data'; +import { umbDocumentTypeData } from '../data/document-type.data'; +import type { DocumentTypeDetails } from '@umbraco-cms/models'; // TODO: add schema export const handlers = [ diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type-tree.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-document-type.handlers.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-type-tree.handlers.ts rename to src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-document-type.handlers.ts diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts index b9383becd6..03f330905b 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts @@ -79,7 +79,7 @@ export class UmbDataTypeStore extends UmbDataStoreBase> { + getTreeRoot(): Observable> { DataTypeResource.getTreeDataTypeRoot({}).then( (res) => { this.update(res.items); @@ -97,7 +97,7 @@ export class UmbDataTypeStore extends UmbDataStoreBase items.filter((item) => item.parentKey === null))); } - getTreeItemChildren(key: string): Observable> { + getTreeItemChildren(key: string): Observable> { DataTypeResource.getTreeDataTypeChildren({ parentKey: key, }).then( diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts index 73b5b8925b..c340c20fec 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts @@ -1,9 +1,10 @@ import { map, Observable } from 'rxjs'; -import { DocumentTypeDetails } from '../../mocks/data/document-type.data'; import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; +import { ApiError, DocumentTypeResource, DocumentTypeTreeItem, ProblemDetails } from '@umbraco-cms/backend-api'; +import type { DocumentTypeDetails } from '@umbraco-cms/models'; -export class UmbDocumentTypeStore extends UmbDataStoreBase { +export class UmbDocumentTypeStore extends UmbDataStoreBase { private _entityStore: UmbEntityStore; constructor(entityStore: UmbEntityStore) { @@ -11,7 +12,7 @@ export class UmbDocumentTypeStore extends UmbDataStoreBase this._entityStore = entityStore; } - getByKey(key: string): Observable { + getByKey(key: string): Observable { // TODO: use Fetcher API. // TODO: only fetch if the data type is not in the store? fetch(`/umbraco/backoffice/document-type/${key}`) @@ -21,10 +22,7 @@ export class UmbDocumentTypeStore extends UmbDataStoreBase }); return this.items.pipe( - map( - (documentTypes: Array) => - documentTypes.find((documentType: DocumentTypeDetails) => documentType.key === key) || null - ) + map((documentTypes) => documentTypes.find((documentType) => documentType.key === key) || null) ); } @@ -45,4 +43,42 @@ export class UmbDocumentTypeStore extends UmbDataStoreBase console.error('Save Document Type error', error); } } + + getTreeRoot(): Observable> { + DocumentTypeResource.getTreeDocumentTypeRoot({}).then( + (res) => { + this.update(res.items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null))); + } + + getTreeItemChildren(key: string): Observable> { + DocumentTypeResource.getTreeDocumentTypeChildren({ + parentKey: key, + }).then( + (res) => { + this.update(res.items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === key))); + } } From 2f310c3311e979c12b08e5497caf55a3aa2b96c7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 18:36:06 +0100 Subject: [PATCH 032/223] update docs --- .../src/core/stores/data-type/data-type.store.ts | 2 +- .../src/core/stores/document-type/document-type.store.ts | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts index 03f330905b..da562432ce 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts @@ -7,7 +7,7 @@ import { ApiError, DataTypeResource, FolderTreeItem, ProblemDetails } from '@umb /** * @export * @class UmbDataTypeStore - * @extends {UmbDataStoreBase} + * @extends {UmbDataStoreBase} * @description - Data Store for Data Types */ export class UmbDataTypeStore extends UmbDataStoreBase { diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts index c340c20fec..00cf7f5857 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts @@ -4,6 +4,12 @@ import { UmbDataStoreBase } from '../store'; import { ApiError, DocumentTypeResource, DocumentTypeTreeItem, ProblemDetails } from '@umbraco-cms/backend-api'; import type { DocumentTypeDetails } from '@umbraco-cms/models'; +/** + * @export + * @class UmbDocumentTypeStore + * @extends {UmbDataStoreBase} + * @description - Data Store for Document Types + */ export class UmbDocumentTypeStore extends UmbDataStoreBase { private _entityStore: UmbEntityStore; From 977a6f5858abfdb7aa3609add8202026874d7753 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 18:36:20 +0100 Subject: [PATCH 033/223] add document store with tree methods --- .../core/stores/document/document.store.ts | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts new file mode 100644 index 0000000000..b96d0c8ead --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts @@ -0,0 +1,58 @@ +import { map, Observable } from 'rxjs'; +import { UmbEntityStore } from '../entity.store'; +import { UmbDataStoreBase } from '../store'; +import type { DocumentDetails } from '@umbraco-cms/models'; +import { ApiError, DocumentResource, DocumentTreeItem, FolderTreeItem, ProblemDetails } from '@umbraco-cms/backend-api'; + +/** + * @export + * @class UmbDocumentStore + * @extends {UmbDocumentStoreBase} + * @description - Data Store for Documents + */ +export class UmbDocumentStore extends UmbDataStoreBase { + private _entityStore: UmbEntityStore; + + constructor(entityStore: UmbEntityStore) { + super(); + this._entityStore = entityStore; + } + + getTreeRoot(): Observable> { + DocumentResource.getTreeDocumentRoot({}).then( + (res) => { + this.update(res.items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null))); + } + + getTreeItemChildren(key: string): Observable> { + DocumentResource.getTreeDocumentChildren({ + parentKey: key, + }).then( + (res) => { + this.update(res.items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === key))); + } +} From 86e430676f7fe1e11be942e8b947011af48ae6ab Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 18:38:34 +0100 Subject: [PATCH 034/223] provide document store for entire backoffice --- src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index 2330015f52..bc6e006fa9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -19,6 +19,7 @@ import { UmbModalService } from '../core/services/modal'; import { UmbNotificationService } from '../core/services/notification'; import { UmbDataTypeStore } from '../core/stores/data-type/data-type.store'; import { UmbDocumentTypeStore } from '../core/stores/document-type/document-type.store'; +import { UmbDocumentStore } from '../core/stores/document/document.store'; import { UmbNodeStore } from '../core/stores/node.store'; import { UmbSectionStore } from '../core/stores/section.store'; import { UmbEntityStore } from '../core/stores/entity.store'; @@ -68,6 +69,7 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this._umbIconRegistry.attach(this); this.provideContext('umbEntityStore', this._umbEntityStore); + this.provideContext('umbDocumentStore', new UmbDocumentStore(this._umbEntityStore)); this.provideContext('umbNodeStore', new UmbNodeStore(this._umbEntityStore)); this.provideContext('umbDataTypeStore', new UmbDataTypeStore(this._umbEntityStore)); this.provideContext('umbDocumentTypeStore', new UmbDocumentTypeStore(this._umbEntityStore)); From e78514f3e6419321e7750efa4e72c20f3a7663db Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 18:55:31 +0100 Subject: [PATCH 035/223] call document store from tree --- .../documents/tree-documents-data.context.ts | 29 ---- .../trees/documents/tree-documents.element.ts | 13 +- .../src/core/mocks/browser-handlers.ts | 2 + .../src/core/mocks/data/document.data.ts | 158 +++++++++++++++--- ....handlers.ts => tree-document.handlers.ts} | 0 .../src/core/models/index.ts | 1 + 6 files changed, 138 insertions(+), 65 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents-data.context.ts rename src/Umbraco.Web.UI.Client/src/core/mocks/domains/{document-tree.handlers.ts => tree-document.handlers.ts} (100%) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents-data.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents-data.context.ts deleted file mode 100644 index 4c7e1e518e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents-data.context.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { map } from 'rxjs'; -import { UmbTreeDataContextBase } from '../tree-data.context'; - -export class UmbTreeDocumentDataContext extends UmbTreeDataContextBase { - public rootKey = 'ba23245c-d8c0-46f7-a2bc-7623743d6eba'; - - public rootChanges() { - fetch(`/umbraco/backoffice/entities/documents?parentKey=${this.rootKey}`) - .then((res) => res.json()) - .then((data) => { - this.entityStore.update(data); - }); - - return this.entityStore.items.pipe( - map((items) => items.filter((item) => item.parentKey === this.rootKey && !item.isTrashed)) - ); - } - - public fetchChildren(key: string) { - // TODO: figure out url structure - fetch(`/umbraco/backoffice/entities/documents?parentKey=${key}`) - .then((res) => res.json()) - .then((data) => { - this.entityStore.update(data); - }); - - return super.childrenChanges(key); - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts index 462b1c5245..a21b9052e0 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts @@ -1,13 +1,12 @@ import { html } from 'lit'; import { customElement } from 'lit/decorators.js'; -import { UmbEntityStore } from '../../../core/stores/entity.store'; import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbTreeDocumentDataContext } from './tree-documents-data.context'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import type { ManifestTreeItemAction, ManifestWithLoader } from '@umbraco-cms/models'; +import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; +import { UmbDocumentStore } from 'src/core/stores/document/document.store'; import '../shared/tree-navigator.element'; -import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; @customElement('umb-tree-document') export class UmbTreeDocumentElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { constructor() { @@ -15,12 +14,8 @@ export class UmbTreeDocumentElement extends UmbContextProviderMixin(UmbContextCo this._registerTreeItemActions(); - this.consumeContext('umbEntityStore', (entityStore: UmbEntityStore) => { - this._entityStore = entityStore; - if (!this._entityStore || !this.tree) return; - - this._treeDataContext = new UmbTreeDocumentDataContext(this._entityStore); - this.provideContext('umbTreeDataContext', this._treeDataContext); + this.consumeContext('umbDocumentStore', (store: UmbDocumentStore) => { + this.provideContext('umbTreeStore', store); }); } 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 0a45bd9652..b002156305 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 @@ -13,6 +13,7 @@ import { handlers as usersHandlers } from './domains/users.handlers'; import { handlers as userGroupsHandlers } from './domains/user-groups.handlers'; // treeHandlers +import { handlers as treeDocumentHandlers } from './domains/tree-document.handlers'; import { handlers as treeDataTypeHandlers } from './domains/tree-data-type.handlers'; import { handlers as treeDocumentTypeHandlers } from './domains/tree-document-type.handlers'; @@ -31,6 +32,7 @@ const handlers = [ ...usersHandlers, ...userGroupsHandlers, + ...treeDocumentHandlers, ...treeDataTypeHandlers, ...treeDocumentTypeHandlers, ]; 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 36950c82cb..7296a87528 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 @@ -4,38 +4,27 @@ import type { DocumentDetails } from '@umbraco-cms/models'; export const data: Array = [ { - key: 'f2f81a40-c989-4b6b-84e2-057cecd3adc1', - name: 'Media 1', - type: 'media', - icon: 'picture', - parentKey: 'c0858d71-52be-4bb2-822f-42fa0c9a1ea5', + name: 'Document 1', + type: 'document', + icon: 'document', hasChildren: false, + key: '74e4008a-ea4f-4793-b924-15e02fd380d1', + isContainer: false, + parentKey: null, + noAccess: false, + isProtected: false, + isPublished: false, + isEdited: false, + isTrashed: false, properties: [ { - alias: 'myMediaHeadline', - label: 'Media Headline', + alias: 'myHeadline', + label: 'Headline', description: 'Text string property', dataTypeKey: 'dt-1', }, - ], - data: [ { - alias: 'myMediaHeadline', - value: 'The daily life at Umbraco HQ', - }, - ], - variants: [], - }, - { - key: '69431027-8867-45bf-a93b-72bbdabfb177', - type: 'media', - name: 'Media 2', - icon: 'picture', - parentKey: 'c0858d71-52be-4bb2-822f-42fa0c9a1ea5', - hasChildren: false, - properties: [ - { - alias: 'myMediaDescription', + alias: 'myDescription', label: 'Description', description: 'Textarea property', dataTypeKey: 'dt-2', @@ -43,11 +32,126 @@ export const data: Array = [ ], data: [ { - alias: 'myMediaDescription', + alias: 'myHeadline', + value: 'The daily life at Umbraco HQ', + }, + { + alias: 'myDescription', value: 'Every day, a rabbit in a military costume greets me at the front door', }, ], - variants: [], + variants: [{ name: 'fake data' }], + /* + // Concept for node layout, separation of design from config and data. + layout: [ + { + type: 'group', + children: [ + { + type: 'property', + alias: 'myHeadline' + }, + { + type: 'property', + alias: 'myDescription' + } + ] + } + ], + */ + }, + { + name: 'Document 2', + type: 'document', + icon: 'favorite', + hasChildren: false, + key: '74e4008a-ea4f-4793-b924-15e02fd380d2', + isContainer: false, + parentKey: null, + noAccess: false, + isProtected: false, + isPublished: false, + isEdited: false, + isTrashed: false, + properties: [ + { + alias: 'myHeadline', + label: 'Text string label', + description: 'this is a text string property', + dataTypeKey: 'dt-1', + }, + { + alias: 'myDescription', + label: 'Textarea label', + description: 'This is the a textarea property', + dataTypeKey: 'dt-2', + }, + { + alias: 'myExternalEditor', + label: 'My JS Property Editor', + description: 'This is the a external property', + dataTypeKey: 'dt-3', + }, + { + alias: 'myContentPicker', + label: 'Content Picker', + description: 'This is a content picker', + dataTypeKey: 'dt-5', + }, + ], + data: [ + { + alias: 'myHeadline', + value: 'Is it all just fun and curling and scary rabbits?', + }, + { + alias: 'myDescription', + value: + "So no, there's not confetti every day. And no, there's not champagne every week or a crazy rabbit running around 🐰", + }, + { + alias: 'myExternalEditor', + value: 'Tex lkasdfkljdfsa 1', + }, + { + alias: 'myContextExampleEditor', + value: '', + }, + { + alias: 'myContentPicker', + value: '', + }, + ], + variants: [{ name: 'Variant 1' }], + }, + { + name: 'Document 3', + type: 'document', + icon: 'document', + hasChildren: false, + key: 'cdd30288-2d1c-41b4-89a9-61647b4a10d5', + isContainer: false, + parentKey: null, + noAccess: false, + isProtected: false, + isPublished: false, + isEdited: false, + isTrashed: false, + properties: [ + { + alias: 'myDescription', + label: 'Description', + description: 'Textarea property', + dataTypeKey: 'dt-2', + }, + ], + data: [ + { + alias: 'myDescription', + value: 'Every day, a rabbit in a military costume greets me at the front door', + }, + ], + variants: [{ name: 'Variant 1' }], }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-tree.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-document.handlers.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/core/mocks/domains/document-tree.handlers.ts rename to src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-document.handlers.ts diff --git a/src/Umbraco.Web.UI.Client/src/core/models/index.ts b/src/Umbraco.Web.UI.Client/src/core/models/index.ts index 75f7eb2922..05f6ffc35e 100644 --- a/src/Umbraco.Web.UI.Client/src/core/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/core/models/index.ts @@ -98,6 +98,7 @@ export interface ContentPropertyData { // Documents export interface DocumentDetails extends DocumentTreeItem { key: string; // TODO: Remove this when the backend is fixed + isTrashed: boolean; // TODO: remove only temp part of refactor properties: Array; data: Array; variants: Array; // TODO: define variant data From 1e42ea9d0b582de20e00b1a490111e7584d61e26 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 19:26:05 +0100 Subject: [PATCH 036/223] wire up media tree --- .../src/backoffice/backoffice.element.ts | 2 + .../trees/media/tree-media-data.context.ts | 27 --------- .../trees/media/tree-media.element.ts | 10 +--- .../src/core/mocks/browser-handlers.ts | 2 + .../src/core/mocks/data/document-type.data.ts | 2 +- .../src/core/mocks/data/media.data.ts | 22 ++++--- .../core/mocks/domains/tree-media.handlers.ts | 26 +++++++++ .../core/stores/document/document.store.ts | 2 +- .../src/core/stores/media/media.store.ts | 58 +++++++++++++++++++ 9 files changed, 105 insertions(+), 46 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media-data.context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-media.handlers.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/stores/media/media.store.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index bc6e006fa9..ce3b50a9c2 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -20,6 +20,7 @@ import { UmbNotificationService } from '../core/services/notification'; import { UmbDataTypeStore } from '../core/stores/data-type/data-type.store'; import { UmbDocumentTypeStore } from '../core/stores/document-type/document-type.store'; import { UmbDocumentStore } from '../core/stores/document/document.store'; +import { UmbMediaStore } from '../core/stores/media/media.store'; import { UmbNodeStore } from '../core/stores/node.store'; import { UmbSectionStore } from '../core/stores/section.store'; import { UmbEntityStore } from '../core/stores/entity.store'; @@ -70,6 +71,7 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this.provideContext('umbEntityStore', this._umbEntityStore); this.provideContext('umbDocumentStore', new UmbDocumentStore(this._umbEntityStore)); + this.provideContext('umbMediaStore', new UmbMediaStore(this._umbEntityStore)); this.provideContext('umbNodeStore', new UmbNodeStore(this._umbEntityStore)); this.provideContext('umbDataTypeStore', new UmbDataTypeStore(this._umbEntityStore)); this.provideContext('umbDocumentTypeStore', new UmbDocumentTypeStore(this._umbEntityStore)); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media-data.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media-data.context.ts deleted file mode 100644 index 9a0969cec7..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media-data.context.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { map } from 'rxjs'; -import { UmbTreeDataContextBase } from '../tree-data.context'; - -export class UmbTreeMediaDataContext extends UmbTreeDataContextBase { - public rootKey = 'c0858d71-52be-4bb2-822f-42fa0c9a1ea5'; - - public rootChanges() { - fetch(`/umbraco/backoffice/entities/media?parentKey=${this.rootKey}`) - .then((res) => res.json()) - .then((data) => { - this.entityStore.update(data); - }); - - return this.entityStore.items.pipe(map((items) => items.filter((item) => item.parentKey === this.rootKey))); - } - - public childrenChanges(key: string) { - // TODO: figure out url structure - fetch(`/umbraco/backoffice/entities/media?parentKey=${key}`) - .then((res) => res.json()) - .then((data) => { - this.entityStore.update(data); - }); - - return super.childrenChanges(key); - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.element.ts index ac9986a7ed..a255564c37 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.element.ts @@ -1,8 +1,6 @@ import { html } from 'lit'; import { customElement } from 'lit/decorators.js'; -import { UmbEntityStore } from '../../../core/stores/entity.store'; import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbTreeMediaDataContext } from './tree-media-data.context'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import '../shared/tree-navigator.element'; @@ -12,12 +10,8 @@ export class UmbTreeMediaElement extends UmbContextProviderMixin(UmbContextConsu constructor() { super(); - this.consumeContext('umbEntityStore', (entityStore: UmbEntityStore) => { - this._entityStore = entityStore; - if (!this._entityStore) return; - - this._treeDataContext = new UmbTreeMediaDataContext(this._entityStore); - this.provideContext('umbTreeDataContext', this._treeDataContext); + this.consumeContext('umbMediaStore', (store: UmbMediaStore) => { + this.provideContext('umbTreeStore', store); }); } 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 b002156305..ebecc63d6c 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 @@ -14,6 +14,7 @@ import { handlers as userGroupsHandlers } from './domains/user-groups.handlers'; // treeHandlers import { handlers as treeDocumentHandlers } from './domains/tree-document.handlers'; +import { handlers as treeMediaHandlers } from './domains/tree-media.handlers'; import { handlers as treeDataTypeHandlers } from './domains/tree-data-type.handlers'; import { handlers as treeDocumentTypeHandlers } from './domains/tree-document-type.handlers'; @@ -33,6 +34,7 @@ const handlers = [ ...userGroupsHandlers, ...treeDocumentHandlers, + ...treeMediaHandlers, ...treeDataTypeHandlers, ...treeDocumentTypeHandlers, ]; 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 0f23f2f541..3c921a3a15 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 @@ -48,7 +48,7 @@ class UmbDocumentTypeData extends UmbEntityData { } getTreeItem(keys: Array): Array { - return this.data.filter((item) => keys.includes(item.key ?? '')); + return this.data.filter((item) => keys.includes(item.key)); } } 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 40e3ae0dbb..8b2995852c 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 @@ -4,12 +4,14 @@ import type { MediaDetails } from '@umbraco-cms/models'; export const data: Array = [ { - key: 'f2f81a40-c989-4b6b-84e2-057cecd3adc1', name: 'Media 1', type: 'media', icon: 'picture', - parentKey: 'c0858d71-52be-4bb2-822f-42fa0c9a1ea5', hasChildren: false, + key: 'f2f81a40-c989-4b6b-84e2-057cecd3adc1', + isContainer: false, + parentKey: null, + noAccess: false, properties: [ { alias: 'myMediaHeadline', @@ -27,12 +29,14 @@ export const data: Array = [ variants: [], }, { - key: '69431027-8867-45bf-a93b-72bbdabfb177', - type: 'media', name: 'Media 2', + type: 'media', icon: 'picture', - parentKey: 'c0858d71-52be-4bb2-822f-42fa0c9a1ea5', hasChildren: false, + key: '69431027-8867-45bf-a93b-72bbdabfb177', + isContainer: false, + parentKey: null, + noAccess: false, properties: [ { alias: 'myMediaDescription', @@ -52,7 +56,7 @@ export const data: Array = [ ]; // Temp mocked database -class UmbDataTypeData extends UmbData { +class UmbMediaData extends UmbData { constructor() { super(data); } @@ -64,14 +68,14 @@ class UmbDataTypeData extends UmbData { } getTreeItemChildren(key: string): PagedContentTreeItem { - const items = this.data.filter((item) => item.key === null); + const items = this.data.filter((item) => item.key === key); const total = items.length; return { items, total }; } getTreeItem(keys: Array): Array { - return this.data.filter((item) => keys.includes(item.key ?? '')); + return this.data.filter((item) => keys.includes(item.key)); } } -export const umbDataTypeData = new UmbDataTypeData(); +export const umbMediaData = new UmbMediaData(); diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-media.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-media.handlers.ts new file mode 100644 index 0000000000..ccf1784a38 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-media.handlers.ts @@ -0,0 +1,26 @@ +import { rest } from 'msw'; +import { umbMediaData } from '../data/media.data'; + +// TODO: add schema +export const handlers = [ + rest.get('/umbraco/management/api/v1/tree/media/root', (req, res, ctx) => { + const response = umbMediaData.getTreeRoot(); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/tree/media/children', (req, res, ctx) => { + const key = req.params.key as string; + if (!key) return; + const response = umbMediaData.getTreeItemChildren(key); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/tree/media/item', (req, res, ctx) => { + const keys = req.params.keys as string; + if (!keys) return; + + const items = umbMediaData.getTreeItem(keys.split(',')); + + return res(ctx.status(200), ctx.json(items)); + }), +]; diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts index b96d0c8ead..6fcf0e9349 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts @@ -7,7 +7,7 @@ import { ApiError, DocumentResource, DocumentTreeItem, FolderTreeItem, ProblemDe /** * @export * @class UmbDocumentStore - * @extends {UmbDocumentStoreBase} + * @extends {UmbDocumentStoreBase} * @description - Data Store for Documents */ export class UmbDocumentStore extends UmbDataStoreBase { diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/media/media.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/media/media.store.ts new file mode 100644 index 0000000000..22e00120ec --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/stores/media/media.store.ts @@ -0,0 +1,58 @@ +import { map, Observable } from 'rxjs'; +import { UmbEntityStore } from '../entity.store'; +import { UmbDataStoreBase } from '../store'; +import type { MediaDetails } from '@umbraco-cms/models'; +import { ApiError, ContentTreeItem, MediaResource, ProblemDetails } from '@umbraco-cms/backend-api'; + +/** + * @export + * @class UmbMediaStore + * @extends {UmbMediaStoreBase} + * @description - Data Store for Media + */ +export class UmbMediaStore extends UmbDataStoreBase { + private _entityStore: UmbEntityStore; + + constructor(entityStore: UmbEntityStore) { + super(); + this._entityStore = entityStore; + } + + getTreeRoot(): Observable> { + MediaResource.getTreeMediaRoot({}).then( + (res) => { + this.update(res.items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null))); + } + + getTreeItemChildren(key: string): Observable> { + MediaResource.getTreeMediaChildren({ + parentKey: key, + }).then( + (res) => { + this.update(res.items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === key))); + } +} From 3ff98c6ffbd0a85e72aff2ef8aaa072bbabcb057 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 19:46:22 +0100 Subject: [PATCH 037/223] add member group tree --- .../src/backoffice/backoffice.element.ts | 2 + .../tree-member-groups-data.context.ts | 30 -------------- .../tree-member-groups.element.ts | 12 ++---- .../src/core/mocks/browser-handlers.ts | 2 + .../src/core/mocks/data/member-group.data.ts | 40 +++++++++++++++++++ .../domains/tree-member-group.handlers.ts | 19 +++++++++ .../src/core/models/index.ts | 5 +++ .../stores/member-group/member-group.store.ts | 38 ++++++++++++++++++ 8 files changed, 109 insertions(+), 39 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups-data.context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/data/member-group.data.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-member-group.handlers.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/stores/member-group/member-group.store.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index ce3b50a9c2..8650fc8b6a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -22,6 +22,7 @@ import { UmbDocumentTypeStore } from '../core/stores/document-type/document-type import { UmbDocumentStore } from '../core/stores/document/document.store'; import { UmbMediaStore } from '../core/stores/media/media.store'; import { UmbNodeStore } from '../core/stores/node.store'; +import { UmbMemberGroupStore } from '../core/stores/member-group/member-group.store'; import { UmbSectionStore } from '../core/stores/section.store'; import { UmbEntityStore } from '../core/stores/entity.store'; import { UmbUserStore } from '../core/stores/user/user.store'; @@ -77,6 +78,7 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this.provideContext('umbDocumentTypeStore', new UmbDocumentTypeStore(this._umbEntityStore)); this.provideContext('umbUserStore', new UmbUserStore(this._umbEntityStore)); this.provideContext('umbUserGroupStore', new UmbUserGroupStore(this._umbEntityStore)); + this.provideContext('umbMemberGroupStore', new UmbMemberGroupStore(this._umbEntityStore)); this.provideContext('umbNotificationService', new UmbNotificationService()); this.provideContext('umbModalService', new UmbModalService()); this.provideContext('umbSectionStore', new UmbSectionStore()); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups-data.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups-data.context.ts deleted file mode 100644 index ae61ae9484..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups-data.context.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { UmbTreeDataContextBase } from '../tree-data.context'; - -export class UmbTreeMemberGroupsDataContext extends UmbTreeDataContextBase { - public rootKey = '575645a5-0f25-4671-b9a0-be515096ad6b'; - - public rootChanges() { - const data = { - key: this.rootKey, - name: 'Member Groups', - hasChildren: true, - type: 'memberGroupRoot', - icon: 'folder', - parentKey: '', - isTrashed: false, - }; - - this.entityStore.update([data]); - return super.rootChanges(); - } - - public childrenChanges(key: string) { - // TODO: figure out url structure - fetch(`/umbraco/backoffice/entities/member-groups?parentKey=${key}`) - .then((res) => res.json()) - .then((data) => { - this.entityStore.update(data); - }); - return super.childrenChanges(key); - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.element.ts index 61f5cd0d94..be41286796 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.element.ts @@ -1,10 +1,8 @@ import { html } from 'lit'; import { customElement } from 'lit/decorators.js'; import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbEntityStore } from '../../../core/stores/entity.store'; -import { UmbTreeMemberGroupsDataContext } from './tree-member-groups-data.context'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; - +import { UmbMemberGroupStore } from 'src/core/stores/member-group/member-group.store'; import '../shared/tree-navigator.element'; @customElement('umb-tree-member-groups') @@ -12,12 +10,8 @@ export class UmbTreeMemberGroups extends UmbContextProviderMixin(UmbContextConsu constructor() { super(); - this.consumeContext('umbEntityStore', (entityStore: UmbEntityStore) => { - this._entityStore = entityStore; - if (!this._entityStore || !this.tree) return; - - this._treeDataContext = new UmbTreeMemberGroupsDataContext(this._entityStore); - this.provideContext('umbTreeDataContext', this._treeDataContext); + this.consumeContext('umbMemberGroupStore', (store: UmbMemberGroupStore) => { + this.provideContext('umbTreeStore', store); }); } 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 ebecc63d6c..40864bf2c1 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 @@ -17,6 +17,7 @@ import { handlers as treeDocumentHandlers } from './domains/tree-document.handle import { handlers as treeMediaHandlers } from './domains/tree-media.handlers'; import { handlers as treeDataTypeHandlers } from './domains/tree-data-type.handlers'; import { handlers as treeDocumentTypeHandlers } from './domains/tree-document-type.handlers'; +import { handlers as treeMemberGroupHandlers } from './domains/tree-member-group.handlers'; const handlers = [ serverHandlers.serverVersionHandler, @@ -37,6 +38,7 @@ const handlers = [ ...treeMediaHandlers, ...treeDataTypeHandlers, ...treeDocumentTypeHandlers, + ...treeMemberGroupHandlers, ]; switch (import.meta.env.VITE_UMBRACO_INSTALL_STATUS) { diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/member-group.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/member-group.data.ts new file mode 100644 index 0000000000..b3c8437545 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/member-group.data.ts @@ -0,0 +1,40 @@ +import { UmbEntityData } from './entity.data'; +import { EntityTreeItem, PagedEntityTreeItem } from '@umbraco-cms/backend-api'; +import type { MemberGroupDetails } from '@umbraco-cms/models'; + +export const data: Array = [ + { + name: 'Member Group 1', + type: 'member-group', + icon: 'umb:document', + hasChildren: false, + key: '76708ccd-4179-464c-b694-6969149dd9f9', + isContainer: false, + parentKey: null, + }, +]; + +// Temp mocked database +class UmbMemberGroupData extends UmbEntityData { + constructor() { + super(data); + } + + getTreeRoot(): PagedEntityTreeItem { + const items = this.data.filter((item) => item.parentKey === null); + const total = items.length; + return { items, total }; + } + + getTreeItemChildren(key: string): PagedEntityTreeItem { + const items = this.data.filter((item) => item.parentKey === key); + const total = items.length; + return { items, total }; + } + + getTreeItem(keys: Array): Array { + return this.data.filter((item) => keys.includes(item.key)); + } +} + +export const umbMemberGroupData = new UmbMemberGroupData(); diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-member-group.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-member-group.handlers.ts new file mode 100644 index 0000000000..3d96c7eaff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-member-group.handlers.ts @@ -0,0 +1,19 @@ +import { rest } from 'msw'; +import { umbMemberGroupData } from '../data/member-group.data'; + +// TODO: add schema +export const handlers = [ + rest.get('/umbraco/management/api/v1/tree/member-group/root', (req, res, ctx) => { + const response = umbMemberGroupData.getTreeRoot(); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/tree/member-group/item', (req, res, ctx) => { + const keys = req.params.keys as string; + if (!keys) return; + + const items = umbMemberGroupData.getTreeItem(keys.split(',')); + + return res(ctx.status(200), ctx.json(items)); + }), +]; diff --git a/src/Umbraco.Web.UI.Client/src/core/models/index.ts b/src/Umbraco.Web.UI.Client/src/core/models/index.ts index 05f6ffc35e..3436b2df0f 100644 --- a/src/Umbraco.Web.UI.Client/src/core/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/core/models/index.ts @@ -121,3 +121,8 @@ export interface MediaTypeDetails extends EntityTreeItem { alias: string; properties: []; } + +// Member Groups +export interface MemberGroupDetails extends EntityTreeItem { + key: string; // TODO: Remove this when the backend is fixed +} diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/member-group/member-group.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/member-group/member-group.store.ts new file mode 100644 index 0000000000..5edb641b70 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/stores/member-group/member-group.store.ts @@ -0,0 +1,38 @@ +import { map, Observable } from 'rxjs'; +import { UmbEntityStore } from '../entity.store'; +import { UmbDataStoreBase } from '../store'; +import { ApiError, EntityTreeItem, MemberGroupResource, ProblemDetails } from '@umbraco-cms/backend-api'; +import type { MemberGroupDetails } from '@umbraco-cms/models'; + +/** + * @export + * @class UmbMemberGroupStore + * @extends {UmbDataStoreBase} + * @description - Data Store for Member Groups + */ +export class UmbMemberGroupStore extends UmbDataStoreBase { + private _entityStore: UmbEntityStore; + + constructor(entityStore: UmbEntityStore) { + super(); + this._entityStore = entityStore; + } + + getTreeRoot(): Observable> { + MemberGroupResource.getTreeMemberGroupRoot({}).then( + (res) => { + this.update(res.items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null))); + } +} From 58bb3dcfb92422c2aedeb93d4425853ff380155e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 19:58:42 +0100 Subject: [PATCH 038/223] remove member tree --- .../src/backoffice/trees/manifests.ts | 14 +------- .../trees/members/tree-members.context.ts | 29 --------------- .../trees/members/tree-members.element.ts | 35 ------------------- 3 files changed, 1 insertion(+), 77 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.context.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts index 9d13a0fad3..1cc64efd9c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts @@ -37,22 +37,10 @@ export const manifests: Array> = [ sections: ['Umb.Section.Settings'], }, }, - { - type: 'tree', - alias: 'Umb.Tree.Members', - name: 'Members Tree', - loader: () => import('./members/tree-members.element'), - weight: 0, - meta: { - label: 'Members', - icon: 'umb:folder', - sections: ['Umb.Section.Members'], - }, - }, { type: 'tree', alias: 'Umb.Tree.MemberGroups', - name: 'Members Groups Tree', + name: 'Member Groups Tree', loader: () => import('./member-groups/tree-member-groups.element'), weight: 1, meta: { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.context.ts deleted file mode 100644 index 11be2dbc3a..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.context.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { UmbTreeDataContextBase } from '../tree-data.context'; - -export class UmbTreeMembersDataContext extends UmbTreeDataContextBase { - public rootKey = '8f974b62-392b-4ddd-908c-03c2e03ab1a6'; - - public rootChanges() { - const data = { - key: this.rootKey, - parentKey: '', - name: 'Members', - hasChildren: true, - type: 'member', - icon: 'folder', - isTrashed: false, - }; - this.entityStore.update([data]); - return super.rootChanges(); - } - - public childrenChanges(key: string) { - // TODO: figure out url structure - fetch(`/umbraco/backoffice/entities/members?parentKey=${key}`) - .then((res) => res.json()) - .then((data) => { - this.entityStore.update(data); - }); - return super.childrenChanges(key); - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.element.ts deleted file mode 100644 index 962f9aaa3a..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.element.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { html } from 'lit'; -import { customElement } from 'lit/decorators.js'; -import { UmbEntityStore } from '../../../core/stores/entity.store'; -import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbTreeMembersDataContext } from './tree-members.context'; -import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; - -import '../shared/tree-navigator.element'; - -@customElement('umb-tree-members') -export class UmbTreeMembers extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { - constructor() { - super(); - - this.consumeContext('umbEntityStore', (entityStore: UmbEntityStore) => { - this._entityStore = entityStore; - if (!this._entityStore || !this.tree) return; - - this._treeDataContext = new UmbTreeMembersDataContext(this._entityStore); - this.provideContext('umbTreeDataContext', this._treeDataContext); - }); - } - - render() { - return html``; - } -} - -export default UmbTreeMembers; - -declare global { - interface HTMLElementTagNameMap { - 'umb-tree-members': UmbTreeMembers; - } -} From 08c6b482a31cb77cd398fa70895dac9ec31187df Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 20:17:48 +0100 Subject: [PATCH 039/223] add member type tree + editor scaffold --- .../src/backoffice/backoffice.element.ts | 2 + .../src/backoffice/editors/manifests.ts | 9 +++++ .../member-type/editor-member-type.element.ts | 36 ++++++++++++++++++ .../src/backoffice/trees/manifests.ts | 28 ++++++++++---- .../member-types/tree-member-types.element.ts | 30 +++++++++++++++ .../src/core/mocks/browser-handlers.ts | 2 + .../src/core/mocks/data/member-type.data.ts | 23 ++++++----- .../domains/tree-member-type.handlers.ts | 19 ++++++++++ .../src/core/models/index.ts | 1 + .../stores/member-type/member-type.store.ts | 38 +++++++++++++++++++ 10 files changed, 171 insertions(+), 17 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/editors/member-type/editor-member-type.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/member-types/tree-member-types.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-member-type.handlers.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/stores/member-type/member-type.store.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index 8650fc8b6a..b322f6b2d7 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -19,6 +19,7 @@ import { UmbModalService } from '../core/services/modal'; import { UmbNotificationService } from '../core/services/notification'; import { UmbDataTypeStore } from '../core/stores/data-type/data-type.store'; import { UmbDocumentTypeStore } from '../core/stores/document-type/document-type.store'; +import { UmbMemberTypeStore } from '../core/stores/member-type/member-type.store'; import { UmbDocumentStore } from '../core/stores/document/document.store'; import { UmbMediaStore } from '../core/stores/media/media.store'; import { UmbNodeStore } from '../core/stores/node.store'; @@ -76,6 +77,7 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this.provideContext('umbNodeStore', new UmbNodeStore(this._umbEntityStore)); this.provideContext('umbDataTypeStore', new UmbDataTypeStore(this._umbEntityStore)); this.provideContext('umbDocumentTypeStore', new UmbDocumentTypeStore(this._umbEntityStore)); + this.provideContext('umbMemberTypeStore', new UmbMemberTypeStore(this._umbEntityStore)); this.provideContext('umbUserStore', new UmbUserStore(this._umbEntityStore)); this.provideContext('umbUserGroupStore', new UmbUserGroupStore(this._umbEntityStore)); this.provideContext('umbMemberGroupStore', new UmbMemberGroupStore(this._umbEntityStore)); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/manifests.ts index 46b9711134..8e4864ca3a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/manifests.ts @@ -37,6 +37,15 @@ export const manifests: Array> = [ entityType: 'document-type', }, }, + { + type: 'editor', + alias: 'Umb.Editor.MemberType', + name: 'Member Type Editor', + loader: () => import('./member-type/editor-member-type.element'), + meta: { + entityType: 'member-type', + }, + }, { type: 'editor', alias: 'Umb.Editor.Extensions', diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/member-type/editor-member-type.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/member-type/editor-member-type.element.ts new file mode 100644 index 0000000000..95dc175aed --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/member-type/editor-member-type.element.ts @@ -0,0 +1,36 @@ +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { css, html, LitElement } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; + +import '../shared/editor-entity-layout/editor-entity-layout.element'; + +@customElement('umb-editor-member-type') +export class UmbEditorMemberTypeElement extends LitElement { + static styles = [ + UUITextStyles, + css` + :host { + display: block; + width: 100%; + height: 100%; + } + `, + ]; + + @property() + id!: string; + + render() { + return html` + Member Type Editor + `; + } +} + +export default UmbEditorMemberTypeElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-editor-member-type': UmbEditorMemberTypeElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts index 1cc64efd9c..1c9085765c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts @@ -15,24 +15,36 @@ export const manifests: Array> = [ }, { type: 'tree', - alias: 'Umb.Tree.DataTypes', - name: 'Data Types Tree', - loader: () => import('./data-types/tree-data-types.element'), + alias: 'Umb.Tree.DocumentTypes', + name: 'Document Types Tree', + loader: () => import('./document-types/tree-document-types.element'), weight: 300, meta: { - label: 'Data Types', + label: 'Document Types', icon: 'umb:folder', sections: ['Umb.Section.Settings'], }, }, { type: 'tree', - alias: 'Umb.Tree.DocumentTypes', - name: 'Document Types Tree', - loader: () => import('./document-types/tree-document-types.element'), + alias: 'Umb.Tree.MemberTypes', + name: 'Member Types Tree', + loader: () => import('./member-types/tree-member-types.element'), weight: 200, meta: { - label: 'Document Types', + label: 'Member Types', + icon: 'umb:folder', + sections: ['Umb.Section.Settings'], + }, + }, + { + type: 'tree', + alias: 'Umb.Tree.DataTypes', + name: 'Data Types Tree', + loader: () => import('./data-types/tree-data-types.element'), + weight: 100, + meta: { + label: 'Data Types', icon: 'umb:folder', sections: ['Umb.Section.Settings'], }, diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-types/tree-member-types.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-types/tree-member-types.element.ts new file mode 100644 index 0000000000..f36ca1eb4b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-types/tree-member-types.element.ts @@ -0,0 +1,30 @@ +import { html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { UmbTreeBase } from '../shared/tree-base.element'; +import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; +import { UmbMemberTypeStore } from 'src/core/stores/member-type/member-type.store'; + +import '../shared/tree-navigator.element'; + +@customElement('umb-tree-member-types') +export class UmbTreeMemberTypes extends UmbContextConsumerMixin(UmbContextProviderMixin(UmbTreeBase)) { + constructor() { + super(); + + this.consumeContext('umbMemberTypeStore', (store: UmbMemberTypeStore) => { + this.provideContext('umbTreeStore', store); + }); + } + + render() { + return html``; + } +} + +export default UmbTreeMemberTypes; + +declare global { + interface HTMLElementTagNameMap { + 'umb-tree-member-types': UmbTreeMemberTypes; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/browser-handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/browser-handlers.ts index 40864bf2c1..b7807c86d8 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 @@ -17,6 +17,7 @@ import { handlers as treeDocumentHandlers } from './domains/tree-document.handle import { handlers as treeMediaHandlers } from './domains/tree-media.handlers'; import { handlers as treeDataTypeHandlers } from './domains/tree-data-type.handlers'; import { handlers as treeDocumentTypeHandlers } from './domains/tree-document-type.handlers'; +import { handlers as treeMemberTypeHandlers } from './domains/tree-member-type.handlers'; import { handlers as treeMemberGroupHandlers } from './domains/tree-member-group.handlers'; const handlers = [ @@ -38,6 +39,7 @@ const handlers = [ ...treeMediaHandlers, ...treeDataTypeHandlers, ...treeDocumentTypeHandlers, + ...treeMemberTypeHandlers, ...treeMemberGroupHandlers, ]; diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/member-type.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/member-type.data.ts index 1c010558d3..2b8f4bbd9c 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/member-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/member-type.data.ts @@ -1,16 +1,17 @@ import { UmbData } from './data'; -import { EntityTreeItem } from '@umbraco-cms/backend-api'; +import { EntityTreeItem, PagedEntityTreeItem } from '@umbraco-cms/backend-api'; import type { MemberTypeDetails } from '@umbraco-cms/models'; export const data: Array = [ { - key: 'd59be02f-1df9-4228-aa1e-01917d806cda', - isContainer: false, - parentKey: null, - name: 'Member', + name: 'Member Type 1', type: 'member-type', icon: 'icon-user', hasChildren: false, + key: 'd59be02f-1df9-4228-aa1e-01917d806cda', + isContainer: false, + parentKey: null, + isTrashed: false, alias: 'memberType1', properties: [], }, @@ -22,12 +23,16 @@ class UmbMemberTypeData extends UmbData { super(data); } - getTreeRoot(): Array { - return this.data.filter((item) => item.parentKey === null); + getTreeRoot(): PagedEntityTreeItem { + const items = this.data.filter((item) => item.parentKey === null); + const total = items.length; + return { items, total }; } - getTreeItemChildren(key: string): Array { - return this.data.filter((item) => item.parentKey === key); + getTreeItemChildren(key: string): PagedEntityTreeItem { + const items = this.data.filter((item) => item.parentKey === key); + const total = items.length; + return { items, total }; } getTreeItem(keys: Array): Array { diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-member-type.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-member-type.handlers.ts new file mode 100644 index 0000000000..21acb5d242 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-member-type.handlers.ts @@ -0,0 +1,19 @@ +import { rest } from 'msw'; +import { umbMemberTypeData } from '../data/member-type.data'; + +// TODO: add schema +export const handlers = [ + rest.get('/umbraco/management/api/v1/tree/member-type/root', (req, res, ctx) => { + const response = umbMemberTypeData.getTreeRoot(); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/tree/member-type/item', (req, res, ctx) => { + const keys = req.params.keys as string; + if (!keys) return; + + const items = umbMemberTypeData.getTreeItem(keys.split(',')); + + return res(ctx.status(200), ctx.json(items)); + }), +]; diff --git a/src/Umbraco.Web.UI.Client/src/core/models/index.ts b/src/Umbraco.Web.UI.Client/src/core/models/index.ts index 3436b2df0f..66e01b1e7f 100644 --- a/src/Umbraco.Web.UI.Client/src/core/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/core/models/index.ts @@ -78,6 +78,7 @@ export interface DocumentTypeDetails extends DocumentTypeTreeItem { export interface MemberTypeDetails extends EntityTreeItem { key: string; // TODO: Remove this when the backend is fixed + isTrashed: boolean; // TODO: remove only temp part of refactor alias: string; properties: []; } diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/member-type/member-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/member-type/member-type.store.ts new file mode 100644 index 0000000000..cf83a12119 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/stores/member-type/member-type.store.ts @@ -0,0 +1,38 @@ +import { map, Observable } from 'rxjs'; +import { UmbEntityStore } from '../entity.store'; +import { UmbDataStoreBase } from '../store'; +import { MemberTypeResource, ApiError, EntityTreeItem, ProblemDetails } from '@umbraco-cms/backend-api'; +import type { MemberTypeDetails } from '@umbraco-cms/models'; + +/** + * @export + * @class UmbMemberTypeStore + * @extends {UmbDataStoreBase} + * @description - Data Store for Member Types + */ +export class UmbMemberTypeStore extends UmbDataStoreBase { + private _entityStore: UmbEntityStore; + + constructor(entityStore: UmbEntityStore) { + super(); + this._entityStore = entityStore; + } + + getTreeRoot(): Observable> { + MemberTypeResource.getTreeMemberTypeRoot({}).then( + (res) => { + this.update(res.items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null))); + } +} From 8a41271063d323b4adc1f1d3856eee7972adfcf8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 20:19:05 +0100 Subject: [PATCH 040/223] fix mocked document type data --- .../src/core/mocks/data/document-type.data.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 3c921a3a15..0a7f84a80e 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 @@ -5,7 +5,7 @@ import type { DocumentTypeDetails } from '@umbraco-cms/models'; export const data: Array = [ { name: 'Document Type 1', - type: 'documentType', + type: 'document-type', hasChildren: false, key: 'd81c7957-153c-4b5a-aa6f-b434a4964624', isContainer: false, @@ -19,7 +19,7 @@ export const data: Array = [ }, { name: 'Document Type 2', - type: 'documentType', + type: 'document-type', hasChildren: false, key: 'a99e4018-3ffc-486b-aa76-eecea9593d17', isContainer: false, From 4b4c01dff875a8540354866e5c74698857d0744c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 21:03:57 +0100 Subject: [PATCH 041/223] add media type store, tree, and editor --- .../src/backoffice/backoffice.element.ts | 2 + .../src/backoffice/editors/manifests.ts | 9 +++ .../media-type/editor-media-type.element.ts | 34 +++++++++++ .../src/backoffice/trees/manifests.ts | 16 ++++- .../media-types/tree-media-types.element.ts | 30 ++++++++++ .../src/core/mocks/browser-handlers.ts | 2 + .../src/core/mocks/data/media-type.data.ts | 57 ++++++++++++++++++ .../mocks/domains/tree-media-type.handlers.ts | 26 +++++++++ .../src/core/models/index.ts | 6 +- .../stores/media-type/media-type.store.ts | 58 +++++++++++++++++++ 10 files changed, 237 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/editors/media-type/editor-media-type.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/media-types/tree-media-types.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/data/media-type.data.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-media-type.handlers.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/stores/media-type/media-type.store.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index b322f6b2d7..3636af276c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -19,6 +19,7 @@ import { UmbModalService } from '../core/services/modal'; import { UmbNotificationService } from '../core/services/notification'; import { UmbDataTypeStore } from '../core/stores/data-type/data-type.store'; import { UmbDocumentTypeStore } from '../core/stores/document-type/document-type.store'; +import { UmbMediaTypeStore } from '../core/stores/media-type/media-type.store'; import { UmbMemberTypeStore } from '../core/stores/member-type/member-type.store'; import { UmbDocumentStore } from '../core/stores/document/document.store'; import { UmbMediaStore } from '../core/stores/media/media.store'; @@ -77,6 +78,7 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this.provideContext('umbNodeStore', new UmbNodeStore(this._umbEntityStore)); this.provideContext('umbDataTypeStore', new UmbDataTypeStore(this._umbEntityStore)); this.provideContext('umbDocumentTypeStore', new UmbDocumentTypeStore(this._umbEntityStore)); + this.provideContext('umbMediaTypeStore', new UmbMediaTypeStore(this._umbEntityStore)); this.provideContext('umbMemberTypeStore', new UmbMemberTypeStore(this._umbEntityStore)); this.provideContext('umbUserStore', new UmbUserStore(this._umbEntityStore)); this.provideContext('umbUserGroupStore', new UmbUserGroupStore(this._umbEntityStore)); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/manifests.ts index 8e4864ca3a..db8fe91fab 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/manifests.ts @@ -37,6 +37,15 @@ export const manifests: Array> = [ entityType: 'document-type', }, }, + { + type: 'editor', + alias: 'Umb.Editor.MediaType', + name: 'Media Type Editor', + loader: () => import('./media-type/editor-media-type.element'), + meta: { + entityType: 'media-type', + }, + }, { type: 'editor', alias: 'Umb.Editor.MemberType', diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/media-type/editor-media-type.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/media-type/editor-media-type.element.ts new file mode 100644 index 0000000000..8f10ec3f5f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/media-type/editor-media-type.element.ts @@ -0,0 +1,34 @@ +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { css, html, LitElement } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; + +import '../shared/editor-entity-layout/editor-entity-layout.element'; + +@customElement('umb-editor-media-type') +export class UmbEditorMediaTypeElement extends LitElement { + static styles = [ + UUITextStyles, + css` + :host { + display: block; + width: 100%; + height: 100%; + } + `, + ]; + + @property() + id!: string; + + render() { + return html` Media Type Editor `; + } +} + +export default UmbEditorMediaTypeElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-editor-media-type': UmbEditorMediaTypeElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts index 1c9085765c..99a5e7fed5 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/manifests.ts @@ -6,7 +6,7 @@ export const manifests: Array> = [ alias: 'Umb.Tree.Extensions', name: 'Extensions Tree', loader: () => import('./extensions/tree-extensions.element'), - weight: 400, + weight: 500, meta: { label: 'Extensions', icon: 'umb:favorite', @@ -18,13 +18,25 @@ export const manifests: Array> = [ alias: 'Umb.Tree.DocumentTypes', name: 'Document Types Tree', loader: () => import('./document-types/tree-document-types.element'), - weight: 300, + weight: 400, meta: { label: 'Document Types', icon: 'umb:folder', sections: ['Umb.Section.Settings'], }, }, + { + type: 'tree', + alias: 'Umb.Tree.MediaTypes', + name: 'Media Types Tree', + loader: () => import('./media-types/tree-media-types.element'), + weight: 300, + meta: { + label: 'Media Types', + icon: 'umb:folder', + sections: ['Umb.Section.Settings'], + }, + }, { type: 'tree', alias: 'Umb.Tree.MemberTypes', diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media-types/tree-media-types.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media-types/tree-media-types.element.ts new file mode 100644 index 0000000000..a98e183ac0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media-types/tree-media-types.element.ts @@ -0,0 +1,30 @@ +import { html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { UmbTreeBase } from '../shared/tree-base.element'; +import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; +import { UmbMediaTypeStore } from 'src/core/stores/media-type/media-type.store'; + +import '../shared/tree-navigator.element'; + +@customElement('umb-tree-media-types') +export class UmbTreeMediaTypes extends UmbContextConsumerMixin(UmbContextProviderMixin(UmbTreeBase)) { + constructor() { + super(); + + this.consumeContext('umbMediaTypeStore', (store: UmbMediaTypeStore) => { + this.provideContext('umbTreeStore', store); + }); + } + + render() { + return html``; + } +} + +export default UmbTreeMediaTypes; + +declare global { + interface HTMLElementTagNameMap { + 'umb-tree-media-types': UmbTreeMediaTypes; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/browser-handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/browser-handlers.ts index b7807c86d8..d3553d0f34 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 @@ -17,6 +17,7 @@ import { handlers as treeDocumentHandlers } from './domains/tree-document.handle import { handlers as treeMediaHandlers } from './domains/tree-media.handlers'; import { handlers as treeDataTypeHandlers } from './domains/tree-data-type.handlers'; import { handlers as treeDocumentTypeHandlers } from './domains/tree-document-type.handlers'; +import { handlers as treeMediaTypeHandlers } from './domains/tree-media-type.handlers'; import { handlers as treeMemberTypeHandlers } from './domains/tree-member-type.handlers'; import { handlers as treeMemberGroupHandlers } from './domains/tree-member-group.handlers'; @@ -39,6 +40,7 @@ const handlers = [ ...treeMediaHandlers, ...treeDataTypeHandlers, ...treeDocumentTypeHandlers, + ...treeMediaTypeHandlers, ...treeMemberTypeHandlers, ...treeMemberGroupHandlers, ]; diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/media-type.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/media-type.data.ts new file mode 100644 index 0000000000..7db2b8414e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/media-type.data.ts @@ -0,0 +1,57 @@ +import { UmbEntityData } from './entity.data'; +import { FolderTreeItem, PagedFolderTreeItem } from '@umbraco-cms/backend-api'; +import type { MediaTypeDetails } from '@umbraco-cms/models'; + +export const data: Array = [ + { + name: 'Media Type 1', + type: 'media-type', + hasChildren: false, + key: 'c5159663-eb82-43ee-bd23-e42dc5e71db6', + isContainer: false, + parentKey: null, + isFolder: false, + isTrashed: false, + icon: '', + alias: 'mediaType1', + properties: [], + }, + { + name: 'Media Type 2', + type: 'media-type', + hasChildren: false, + key: '22da1b0b-c310-4730-9912-c30b3eb9802e', + isContainer: false, + parentKey: null, + isFolder: false, + isTrashed: false, + icon: '', + alias: 'mediaType2', + properties: [], + }, +]; + +// Temp mocked database +class UmbMediaTypeData extends UmbEntityData { + constructor() { + super(data); + } + + getTreeRoot(): PagedFolderTreeItem { + const items = this.data.filter((item) => item.parentKey === null); + const total = items.length; + return { items, total }; + } + + getTreeItemChildren(key: string): PagedFolderTreeItem { + const items = this.data.filter((item) => item.parentKey === key); + const total = items.length; + return { items, total }; + } + + getTreeItem(keys: Array): Array { + return this.data.filter((item) => keys.includes(item.key ?? '')); + } +} + +export const umbMediaTypeData = new UmbMediaTypeData(); diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-media-type.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-media-type.handlers.ts new file mode 100644 index 0000000000..87d6d0d463 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-media-type.handlers.ts @@ -0,0 +1,26 @@ +import { rest } from 'msw'; +import { umbMediaTypeData } from '../data/media-type.data'; + +// TODO: add schema +export const handlers = [ + rest.get('/umbraco/management/api/v1/tree/media-type/root', (req, res, ctx) => { + const response = umbMediaTypeData.getTreeRoot(); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/tree/media-type/children', (req, res, ctx) => { + const key = req.params.key as string; + if (!key) return; + + const response = umbMediaTypeData.getTreeItemChildren(key); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get('/umbraco/management/api/v1/tree/media-type/item', (req, res, ctx) => { + const keys = req.params.keys as string; + if (!keys) return; + + const items = umbMediaTypeData.getTreeItem(keys.split(',')); + return res(ctx.status(200), ctx.json(items)); + }), +]; diff --git a/src/Umbraco.Web.UI.Client/src/core/models/index.ts b/src/Umbraco.Web.UI.Client/src/core/models/index.ts index 66e01b1e7f..1b5d4566ba 100644 --- a/src/Umbraco.Web.UI.Client/src/core/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/core/models/index.ts @@ -5,6 +5,7 @@ import { DocumentTypeTreeItem, EntityTreeItem, FolderTreeItem, + PagedFolderTreeItem, } from '@umbraco-cms/backend-api'; // Extension Manifests @@ -109,6 +110,7 @@ export interface DocumentDetails extends DocumentTreeItem { // Media export interface MediaDetails extends ContentTreeItem { key: string; // TODO: Remove this when the backend is fixed + isTrashed: boolean; // TODO: remove only temp part of refactor properties: Array; data: Array; variants: Array; // TODO: define variant data @@ -117,8 +119,9 @@ export interface MediaDetails extends ContentTreeItem { // Media Types -export interface MediaTypeDetails extends EntityTreeItem { +export interface MediaTypeDetails extends FolderTreeItem { key: string; // TODO: Remove this when the backend is fixed + isTrashed: boolean; // TODO: remove only temp part of refactor alias: string; properties: []; } @@ -126,4 +129,5 @@ export interface MediaTypeDetails extends EntityTreeItem { // Member Groups export interface MemberGroupDetails extends EntityTreeItem { key: string; // TODO: Remove this when the backend is fixed + isTrashed: boolean; // TODO: remove only temp part of refactor } diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/media-type/media-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/media-type/media-type.store.ts new file mode 100644 index 0000000000..b0aed3a6ba --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/stores/media-type/media-type.store.ts @@ -0,0 +1,58 @@ +import { map, Observable } from 'rxjs'; +import { UmbEntityStore } from '../entity.store'; +import { UmbDataStoreBase } from '../store'; +import { MediaTypeResource, ApiError, ProblemDetails, PagedFolderTreeItem } from '@umbraco-cms/backend-api'; +import type { MediaTypeDetails } from '@umbraco-cms/models'; + +/** + * @export + * @class UmbMediaTypeStore + * @extends {UmbDataStoreBase} + * @description - Data Store for Media Types + */ +export class UmbMediaTypeStore extends UmbDataStoreBase { + private _entityStore: UmbEntityStore; + + constructor(entityStore: UmbEntityStore) { + super(); + this._entityStore = entityStore; + } + + getTreeRoot(): Observable> { + MediaTypeResource.getTreeMediaTypeRoot({}).then( + (res) => { + this.update(res.items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null))); + } + + getTreeItemChildren(key: string): Observable> { + MediaTypeResource.getTreeMediaTypeChildren({ + parentKey: key, + }).then( + (res) => { + this.update(res.items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === key))); + } +} From e3d5d1eb1b0d24608c189751ff8667470f72c11b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 17 Nov 2022 21:09:57 +0100 Subject: [PATCH 042/223] remove dependency on entity store --- .../src/backoffice/backoffice.element.ts | 14 +++++++------- .../src/core/stores/data-type/data-type.store.ts | 8 -------- .../stores/document-type/document-type.store.ts | 8 -------- .../src/core/stores/document/document.store.ts | 8 -------- .../src/core/stores/media-type/media-type.store.ts | 8 -------- .../src/core/stores/media/media.store.ts | 8 -------- .../core/stores/member-group/member-group.store.ts | 8 -------- .../core/stores/member-type/member-type.store.ts | 8 -------- 8 files changed, 7 insertions(+), 63 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index 3636af276c..e2a2f7b936 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -73,16 +73,16 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this._umbIconRegistry.attach(this); this.provideContext('umbEntityStore', this._umbEntityStore); - this.provideContext('umbDocumentStore', new UmbDocumentStore(this._umbEntityStore)); - this.provideContext('umbMediaStore', new UmbMediaStore(this._umbEntityStore)); + this.provideContext('umbDocumentStore', new UmbDocumentStore()); + this.provideContext('umbMediaStore', new UmbMediaStore()); this.provideContext('umbNodeStore', new UmbNodeStore(this._umbEntityStore)); - this.provideContext('umbDataTypeStore', new UmbDataTypeStore(this._umbEntityStore)); - this.provideContext('umbDocumentTypeStore', new UmbDocumentTypeStore(this._umbEntityStore)); - this.provideContext('umbMediaTypeStore', new UmbMediaTypeStore(this._umbEntityStore)); - this.provideContext('umbMemberTypeStore', new UmbMemberTypeStore(this._umbEntityStore)); + this.provideContext('umbDataTypeStore', new UmbDataTypeStore()); + this.provideContext('umbDocumentTypeStore', new UmbDocumentTypeStore()); + this.provideContext('umbMediaTypeStore', new UmbMediaTypeStore()); + this.provideContext('umbMemberTypeStore', new UmbMemberTypeStore()); this.provideContext('umbUserStore', new UmbUserStore(this._umbEntityStore)); this.provideContext('umbUserGroupStore', new UmbUserGroupStore(this._umbEntityStore)); - this.provideContext('umbMemberGroupStore', new UmbMemberGroupStore(this._umbEntityStore)); + this.provideContext('umbMemberGroupStore', new UmbMemberGroupStore()); this.provideContext('umbNotificationService', new UmbNotificationService()); this.provideContext('umbModalService', new UmbModalService()); this.provideContext('umbSectionStore', new UmbSectionStore()); diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts index da562432ce..89027c06b0 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts @@ -1,5 +1,4 @@ import { map, Observable } from 'rxjs'; -import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; import type { DataTypeDetails } from '@umbraco-cms/models'; import { ApiError, DataTypeResource, FolderTreeItem, ProblemDetails } from '@umbraco-cms/backend-api'; @@ -11,13 +10,6 @@ import { ApiError, DataTypeResource, FolderTreeItem, ProblemDetails } from '@umb * @description - Data Store for Data Types */ export class UmbDataTypeStore extends UmbDataStoreBase { - private _entityStore: UmbEntityStore; - - constructor(entityStore: UmbEntityStore) { - super(); - this._entityStore = entityStore; - } - /** * @description - Request a Data Type by key. The Data Type is added to the store and is returned as an Observable. * @param {string} key diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts index 00cf7f5857..a3de4148f0 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts @@ -1,5 +1,4 @@ import { map, Observable } from 'rxjs'; -import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; import { ApiError, DocumentTypeResource, DocumentTypeTreeItem, ProblemDetails } from '@umbraco-cms/backend-api'; import type { DocumentTypeDetails } from '@umbraco-cms/models'; @@ -11,13 +10,6 @@ import type { DocumentTypeDetails } from '@umbraco-cms/models'; * @description - Data Store for Document Types */ export class UmbDocumentTypeStore extends UmbDataStoreBase { - private _entityStore: UmbEntityStore; - - constructor(entityStore: UmbEntityStore) { - super(); - this._entityStore = entityStore; - } - getByKey(key: string): Observable { // TODO: use Fetcher API. // TODO: only fetch if the data type is not in the store? diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts index 6fcf0e9349..32acdeb94d 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts @@ -1,5 +1,4 @@ import { map, Observable } from 'rxjs'; -import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; import type { DocumentDetails } from '@umbraco-cms/models'; import { ApiError, DocumentResource, DocumentTreeItem, FolderTreeItem, ProblemDetails } from '@umbraco-cms/backend-api'; @@ -11,13 +10,6 @@ import { ApiError, DocumentResource, DocumentTreeItem, FolderTreeItem, ProblemDe * @description - Data Store for Documents */ export class UmbDocumentStore extends UmbDataStoreBase { - private _entityStore: UmbEntityStore; - - constructor(entityStore: UmbEntityStore) { - super(); - this._entityStore = entityStore; - } - getTreeRoot(): Observable> { DocumentResource.getTreeDocumentRoot({}).then( (res) => { diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/media-type/media-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/media-type/media-type.store.ts index b0aed3a6ba..6c826bd32d 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/media-type/media-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/media-type/media-type.store.ts @@ -1,5 +1,4 @@ import { map, Observable } from 'rxjs'; -import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; import { MediaTypeResource, ApiError, ProblemDetails, PagedFolderTreeItem } from '@umbraco-cms/backend-api'; import type { MediaTypeDetails } from '@umbraco-cms/models'; @@ -11,13 +10,6 @@ import type { MediaTypeDetails } from '@umbraco-cms/models'; * @description - Data Store for Media Types */ export class UmbMediaTypeStore extends UmbDataStoreBase { - private _entityStore: UmbEntityStore; - - constructor(entityStore: UmbEntityStore) { - super(); - this._entityStore = entityStore; - } - getTreeRoot(): Observable> { MediaTypeResource.getTreeMediaTypeRoot({}).then( (res) => { diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/media/media.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/media/media.store.ts index 22e00120ec..0b1021ffc2 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/media/media.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/media/media.store.ts @@ -1,5 +1,4 @@ import { map, Observable } from 'rxjs'; -import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; import type { MediaDetails } from '@umbraco-cms/models'; import { ApiError, ContentTreeItem, MediaResource, ProblemDetails } from '@umbraco-cms/backend-api'; @@ -11,13 +10,6 @@ import { ApiError, ContentTreeItem, MediaResource, ProblemDetails } from '@umbra * @description - Data Store for Media */ export class UmbMediaStore extends UmbDataStoreBase { - private _entityStore: UmbEntityStore; - - constructor(entityStore: UmbEntityStore) { - super(); - this._entityStore = entityStore; - } - getTreeRoot(): Observable> { MediaResource.getTreeMediaRoot({}).then( (res) => { diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/member-group/member-group.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/member-group/member-group.store.ts index 5edb641b70..cf26069c8f 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/member-group/member-group.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/member-group/member-group.store.ts @@ -1,5 +1,4 @@ import { map, Observable } from 'rxjs'; -import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; import { ApiError, EntityTreeItem, MemberGroupResource, ProblemDetails } from '@umbraco-cms/backend-api'; import type { MemberGroupDetails } from '@umbraco-cms/models'; @@ -11,13 +10,6 @@ import type { MemberGroupDetails } from '@umbraco-cms/models'; * @description - Data Store for Member Groups */ export class UmbMemberGroupStore extends UmbDataStoreBase { - private _entityStore: UmbEntityStore; - - constructor(entityStore: UmbEntityStore) { - super(); - this._entityStore = entityStore; - } - getTreeRoot(): Observable> { MemberGroupResource.getTreeMemberGroupRoot({}).then( (res) => { diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/member-type/member-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/member-type/member-type.store.ts index cf83a12119..ee20f547db 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/member-type/member-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/member-type/member-type.store.ts @@ -1,5 +1,4 @@ import { map, Observable } from 'rxjs'; -import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; import { MemberTypeResource, ApiError, EntityTreeItem, ProblemDetails } from '@umbraco-cms/backend-api'; import type { MemberTypeDetails } from '@umbraco-cms/models'; @@ -11,13 +10,6 @@ import type { MemberTypeDetails } from '@umbraco-cms/models'; * @description - Data Store for Member Types */ export class UmbMemberTypeStore extends UmbDataStoreBase { - private _entityStore: UmbEntityStore; - - constructor(entityStore: UmbEntityStore) { - super(); - this._entityStore = entityStore; - } - getTreeRoot(): Observable> { MemberTypeResource.getTreeMemberTypeRoot({}).then( (res) => { From ae729b46286c9aae48770f2c8e3f729a278cc503 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 18 Nov 2022 09:32:15 +0100 Subject: [PATCH 043/223] remove call to entity store --- .../src/core/stores/data-type/data-type.store.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts index 89027c06b0..e24973c4df 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/data-type/data-type.store.ts @@ -46,7 +46,6 @@ export class UmbDataTypeStore extends UmbDataStoreBase> { From a91b91ffb3e9c65b07b7b368b3e5fd589bb863cb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 18 Nov 2022 09:56:45 +0100 Subject: [PATCH 044/223] remove unused entity store in section element --- .../src/backoffice/sections/shared/section.element.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/shared/section.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/shared/section.element.ts index de55728768..ec301d110d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/shared/section.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/shared/section.element.ts @@ -54,15 +54,13 @@ export class UmbSectionElement extends UmbContextConsumerMixin(UmbObserverMixin( @state() private _views: Array = []; - private _entityStore?: UmbEntityStore; private _sectionContext?: UmbSectionContext; constructor() { super(); - this.consumeAllContexts(['umbSectionContext', 'umbEntityStore'], (instances) => { + this.consumeAllContexts(['umbSectionContext'], (instances) => { this._sectionContext = instances['umbSectionContext']; - this._entityStore = instances['umbEntityStore']; this._observeTrees(); this._observeViews(); @@ -70,7 +68,7 @@ export class UmbSectionElement extends UmbContextConsumerMixin(UmbObserverMixin( } private _observeTrees() { - if (!this._sectionContext || !this._entityStore) return; + if (!this._sectionContext) return; this.observe( this._sectionContext?.data.pipe( @@ -119,7 +117,7 @@ export class UmbSectionElement extends UmbContextConsumerMixin(UmbObserverMixin( } private _observeViews() { - if (!this._sectionContext || !this._entityStore) return; + if (!this._sectionContext) return; this.observe( this._sectionContext.data.pipe( From a0049cf0a7b7d75acf907a805702c205df343623 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 18 Nov 2022 10:35:36 +0100 Subject: [PATCH 045/223] wire up tree item children --- .../trees/shared/tree-item.element.ts | 16 +++++++---- .../src/core/mocks/data/document.data.ts | 28 +++++++++++++++++-- .../mocks/domains/tree-document.handlers.ts | 6 ++-- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts index 81a55876eb..6358158dce 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts @@ -12,6 +12,7 @@ import { UmbTreeDataContextBase } from '../tree-data.context'; import { UmbTreeContextMenuService } from './context-menu/tree-context-menu.service'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UmbDataStore } from 'src/core/stores/store'; @customElement('umb-tree-item') export class UmbTreeItem extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { @@ -39,7 +40,7 @@ export class UmbTreeItem extends UmbContextConsumerMixin(UmbObserverMixin(LitEle private _isActive = false; private _treeContext?: UmbTreeContextBase; - private _treeDataContext?: UmbTreeDataContextBase; + private _treeStore?: UmbDataStore; private _sectionContext?: UmbSectionContext; private _treeContextMenuService?: UmbTreeContextMenuService; @@ -52,8 +53,8 @@ export class UmbTreeItem extends UmbContextConsumerMixin(UmbObserverMixin(LitEle this._observeSelection(); }); - this.consumeContext('umbTreeDataContext', (treeDataContext: UmbTreeDataContextBase) => { - this._treeDataContext = treeDataContext; + this.consumeContext('umbTreeStore', (store: UmbDataStore) => { + this._treeStore = store; }); this.consumeContext('umbSectionContext', (sectionContext: UmbSectionContext) => { @@ -119,12 +120,15 @@ export class UmbTreeItem extends UmbContextConsumerMixin(UmbObserverMixin(LitEle private _onShowChildren(event: UUIMenuItemEvent) { event.stopPropagation(); if (this._childItems.length > 0) return; + this._observeChildren(); + } + + private _observeChildren() { + if (!this._treeStore?.getTreeItemChildren) return; this._loading = true; - if (!this._treeDataContext) return; - - this.observe(this._treeDataContext.childrenChanges(this.treeItem.key), (childItems) => { + this.observe(this._treeStore.getTreeItemChildren(this.treeItem.key), (childItems) => { if (childItems?.length === 0) return; this._childItems = childItems; this._loading = false; diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/document.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/document.data.ts index 7296a87528..b1028e432c 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 @@ -128,7 +128,7 @@ export const data: Array = [ name: 'Document 3', type: 'document', icon: 'document', - hasChildren: false, + hasChildren: true, key: 'cdd30288-2d1c-41b4-89a9-61647b4a10d5', isContainer: false, parentKey: null, @@ -151,7 +151,31 @@ export const data: Array = [ value: 'Every day, a rabbit in a military costume greets me at the front door', }, ], - variants: [{ name: 'Variant 1' }], + variants: [], + }, + { + name: 'Document 4', + type: 'document', + icon: 'document', + hasChildren: false, + key: 'f6f7a5b2-e7c0-463a-97bc-6cb5b9bcf447', + isContainer: false, + parentKey: 'cdd30288-2d1c-41b4-89a9-61647b4a10d5', + noAccess: false, + isProtected: false, + isPublished: false, + isEdited: false, + isTrashed: false, + properties: [ + { + alias: 'myDescription', + label: 'Description', + description: 'Textarea property', + dataTypeKey: 'dt-2', + }, + ], + data: [], + variants: [], }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-document.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-document.handlers.ts index e17871717c..84d95558ee 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-document.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-document.handlers.ts @@ -9,9 +9,9 @@ export const handlers = [ }), rest.get('/umbraco/management/api/v1/tree/document/children', (req, res, ctx) => { - const key = req.params.key as string; - if (!key) return; - const response = umbDocumentData.getTreeItemChildren(key); + const parentKey = req.url.searchParams.get('parentKey'); + if (!parentKey) return; + const response = umbDocumentData.getTreeItemChildren(parentKey); return res(ctx.status(200), ctx.json(response)); }), From f650bd0f9cdf3f8fb379a654e3251a9cdec06d29 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 18 Nov 2022 10:39:30 +0100 Subject: [PATCH 046/223] remove tree data context --- .../tree-extensions-data.context.ts | 19 ------------ .../extensions/tree-extensions.element.ts | 14 --------- .../trees/shared/tree-item.element.ts | 1 - .../src/backoffice/trees/tree-data.context.ts | 31 ------------------- 4 files changed, 65 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions-data.context.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/tree-data.context.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions-data.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions-data.context.ts deleted file mode 100644 index 4a161c7adf..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions-data.context.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { UmbTreeDataContextBase } from '../tree-data.context'; - -export class UmbTreeExtensionsDataContext extends UmbTreeDataContextBase { - public rootKey = 'fd32ea8b-893b-4ee9-b1d0-72f41c4a6d38'; - - public rootChanges() { - const data = { - key: this.rootKey, - name: 'Extensions', - hasChildren: false, - type: 'extensionsList', - icon: 'favorite', - parentKey: '', - isTrashed: false, - }; - this.entityStore.update([data]); - return super.rootChanges(); - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions.element.ts index 3d0a6113d3..f814f3c096 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions.element.ts @@ -1,26 +1,12 @@ import { html } from 'lit'; import { customElement } from 'lit/decorators.js'; -import { UmbEntityStore } from '../../../core/stores/entity.store'; import { UmbTreeBase } from '../shared/tree-base.element'; -import { UmbTreeExtensionsDataContext } from './tree-extensions-data.context'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import '../shared/tree-navigator.element'; @customElement('umb-tree-extensions') export class UmbTreeExtensionsElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { - constructor() { - super(); - - this.consumeContext('umbEntityStore', (entityStore: UmbEntityStore) => { - this._entityStore = entityStore; - if (!this._entityStore) return; - - this._treeDataContext = new UmbTreeExtensionsDataContext(this._entityStore); - this.provideContext('umbTreeDataContext', this._treeDataContext); - }); - } - render() { return html``; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts index 6358158dce..395632736e 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts @@ -8,7 +8,6 @@ import { UmbTreeContextBase } from '../tree.context'; import { UmbSectionContext } from '../../sections/section.context'; import { Entity } from '../../../core/mocks/data/entities'; import type { ManifestSection } from '../../../core/models'; -import { UmbTreeDataContextBase } from '../tree-data.context'; import { UmbTreeContextMenuService } from './context-menu/tree-context-menu.service'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree-data.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree-data.context.ts deleted file mode 100644 index 9f8cb471aa..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree-data.context.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { map, Observable } from 'rxjs'; -import type { UmbEntityStore } from '../../core/stores/entity.store'; -import { Entity } from '../../core/mocks/data/entities'; - -export interface UmbTreeDataContext { - rootKey: string; - entityStore: UmbEntityStore; - rootChanges?(key: string): Observable; - childrenChanges?(key: string): Observable; -} - -export class UmbTreeDataContextBase implements UmbTreeDataContext { - public entityStore: UmbEntityStore; - public rootKey = ''; - - constructor(entityStore: UmbEntityStore) { - this.entityStore = entityStore; - } - - public rootChanges() { - return this.entityStore.items.pipe( - map((items) => items.filter((item) => item.key === this.rootKey && !item.isTrashed)) - ); - } - - public childrenChanges(key: string) { - return this.entityStore.items.pipe( - map((items) => items.filter((item) => item.parentKey === key && !item.isTrashed)) - ); - } -} From 0e6a91d390715d9605576b56015f1d25e0b4936d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 18 Nov 2022 10:40:42 +0100 Subject: [PATCH 047/223] remove unused tree data context --- .../src/backoffice/trees/shared/tree-base.element.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts index b171335bac..04c3dd933f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts @@ -1,7 +1,6 @@ import { LitElement } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { UmbEntityStore } from '../../../core/stores/entity.store'; -import { UmbTreeDataContext } from '../tree-data.context'; import type { ManifestTree } from '@umbraco-cms/models'; @customElement('umb-tree-base') @@ -9,7 +8,6 @@ export class UmbTreeBase extends LitElement { @property({ type: Object, attribute: false }) tree?: ManifestTree; - protected _treeDataContext?: UmbTreeDataContext; protected _entityStore?: UmbEntityStore; } From 03ba6306a8ce04ea4c6955c9818af78a784264cd Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 18 Nov 2022 10:41:41 +0100 Subject: [PATCH 048/223] remove unused entity store --- .../src/backoffice/sections/shared/section.element.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/shared/section.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/shared/section.element.ts index ec301d110d..5dc4b60b33 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/shared/section.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/shared/section.element.ts @@ -4,7 +4,6 @@ import { customElement, state } from 'lit/decorators.js'; import { map, switchMap, EMPTY, of } from 'rxjs'; import { UmbSectionContext } from '../section.context'; import { UmbEditorEntityElement } from '../../editors/shared/editor-entity/editor-entity.element'; -import { UmbEntityStore } from '../../../core/stores/entity.store'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { createExtensionElement } from '@umbraco-cms/extensions-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; From 108efcb0293a0d913ec4047e45099e1bf1df3f3a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 18 Nov 2022 15:13:11 +0100 Subject: [PATCH 049/223] wire up document picker --- ...operty-editor-ui-content-picker.element.ts | 23 +++++++++--------- .../trees/shared/tree-item.element.ts | 24 ++++++++++++------- .../backoffice/trees/shared/tree.element.ts | 15 +++++++----- .../src/backoffice/trees/tree.context.ts | 6 ++++- .../src/core/mocks/data/document.data.ts | 2 +- .../mocks/domains/tree-document.handlers.ts | 4 ++-- .../modal-layout-content-picker.element.ts | 2 +- .../core/stores/document/document.store.ts | 22 +++++++++++++++++ 8 files changed, 68 insertions(+), 30 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/property-editor-uis/content-picker/property-editor-ui-content-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/property-editor-uis/content-picker/property-editor-ui-content-picker.element.ts index 55b35a698a..48e61a8b89 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/property-editor-uis/content-picker/property-editor-ui-content-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/property-editor-uis/content-picker/property-editor-ui-content-picker.element.ts @@ -3,10 +3,10 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, state } from 'lit/decorators.js'; import type { UmbModalService } from '../../../core/services/modal'; -import type { UmbEntityStore } from '../../../core/stores/entity.store'; import type { Entity } from '../../../core/mocks/data/entities'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UmbDocumentStore } from 'src/core/stores/document/document.store'; @customElement('umb-property-editor-ui-content-picker') export class UmbPropertyEditorUIContentPickerElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { @@ -44,29 +44,30 @@ export class UmbPropertyEditorUIContentPickerElement extends UmbContextConsumerM private _items: Array = []; private _modalService?: UmbModalService; - private _entityStore?: UmbEntityStore; + private _documentStore?: UmbDocumentStore; constructor() { super(); - this.consumeAllContexts(['umbEntityStore', 'umbModalService'], (instances) => { - this._entityStore = instances['umbEntityStore']; + this.consumeAllContexts(['umbDocumentStore', 'umbModalService'], (instances) => { + this._documentStore = instances['umbDocumentStore']; this._modalService = instances['umbModalService']; - this._observePickedEntities(); + this._observePickedDocuments(); }); } - private _observePickedEntities() { - if (!this._entityStore) return; - this.observe(this._entityStore.getByKeys(this.value), (entities) => { - this._items = entities; + private _observePickedDocuments() { + if (!this._documentStore) return; + // TODO: consider changing this to the list data endpoint when it is available + this.observe(this._documentStore.getTreeItems(this.value), (items) => { + this._items = items; }); } private _openPicker() { const modalHandler = this._modalService?.contentPicker({ multiple: true, selection: this.value }); modalHandler?.onClose().then(({ selection }: any) => { - this._setValue([...this.value, ...selection]); + this._setValue([...selection]); }); } @@ -88,7 +89,7 @@ export class UmbPropertyEditorUIContentPickerElement extends UmbContextConsumerM private _setValue(newValue: Array) { this.value = newValue; - this._observePickedEntities(); + this._observePickedDocuments(); this.dispatchEvent(new CustomEvent('property-editor-change', { bubbles: true, composed: true })); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts index 395632736e..7abf917411 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts @@ -4,7 +4,7 @@ import { customElement, property, state } from 'lit/decorators.js'; import { UUIMenuItemEvent } from '@umbraco-ui/uui'; import { map } from 'rxjs'; import { repeat } from 'lit/directives/repeat.js'; -import { UmbTreeContextBase } from '../tree.context'; +import type { UmbTreeContextBase } from '../tree.context'; import { UmbSectionContext } from '../../sections/section.context'; import { Entity } from '../../../core/mocks/data/entities'; import type { ManifestSection } from '../../../core/models'; @@ -49,7 +49,7 @@ export class UmbTreeItem extends UmbContextConsumerMixin(UmbObserverMixin(LitEle this.consumeContext('umbTreeContext', (treeContext: UmbTreeContextBase) => { this._treeContext = treeContext; this._observeSelectable(); - this._observeSelection(); + this._observeIsSelected(); }); this.consumeContext('umbTreeStore', (store: UmbDataStore) => { @@ -69,11 +69,19 @@ export class UmbTreeItem extends UmbContextConsumerMixin(UmbObserverMixin(LitEle connectedCallback(): void { super.connectedCallback(); - this.addEventListener('selected', (e) => { - e.stopPropagation(); - this._treeContext?.select(this.treeItem.key); - this.dispatchEvent(new CustomEvent('change', { composed: true, bubbles: true })); - }); + + this.addEventListener('selected', this._handleSelectedItem); + this.addEventListener('unselected', this._handleDeselectedItem); + } + + private _handleSelectedItem(event: Event) { + event.stopPropagation(); + this._treeContext?.select(this.treeItem.key); + } + + private _handleDeselectedItem(event: Event) { + event.stopPropagation(); + this._treeContext?.deselect(this.treeItem.key); } private _observeSection() { @@ -92,7 +100,7 @@ export class UmbTreeItem extends UmbContextConsumerMixin(UmbObserverMixin(LitEle }); } - private _observeSelection() { + private _observeIsSelected() { if (!this._treeContext) return; this.observe( diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree.element.ts index d3347bee93..45e8ffcff1 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree.element.ts @@ -32,6 +32,10 @@ export class UmbTreeElement extends UmbContextProviderMixin(UmbContextConsumerMi this._selectable = newVal; this.requestUpdate('selectable', oldVal); this._treeContext?.setSelectable(newVal); + + if (newVal) { + this._observeSelection(); + } } private _selection: Array = []; @@ -71,23 +75,22 @@ export class UmbTreeElement extends UmbContextProviderMixin(UmbContextConsumerMi } private _provideTreeContext() { - if (!this._tree) return; + if (!this._tree || this._treeContext) return; + this._treeContext = new UmbTreeContextBase(this._tree); this._treeContext.setSelectable(this.selectable); this._treeContext.setSelection(this.selection); - this.provideContext('umbTreeContext', this._treeContext); - if (this.selectable) { - this._observeSelection(); - } + this.provideContext('umbTreeContext', this._treeContext); } private _observeSelection() { if (!this._treeContext) return; this.observe(this._treeContext.selection, (selection) => { + if (this._selection === selection) return; this._selection = selection; - this.dispatchEvent(new CustomEvent('change')); + this.dispatchEvent(new CustomEvent('selected')); }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree.context.ts index 91ee2535bd..dfa57ae5b5 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree.context.ts @@ -12,7 +12,6 @@ export interface UmbTreeContext { export class UmbTreeContextBase implements UmbTreeContext { public tree: ManifestTree; - public rootKey = ''; private _selectable: BehaviorSubject = new BehaviorSubject(false); public readonly selectable: Observable = this._selectable.asObservable(); @@ -37,4 +36,9 @@ export class UmbTreeContextBase implements UmbTreeContext { const selection = this._selection.getValue(); this._selection.next([...selection, key]); } + + public deselect(key: string) { + const selection = this._selection.getValue(); + this._selection.next(selection.filter((x) => x !== key)); + } } 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 b1028e432c..ec0e5e066c 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 @@ -197,7 +197,7 @@ class UmbDocumentData extends UmbData { return { items, total }; } - getTreeItem(keys: Array): Array { + getTreeItems(keys: Array): Array { return this.data.filter((item) => keys.includes(item.key ?? '')); } } diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-document.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-document.handlers.ts index 84d95558ee..ab361bfab4 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-document.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/tree-document.handlers.ts @@ -16,10 +16,10 @@ export const handlers = [ }), rest.get('/umbraco/management/api/v1/tree/document/item', (req, res, ctx) => { - const keys = req.params.keys as string; + const keys = req.url.searchParams.getAll('key'); if (!keys) return; - const items = umbDocumentData.getTreeItem(keys.split(',')); + const items = umbDocumentData.getTreeItems(keys); return res(ctx.status(200), ctx.json(items)); }), diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.element.ts index 1c60ce0cb9..4ef52ea23d 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.element.ts @@ -78,7 +78,7 @@ export class UmbModalLayoutContentPickerElement extends UmbModalLayoutElement diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts index 32acdeb94d..7aeecbc364 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts @@ -47,4 +47,26 @@ export class UmbDocumentStore extends UmbDataStoreBase items.filter((item) => item.parentKey === key))); } + + getTreeItems(keys: Array): Observable> { + if (keys.length > 0) { + DocumentResource.getTreeDocumentItem({ + key: keys, + }).then( + (items) => { + this.update(items); + }, + (e) => { + if (e instanceof ApiError) { + const error = e.body as ProblemDetails; + if (e.status === 400) { + console.log(error.detail); + } + } + } + ); + } + + return this.items.pipe(map((items) => items.filter((item) => keys.includes(item.key ?? '')))); + } } From b41a57e8f3bfae6b3967ed0fcd4e0ff222f3485f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 18 Nov 2022 15:16:58 +0100 Subject: [PATCH 050/223] rename node folder to editor-content --- .../backoffice/editors/document/editor-document.element.ts | 6 +++--- .../src/backoffice/editors/media/editor-media.element.ts | 6 +++--- .../shared/{node => editor-content}/editor-node.element.ts | 2 +- .../shared/{node => editor-content}/editor-node.stories.ts | 0 .../editors/shared/{node => editor-content}/node.context.ts | 0 .../views/edit/editor-view-node-edit.element.ts | 0 .../views/edit/editor-view-node-edit.stories.ts | 0 .../views/info/editor-view-node-info.element.ts | 0 .../views/info/editor-view-node-info.stories.ts | 0 9 files changed, 7 insertions(+), 7 deletions(-) rename src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/{node => editor-content}/editor-node.element.ts (98%) rename src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/{node => editor-content}/editor-node.stories.ts (100%) rename src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/{node => editor-content}/node.context.ts (100%) rename src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/{node => editor-content}/views/edit/editor-view-node-edit.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/{node => editor-content}/views/edit/editor-view-node-edit.stories.ts (100%) rename src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/{node => editor-content}/views/info/editor-view-node-info.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/{node => editor-content}/views/info/editor-view-node-info.stories.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts index 7b0c061cc3..55e8e7d6ce 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts @@ -4,7 +4,7 @@ import { customElement, property } from 'lit/decorators.js'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import type { ManifestEditorView, ManifestWithLoader } from '@umbraco-cms/models'; -import '../shared/node/editor-node.element'; +import '../shared/editor-content/editor-node.element'; @customElement('umb-editor-document') export class UmbEditorDocumentElement extends LitElement { @@ -34,7 +34,7 @@ export class UmbEditorDocumentElement extends LitElement { type: 'editorView', alias: 'Umb.EditorView.Document.Edit', name: 'Document Editor Edit View', - loader: () => import('../shared/node/views/edit/editor-view-node-edit.element'), + loader: () => import('../shared/editor-content/views/edit/editor-view-node-edit.element'), weight: 200, meta: { editors: ['Umb.Editor.Document'], @@ -47,7 +47,7 @@ export class UmbEditorDocumentElement extends LitElement { type: 'editorView', alias: 'Umb.EditorView.Document.Info', name: 'Document Editor Info View', - loader: () => import('../shared/node/views/info/editor-view-node-info.element'), + loader: () => import('../shared/editor-content/views/info/editor-view-node-info.element'), weight: 100, meta: { editors: ['Umb.Editor.Document'], diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts index a103fe5c5d..443acf8be0 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts @@ -4,7 +4,7 @@ import { customElement, property } from 'lit/decorators.js'; import type { ManifestEditorView, ManifestWithLoader } from '@umbraco-cms/models'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; -import '../shared/node/editor-node.element'; +import '../shared/editor-content/editor-node.element'; @customElement('umb-editor-media') export class UmbEditorMediaElement extends LitElement { @@ -34,7 +34,7 @@ export class UmbEditorMediaElement extends LitElement { type: 'editorView', alias: 'Umb.EditorView.Media.Edit', name: 'Media Editor Edit View', - loader: () => import('../shared/node/views/edit/editor-view-node-edit.element'), + loader: () => import('../shared/editor-content/views/edit/editor-view-node-edit.element'), weight: 200, meta: { editors: ['Umb.Editor.Media'], @@ -47,7 +47,7 @@ export class UmbEditorMediaElement extends LitElement { type: 'editorView', alias: 'Umb.EditorView.Media.Info', name: 'Media Editor Info View', - loader: () => import('../shared/node/views/info/editor-view-node-info.element'), + loader: () => import('../shared/editor-content/views/info/editor-view-node-info.element'), weight: 100, meta: { editors: ['Umb.Editor.Media'], diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/editor-node.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-node.element.ts similarity index 98% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/editor-node.element.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-node.element.ts index aabd79bf42..a61320ef24 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/editor-node.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-node.element.ts @@ -11,7 +11,7 @@ import { UmbNodeContext } from './node.context'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; -import '../../shared/editor-entity-layout/editor-entity-layout.element'; +import '../editor-entity-layout/editor-entity-layout.element'; // Lazy load // TODO: Make this dynamic, use load-extensions method to loop over extensions for this node. diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/editor-node.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-node.stories.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/editor-node.stories.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-node.stories.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/node.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/node.context.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/node.context.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/node.context.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/views/edit/editor-view-node-edit.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-node-edit.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/views/edit/editor-view-node-edit.element.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-node-edit.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/views/edit/editor-view-node-edit.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-node-edit.stories.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/views/edit/editor-view-node-edit.stories.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-node-edit.stories.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/views/info/editor-view-node-info.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-node-info.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/views/info/editor-view-node-info.element.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-node-info.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/views/info/editor-view-node-info.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-node-info.stories.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/node/views/info/editor-view-node-info.stories.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-node-info.stories.ts From f5bb2f5e176c6bf61842cdc28a3401baef8173fd Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 18 Nov 2022 15:42:09 +0100 Subject: [PATCH 051/223] remove entityStore from users and user groups --- .../backoffice/trees/shared/tree-base.element.ts | 3 --- .../stores/document-type/document-type.store.ts | 1 - .../src/core/stores/user/user-group.store.ts | 13 ++----------- .../src/core/stores/user/user.store.ts | 16 +--------------- 4 files changed, 3 insertions(+), 30 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts index 04c3dd933f..366b11e608 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts @@ -1,14 +1,11 @@ import { LitElement } from 'lit'; import { customElement, property } from 'lit/decorators.js'; -import { UmbEntityStore } from '../../../core/stores/entity.store'; import type { ManifestTree } from '@umbraco-cms/models'; @customElement('umb-tree-base') export class UmbTreeBase extends LitElement { @property({ type: Object, attribute: false }) tree?: ManifestTree; - - protected _entityStore?: UmbEntityStore; } declare global { diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts index a3de4148f0..fefdde35cc 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document-type/document-type.store.ts @@ -36,7 +36,6 @@ export class UmbDocumentTypeStore extends UmbDataStoreBase { - private _entityStore: UmbEntityStore; - - constructor(entityStore: UmbEntityStore) { - super(); - this._entityStore = entityStore; - } - getAll(): Observable> { // TODO: use Fetcher API. // TODO: only fetch if the data type is not in the store? diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/user/user.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/user/user.store.ts index d562b3fdd8..ed7a5294ed 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/user/user.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/user/user.store.ts @@ -1,7 +1,5 @@ import { BehaviorSubject, map, Observable } from 'rxjs'; -import { v4 as uuidv4 } from 'uuid'; -import type { UserDetails, UserEntity } from '../../models'; -import { UmbEntityStore } from '../entity.store'; +import type { UserDetails } from '../../models'; import { UmbDataStoreBase } from '../store'; /** @@ -11,16 +9,9 @@ import { UmbDataStoreBase } from '../store'; * @description - Data Store for Users */ export class UmbUserStore extends UmbDataStoreBase { - private _entityStore: UmbEntityStore; - private _totalUsers: BehaviorSubject = new BehaviorSubject(0); public readonly totalUsers: Observable = this._totalUsers.asObservable(); - constructor(entityStore: UmbEntityStore) { - super(); - this._entityStore = entityStore; - } - getAll(): Observable> { // TODO: use Fetcher API. // TODO: only fetch if the data type is not in the store? @@ -72,7 +63,6 @@ export class UmbUserStore extends UmbDataStoreBase { }); this.update(storedUsers); - this._entityStore.update(storedUsers); } catch (error) { console.error('Enable Users failed', error); } @@ -96,7 +86,6 @@ export class UmbUserStore extends UmbDataStoreBase { }); this.update(storedUsers); - this._entityStore.update(storedUsers); } catch (error) { console.error('Disable Users failed', error); } @@ -114,7 +103,6 @@ export class UmbUserStore extends UmbDataStoreBase { }); const deletedKeys = await res.json(); this.delete(deletedKeys); - this._entityStore.delete(deletedKeys); } catch (error) { console.error('Delete Users failed', error); } @@ -132,7 +120,6 @@ export class UmbUserStore extends UmbDataStoreBase { }); const json = await res.json(); this.update(json); - this._entityStore.update(json); } catch (error) { console.error('Save Data Type error', error); } @@ -150,7 +137,6 @@ export class UmbUserStore extends UmbDataStoreBase { }); const json = (await res.json()) as UserDetails[]; this.update(json); - this._entityStore.update(json); return json[0]; } catch (error) { console.error('Invite user error', error); From f987647ce2bbd4b72ffc94a164deb71c0aede358 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 18 Nov 2022 15:43:20 +0100 Subject: [PATCH 052/223] don't inject entity store into user and user group store --- .../src/backoffice/backoffice.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index e2a2f7b936..5b02275b58 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -80,8 +80,8 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this.provideContext('umbDocumentTypeStore', new UmbDocumentTypeStore()); this.provideContext('umbMediaTypeStore', new UmbMediaTypeStore()); this.provideContext('umbMemberTypeStore', new UmbMemberTypeStore()); - this.provideContext('umbUserStore', new UmbUserStore(this._umbEntityStore)); - this.provideContext('umbUserGroupStore', new UmbUserGroupStore(this._umbEntityStore)); + this.provideContext('umbUserStore', new UmbUserStore()); + this.provideContext('umbUserGroupStore', new UmbUserGroupStore()); this.provideContext('umbMemberGroupStore', new UmbMemberGroupStore()); this.provideContext('umbNotificationService', new UmbNotificationService()); this.provideContext('umbModalService', new UmbModalService()); From dadbd21b0977092719e9a02a111333807cf47ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Wed, 23 Nov 2022 00:12:35 +0100 Subject: [PATCH 053/223] add modal layout --- .../modal-layout-user-settings.element.ts | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-settings.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-settings.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-settings.element.ts new file mode 100644 index 0000000000..e469869741 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-settings.element.ts @@ -0,0 +1,62 @@ +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { css, CSSResultGroup, html, LitElement } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { UmbModalHandler } from '@umbraco-cms/services'; + +@customElement('umb-modal-layout-user-settings') +export class UmbModalLayoutUserSettingsElement extends LitElement { + static styles: CSSResultGroup = [ + UUITextStyles, + css` + :host { + display: block; + } + :host, + umb-editor-entity-layout { + width: 100%; + height: 100%; + } + #main { + padding: var(--uui-size-space-5); + display: flex; + flex-direction: column; + gap: var(--uui-size-space-3); + } + `, + ]; + + @property({ attribute: false }) + modalHandler?: UmbModalHandler; + + private _close() { + this.modalHandler?.close(); + } + + render() { + return html` + +
+ + Your profile + Edit + Logout + + + External login providers + Edit your Umbraco ID profile + Change your Umbraco ID password + +
+
+ Close +
+
+ `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-modal-layout-user-settings': UmbModalLayoutUserSettingsElement; + } +} From fe17aac8c9aca056587d271811ad4e3d88e75b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Wed, 23 Nov 2022 00:12:56 +0100 Subject: [PATCH 054/223] add modal layout to modal service and user icon --- .../backoffice-header-tools.element.ts | 19 +++++++++++++++++-- .../src/core/services/modal/modal.service.ts | 11 +++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts index 0958b10c39..19adf9a7a8 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts @@ -1,9 +1,11 @@ +import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UmbModalService } from '@umbraco-cms/services'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, CSSResultGroup, html, LitElement } from 'lit'; import { customElement } from 'lit/decorators.js'; @customElement('umb-backoffice-header-tools') -export class UmbBackofficeHeaderTools extends LitElement { +export class UmbBackofficeHeaderTools extends UmbContextConsumerMixin(LitElement) { static styles: CSSResultGroup = [ UUITextStyles, css` @@ -19,6 +21,19 @@ export class UmbBackofficeHeaderTools extends LitElement { `, ]; + constructor() { + super(); + this.consumeContext('umbModalService', (modalService: UmbModalService) => { + this._modalService = modalService; + }); + } + + private _handleUserClick() { + this._modalService?.userSettings(); + } + + private _modalService?: UmbModalService; + render() { return html`
@@ -28,7 +43,7 @@ export class UmbBackofficeHeaderTools extends LitElement { - +
diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts index f8027a2cdf..3e9c966980 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts @@ -2,6 +2,7 @@ import './layouts/confirm/modal-layout-confirm.element'; import './layouts/content-picker/modal-layout-content-picker.element'; import './layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.element'; +import './layouts/modal-layout-user-settings.element'; import { UUIModalSidebarSize } from '@umbraco-ui/uui-modal-sidebar'; import { BehaviorSubject, Observable } from 'rxjs'; @@ -68,6 +69,16 @@ export class UmbModalService { return this.open('umb-modal-layout-icon-picker', { data, type: 'sidebar', size: 'small' }); } + /** + * Opens the user settings sidebar modal + * @public + * @return {*} {UmbModalHandler} + * @memberof UmbModalService + */ + public userSettings(): UmbModalHandler { + return this.open('umb-modal-layout-user-settings', { type: 'sidebar', size: 'small' }); + } + /** * Opens a modal or sidebar modal * @public From f000ec0085565a880392bc9a86cf3ca11c9c5932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Wed, 23 Nov 2022 00:14:59 +0100 Subject: [PATCH 055/223] rename to user dialog --- ...tings.element.ts => modal-layout-user-dialog.element.ts} | 6 +++--- .../src/core/services/modal/modal.service.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) rename src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/{modal-layout-user-settings.element.ts => modal-layout-user-dialog.element.ts} (88%) diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-settings.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts similarity index 88% rename from src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-settings.element.ts rename to src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index e469869741..ab1bcef066 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-settings.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -3,8 +3,8 @@ import { css, CSSResultGroup, html, LitElement } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { UmbModalHandler } from '@umbraco-cms/services'; -@customElement('umb-modal-layout-user-settings') -export class UmbModalLayoutUserSettingsElement extends LitElement { +@customElement('umb-modal-layout-user-dialog') +export class UmbModalLayoutUserDialogElement extends LitElement { static styles: CSSResultGroup = [ UUITextStyles, css` @@ -57,6 +57,6 @@ export class UmbModalLayoutUserSettingsElement extends LitElement { declare global { interface HTMLElementTagNameMap { - 'umb-modal-layout-user-settings': UmbModalLayoutUserSettingsElement; + 'umb-modal-layout-user-dialog': UmbModalLayoutUserDialogElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts index 3e9c966980..e8a7d645dd 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts @@ -2,7 +2,7 @@ import './layouts/confirm/modal-layout-confirm.element'; import './layouts/content-picker/modal-layout-content-picker.element'; import './layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.element'; -import './layouts/modal-layout-user-settings.element'; +import './layouts/modal-layout-user-dialog.element'; import { UUIModalSidebarSize } from '@umbraco-ui/uui-modal-sidebar'; import { BehaviorSubject, Observable } from 'rxjs'; @@ -76,7 +76,7 @@ export class UmbModalService { * @memberof UmbModalService */ public userSettings(): UmbModalHandler { - return this.open('umb-modal-layout-user-settings', { type: 'sidebar', size: 'small' }); + return this.open('umb-modal-layout-user-dialog', { type: 'sidebar', size: 'small' }); } /** From 1a7c37df6799f4110eea31b737bab521f70c5522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Wed, 23 Nov 2022 22:18:23 +0100 Subject: [PATCH 056/223] add faked current user to user store --- .../src/core/stores/user/user.store.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/user/user.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/user/user.store.ts index d562b3fdd8..0d4a9a082b 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/user/user.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/user/user.store.ts @@ -1,6 +1,5 @@ -import { BehaviorSubject, map, Observable } from 'rxjs'; -import { v4 as uuidv4 } from 'uuid'; -import type { UserDetails, UserEntity } from '../../models'; +import { BehaviorSubject, map, Observable, ReplaySubject, Subject } from 'rxjs'; +import type { UserDetails } from '../../models'; import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; @@ -16,9 +15,20 @@ export class UmbUserStore extends UmbDataStoreBase { private _totalUsers: BehaviorSubject = new BehaviorSubject(0); public readonly totalUsers: Observable = this._totalUsers.asObservable(); + private _currentUser: Subject = new ReplaySubject(); + public readonly currentUser: Observable = this._currentUser.asObservable(); + constructor(entityStore: UmbEntityStore) { super(); this._entityStore = entityStore; + + //TODO: Temp code to get the first user as the current user. Replace when login is implemented. + const subscription = this.getAll().subscribe((response) => { + if (response.length > 0) { + this._currentUser.next(response[0]); + subscription.unsubscribe(); + } + }); } getAll(): Observable> { From 24f5c32b24f10ed00dbb51098bc14b72b9feaa65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Wed, 23 Nov 2022 22:18:38 +0100 Subject: [PATCH 057/223] add current user to header avatar --- .../backoffice-header-tools.element.ts | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts index 19adf9a7a8..f2f8a37a82 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts @@ -1,11 +1,14 @@ import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UserDetails } from '@umbraco-cms/models'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbModalService } from '@umbraco-cms/services'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, CSSResultGroup, html, LitElement } from 'lit'; -import { customElement } from 'lit/decorators.js'; +import { customElement, state } from 'lit/decorators.js'; +import { UmbUserStore } from 'src/core/stores/user/user.store'; @customElement('umb-backoffice-header-tools') -export class UmbBackofficeHeaderTools extends UmbContextConsumerMixin(LitElement) { +export class UmbBackofficeHeaderTools extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { static styles: CSSResultGroup = [ UUITextStyles, css` @@ -23,8 +26,18 @@ export class UmbBackofficeHeaderTools extends UmbContextConsumerMixin(LitElement constructor() { super(); - this.consumeContext('umbModalService', (modalService: UmbModalService) => { - this._modalService = modalService; + this.consumeAllContexts(['umbUserStore', 'umbModalService'], (instances) => { + this._userStore = instances['umbUserStore']; + this._modalService = instances['umbModalService']; + this._observeCurrentUser(); + }); + } + + private async _observeCurrentUser() { + if (!this._userStore) return; + + this.observe(this._userStore.currentUser, (currentUser) => { + this._currentUser = currentUser; }); } @@ -32,6 +45,10 @@ export class UmbBackofficeHeaderTools extends UmbContextConsumerMixin(LitElement this._modalService?.userSettings(); } + @state() + private _currentUser?: UserDetails; + + private _userStore?: UmbUserStore; private _modalService?: UmbModalService; render() { @@ -44,7 +61,7 @@ export class UmbBackofficeHeaderTools extends UmbContextConsumerMixin(LitElement - + `; From 586e947c8af45bbfe71b5103d51466c046be9340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Wed, 23 Nov 2022 22:25:38 +0100 Subject: [PATCH 058/223] added redirecting to current user edit page --- .../modal-layout-user-dialog.element.ts | 39 +++++++++++++++++-- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index ab1bcef066..9fb582943e 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -1,10 +1,14 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, CSSResultGroup, html, LitElement } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; +import { customElement, property, state } from 'lit/decorators.js'; import { UmbModalHandler } from '@umbraco-cms/services'; +import type { UserDetails } from '@umbraco-cms/models'; +import { UmbUserStore } from 'src/core/stores/user/user.store'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; +import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; @customElement('umb-modal-layout-user-dialog') -export class UmbModalLayoutUserDialogElement extends LitElement { +export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { static styles: CSSResultGroup = [ UUITextStyles, css` @@ -28,17 +32,44 @@ export class UmbModalLayoutUserDialogElement extends LitElement { @property({ attribute: false }) modalHandler?: UmbModalHandler; + @state() + private _currentUser?: UserDetails; + + private _userStore?: UmbUserStore; + + constructor() { + super(); + this.consumeAllContexts(['umbUserStore'], (instances) => { + this._userStore = instances['umbUserStore']; + this._observeCurrentUser(); + }); + } + + private async _observeCurrentUser() { + if (!this._userStore) return; + + this.observe(this._userStore.currentUser, (currentUser) => { + this._currentUser = currentUser; + }); + } + private _close() { this.modalHandler?.close(); } + private _edit() { + if (!this._currentUser) return; + history.pushState(null, '', '/section/users/view/users/user/' + this._currentUser.key); //TODO Change to a tag with href and make dynamic + this._close(); + } + render() { return html` - +
Your profile - Edit + Edit Logout From 9177a5b54d5c83d996add83a66460bdf7c593304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Wed, 23 Nov 2022 23:25:37 +0100 Subject: [PATCH 059/223] user editor: hide status and delete button on current user --- .../backoffice-header-tools.element.ts | 12 +-- .../editors/user/editor-user.element.ts | 90 ++++++++++++------- 2 files changed, 62 insertions(+), 40 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts index f2f8a37a82..dfc275d0f5 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts @@ -24,6 +24,12 @@ export class UmbBackofficeHeaderTools extends UmbContextConsumerMixin(UmbObserve `, ]; + @state() + private _currentUser?: UserDetails; + + private _userStore?: UmbUserStore; + private _modalService?: UmbModalService; + constructor() { super(); this.consumeAllContexts(['umbUserStore', 'umbModalService'], (instances) => { @@ -45,12 +51,6 @@ export class UmbBackofficeHeaderTools extends UmbContextConsumerMixin(UmbObserve this._modalService?.userSettings(); } - @state() - private _currentUser?: UserDetails; - - private _userStore?: UmbUserStore; - private _modalService?: UmbModalService; - render() { return html`
diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts index e6984408d8..8017ef3597 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts @@ -14,9 +14,12 @@ import type { ManifestEditorAction, ManifestWithLoader, UserDetails } from '@umb import '../../property-editor-uis/content-picker/property-editor-ui-content-picker.element'; import '../shared/editor-entity-layout/editor-entity-layout.element'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; @customElement('umb-editor-user') -export class UmbEditorUserElement extends UmbContextProviderMixin(UmbContextConsumerMixin(LitElement)) { +export class UmbEditorUserElement extends UmbContextProviderMixin( + UmbContextConsumerMixin(UmbObserverMixin(LitElement)) +) { static styles = [ UUITextStyles, css` @@ -91,6 +94,9 @@ export class UmbEditorUserElement extends UmbContextProviderMixin(UmbContextCons @state() private _user?: UserDetails | null; + @state() + private _currentUser?: UserDetails | null; + @state() private _userName = ''; @@ -107,10 +113,44 @@ export class UmbEditorUserElement extends UmbContextProviderMixin(UmbContextCons constructor() { super(); - + this.consumeAllContexts(['umbUserStore'], (instances) => { + this._userStore = instances['umbUserStore']; + this._observeCurrentUser(); + this._observeUser(); + }); this._registerEditorActions(); } + private async _observeCurrentUser() { + if (!this._userStore) return; + + this.observe(this._userStore.currentUser, (currentUser) => { + this._currentUser = currentUser; + }); + } + + private async _observeUser() { + if (!this._userStore) return; + + this.observe(this._userStore.getByKey(this.entityKey), (user) => { + this._user = user; + if (!this._user) return; + + if (!this._userContext) { + this._userContext = new UmbUserContext(this._user); + this.provideContext('umbUserContext', this._userContext); + } else { + this._userContext.update(this._user); + } + + this._userNameSubscription = this._userContext.data.subscribe((user) => { + if (user && user.name !== this._userName) { + this._userName = user.name; + } + }); + }); + } + private _registerEditorActions() { const manifests: Array> = [ { @@ -139,28 +179,6 @@ export class UmbEditorUserElement extends UmbContextProviderMixin(UmbContextCons }); } - private _observeUser() { - this._usersSubscription?.unsubscribe(); - - this._usersSubscription = this._userStore?.getByKey(this.entityKey).subscribe((user) => { - this._user = user; - if (!this._user) return; - - if (!this._userContext) { - this._userContext = new UmbUserContext(this._user); - this.provideContext('umbUserContext', this._userContext); - } else { - this._userContext.update(this._user); - } - - this._userNameSubscription = this._userContext.data.subscribe((user) => { - if (user && user.name !== this._userName) { - this._userName = user.name; - } - }); - }); - } - disconnectedCallback(): void { super.disconnectedCallback(); @@ -183,6 +201,19 @@ export class UmbEditorUserElement extends UmbContextProviderMixin(UmbContextCons history.pushState(null, '', '/section/users/view/users/overview'); } + private _renderActionButtons() { + return html` ${this._user?.status !== 'invited' + ? html` + + ` + : nothing} + `; + } + private renderLeftColumn() { if (!this._user) return nothing; @@ -246,16 +277,7 @@ export class UmbEditorUserElement extends UmbContextProviderMixin(UmbContextCons
- ${this._user?.status !== 'invited' - ? html` - - ` - : nothing} - + ${this._currentUser?.key !== this._user.key ? this._renderActionButtons() : nothing}
Status: From ecf667d577b3c9dab41fe2f22fc831d7b205382d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Thu, 24 Nov 2022 00:07:27 +0100 Subject: [PATCH 060/223] added change password dialog --- .../backoffice-header-tools.element.ts | 8 +- .../modal-layout-change-password.element.ts | 91 +++++++++++++++++++ .../modal-layout-user-dialog.element.ts | 14 ++- .../src/core/services/modal/modal.service.ts | 11 +++ 4 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts index dfc275d0f5..0c336cf22d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts @@ -1,10 +1,10 @@ -import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; -import { UserDetails } from '@umbraco-cms/models'; -import { UmbObserverMixin } from '@umbraco-cms/observable-api'; -import { UmbModalService } from '@umbraco-cms/services'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, CSSResultGroup, html, LitElement } from 'lit'; import { customElement, state } from 'lit/decorators.js'; +import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import type { UserDetails } from '@umbraco-cms/models'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; +import { UmbModalService } from '@umbraco-cms/services'; import { UmbUserStore } from 'src/core/stores/user/user.store'; @customElement('umb-backoffice-header-tools') diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts new file mode 100644 index 0000000000..4a7fbe4cdb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts @@ -0,0 +1,91 @@ +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { css, CSSResultGroup, html, LitElement } from 'lit'; +import { customElement, property, state } from 'lit/decorators.js'; +import { UmbModalHandler, UmbModalService } from '@umbraco-cms/services'; +import type { UserDetails } from '@umbraco-cms/models'; +import { UmbUserStore } from 'src/core/stores/user/user.store'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; +import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; + +@customElement('umb-modal-layout-change-password') +export class UmbModalLayoutChangePasswordElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { + static styles: CSSResultGroup = [ + UUITextStyles, + css` + :host { + display: block; + } + :host, + umb-editor-entity-layout { + width: 100%; + height: 100%; + } + #main { + padding: var(--uui-size-space-5); + display: flex; + flex-direction: column; + gap: var(--uui-size-space-3); + } + `, + ]; + + @property({ attribute: false }) + modalHandler?: UmbModalHandler; + + private _close() { + this.modalHandler?.close(); + } + + private _handleSubmit(e: Event) { + e.preventDefault(); + console.log('IMPLEMENT SUBMIT'); + this._close(); + } + + render() { + return html` + + +
+ + Old password + + +
+ + New password + + + + Confirm password + + + + + +
+
+
+ `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-modal-layout-change-password': UmbModalLayoutChangePasswordElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index 9fb582943e..ceb30eab14 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -1,7 +1,7 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, CSSResultGroup, html, LitElement } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; -import { UmbModalHandler } from '@umbraco-cms/services'; +import { UmbModalHandler, UmbModalService } from '@umbraco-cms/services'; import type { UserDetails } from '@umbraco-cms/models'; import { UmbUserStore } from 'src/core/stores/user/user.store'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; @@ -36,11 +36,13 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb private _currentUser?: UserDetails; private _userStore?: UmbUserStore; + private _modalService?: UmbModalService; constructor() { super(); - this.consumeAllContexts(['umbUserStore'], (instances) => { + this.consumeAllContexts(['umbUserStore', 'umbModalService'], (instances) => { this._userStore = instances['umbUserStore']; + this._modalService = instances['umbModalService']; this._observeCurrentUser(); }); } @@ -63,6 +65,11 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb this._close(); } + private _changePassword() { + if (!this._modalService) return; + this._modalService.changePassword(); + } + render() { return html` @@ -70,7 +77,7 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb Your profile Edit - Logout + Change password External login providers @@ -80,6 +87,7 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb
Close + Logout
`; diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts index e8a7d645dd..f7e1397884 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts @@ -3,6 +3,7 @@ import './layouts/confirm/modal-layout-confirm.element'; import './layouts/content-picker/modal-layout-content-picker.element'; import './layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.element'; import './layouts/modal-layout-user-dialog.element'; +import './layouts/modal-layout-change-password.element'; import { UUIModalSidebarSize } from '@umbraco-ui/uui-modal-sidebar'; import { BehaviorSubject, Observable } from 'rxjs'; @@ -79,6 +80,16 @@ export class UmbModalService { return this.open('umb-modal-layout-user-dialog', { type: 'sidebar', size: 'small' }); } + /** + * Opens the user settings sidebar modal + * @public + * @return {*} {UmbModalHandler} + * @memberof UmbModalService + */ + public changePassword(): UmbModalHandler { + return this.open('umb-modal-layout-change-password', { type: 'dialog' }); + } + /** * Opens a modal or sidebar modal * @public From 5d15b87f0852f6c89cc214f6ff203ff0531eee64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Thu, 24 Nov 2022 21:51:53 +0100 Subject: [PATCH 061/223] change password: validation and no old password on admin --- .../editors/user/editor-user.element.ts | 19 ++++++-- .../modal-layout-change-password.element.ts | 46 +++++++++++++------ 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts index 8017ef3597..a7020a3877 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts @@ -15,6 +15,7 @@ import '../../property-editor-uis/content-picker/property-editor-ui-content-pick import '../shared/editor-entity-layout/editor-entity-layout.element'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; +import { UmbModalService } from '@umbraco-cms/services'; @customElement('umb-editor-user') export class UmbEditorUserElement extends UmbContextProviderMixin( @@ -103,9 +104,10 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( @property({ type: String }) entityKey = ''; - protected _userStore?: UmbUserStore; - protected _usersSubscription?: Subscription; + private _userStore?: UmbUserStore; + private _usersSubscription?: Subscription; private _userContext?: UmbUserContext; + private _modalService?: UmbModalService; private _userNameSubscription?: Subscription; @@ -113,8 +115,10 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( constructor() { super(); - this.consumeAllContexts(['umbUserStore'], (instances) => { + this.consumeAllContexts(['umbUserStore', 'umbModalService'], (instances) => { this._userStore = instances['umbUserStore']; + this._modalService = instances['umbModalService']; + this._observeCurrentUser(); this._observeUser(); }); @@ -201,7 +205,14 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( history.pushState(null, '', '/section/users/view/users/overview'); } + private _changePassword() { + this._modalService?.changePassword(); + } + private _renderActionButtons() { + if (this._currentUser?.key === this._user?.key) + return html` `; + return html` ${this._user?.status !== 'invited' ? html`
- ${this._currentUser?.key !== this._user.key ? this._renderActionButtons() : nothing} + ${this._renderActionButtons()}
Status: diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts index 4a7fbe4cdb..62695985a4 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts @@ -1,5 +1,5 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { css, CSSResultGroup, html, LitElement } from 'lit'; +import { css, CSSResultGroup, html, LitElement, nothing } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { UmbModalHandler, UmbModalService } from '@umbraco-cms/services'; import type { UserDetails } from '@umbraco-cms/models'; @@ -32,30 +32,50 @@ export class UmbModalLayoutChangePasswordElement extends UmbContextConsumerMixin @property({ attribute: false }) modalHandler?: UmbModalHandler; + @state() + private _requireOldPassword = false; //TODO: Implement check to see if current user is an admin. + private _close() { this.modalHandler?.close(); } - private _handleSubmit(e: Event) { + private _handleSubmit(e: SubmitEvent) { e.preventDefault(); - console.log('IMPLEMENT SUBMIT'); + + const form = e.target as HTMLFormElement; + if (!form) return; + + const isValid = form.checkValidity(); + if (!isValid) return; + + const formData = new FormData(form); + + const oldPassword = formData.get('oldPassword') as string; + const newPassword = formData.get('newPassword') as string; + const confirmPassword = formData.get('confirmPassword') as string; + console.log('IMPLEMENT SUBMIT', { oldPassword, newPassword, confirmPassword }); this._close(); } + private _renderOldPasswordInput() { + return html` + + Old password + + + `; + } + render() { return html` - +
- - Old password - - -
+ ${this._requireOldPassword ? this._renderOldPasswordInput() : nothing} New password Date: Fri, 25 Nov 2022 10:02:14 +0100 Subject: [PATCH 062/223] change password styling --- .../modal-layout-change-password.element.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts index 62695985a4..4223e2df85 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts @@ -14,17 +14,15 @@ export class UmbModalLayoutChangePasswordElement extends UmbContextConsumerMixin css` :host { display: block; + width: 400px; } - :host, - umb-editor-entity-layout { + uui-input-password { width: 100%; - height: 100%; } - #main { - padding: var(--uui-size-space-5); + #actions { display: flex; - flex-direction: column; - gap: var(--uui-size-space-3); + justify-content: flex-end; + margin-top: var(--uui-size-layout-2); } `, ]; @@ -95,8 +93,10 @@ export class UmbModalLayoutChangePasswordElement extends UmbContextConsumerMixin required-message="Confirm password is required"> - - +
+ + +
From 021081da9bd6774fd6a2a21eebf57ceea12770c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Fri, 25 Nov 2022 11:04:36 +0100 Subject: [PATCH 063/223] external login provider extension point and test extension --- .../src/backoffice/backoffice.element.ts | 2 + ...ternal-login-provider-extension.element.ts | 44 +++++++++++++++++++ .../external-login-provider-test.element.ts | 24 ++++++++++ .../external-login-providers/manifests.ts | 16 +++++++ .../registry/extension.registry.ts | 2 + .../external-login-provider.models.ts | 11 +++++ .../src/core/extensions-registry/models.ts | 8 +++- .../modal-layout-user-dialog.element.ts | 27 +++++++++++- 8 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-extension.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/extensions-registry/external-login-provider.models.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index e4969b2511..70ffa658fc 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -31,6 +31,7 @@ import { manifests as propertyEditorUIManifests } from './property-editor-uis/ma import { manifests as treeManifests } from './trees/manifests'; import { manifests as editorManifests } from './editors/manifests'; import { manifests as propertyActionManifests } from './property-actions/manifests'; +import { manifests as externalLoginProviderManifests } from './external-login-providers/manifests'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import type { ManifestTypes, ManifestWithLoader } from '@umbraco-cms/models'; @@ -64,6 +65,7 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this._registerExtensions(propertyEditorModelManifests); this._registerExtensions(propertyEditorUIManifests); this._registerExtensions(propertyActionManifests); + this._registerExtensions(externalLoginProviderManifests); this._umbIconRegistry.attach(this); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-extension.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-extension.element.ts new file mode 100644 index 0000000000..db338650e1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-extension.element.ts @@ -0,0 +1,44 @@ +import { CSSResultGroup, html, LitElement } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property, state } from 'lit/decorators.js'; +import { createExtensionElement } from '@umbraco-cms/extensions-api'; +import type { ManifestExternalLoginProvider } from '@umbraco-cms/models'; + +@customElement('umb-external-login-provider-extension') +export class UmbExternalLoginProviderExtensionElement extends LitElement { + static styles: CSSResultGroup = [UUITextStyles]; + + private _externalLoginProvider?: ManifestExternalLoginProvider; + + @property({ type: Object }) + public get externalLoginProvider(): ManifestExternalLoginProvider | undefined { + return this._externalLoginProvider; + } + public set externalLoginProvider(value: ManifestExternalLoginProvider | undefined) { + this._externalLoginProvider = value; + this._createElement(); + } + + @state() + private _element?: any; + + private async _createElement() { + if (!this.externalLoginProvider) return; + + try { + this._element = (await createExtensionElement(this.externalLoginProvider)) as any | undefined; + } catch (error) { + // TODO: loading JS failed so we should do some nice UI. (This does only happen if extension has a js prop, otherwise we concluded that no source was needed resolved the load.) + } + } + + render() { + return html`${this._element}`; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-external-login-provider-extension': UmbExternalLoginProviderExtensionElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test.element.ts new file mode 100644 index 0000000000..af85d3cc4f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test.element.ts @@ -0,0 +1,24 @@ +import { css, html, LitElement } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement } from 'lit/decorators.js'; +import { UmbContextProviderMixin, UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; + +@customElement('umb-external-login-provider-test') +export class UmbExternalLoginProviderTestElement extends UmbContextProviderMixin( + UmbContextConsumerMixin(UmbObserverMixin(LitElement)) +) { + static styles = [UUITextStyles, css``]; + + render() { + return html`
MY CUSTOM EXTENSION LETS GOO
`; + } +} + +export default UmbExternalLoginProviderTestElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-external-login-provider-test': UmbExternalLoginProviderTestElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/manifests.ts new file mode 100644 index 0000000000..affde880c2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/manifests.ts @@ -0,0 +1,16 @@ +import type { ManifestExternalLoginProvider, ManifestWithLoader } from '@umbraco-cms/models'; + +export const manifests: Array> = [ + { + type: 'externalLoginProvider', + alias: 'Umb.ExternalLoginProvider.Test', + name: 'Test External Login Provider', + elementName: 'umb-external-login-provider-test', + loader: () => import('./external-login-provider-test.element'), + weight: 600, + meta: { + label: 'Test External Login Provider', + pathname: 'test/test/test', + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/core/extensions-api/registry/extension.registry.ts b/src/Umbraco.Web.UI.Client/src/core/extensions-api/registry/extension.registry.ts index 8da2169429..eac7d95c11 100644 --- a/src/Umbraco.Web.UI.Client/src/core/extensions-api/registry/extension.registry.ts +++ b/src/Umbraco.Web.UI.Client/src/core/extensions-api/registry/extension.registry.ts @@ -15,6 +15,7 @@ import type { ManifestEditorAction, ManifestCustom, ManifestPackageView, + ManifestExternalLoginProvider, } from '../../models'; import { createExtensionElement } from '../create-extension-element.function'; @@ -67,6 +68,7 @@ export class UmbExtensionRegistry { extensionsOfType(type: 'packageView'): Observable>; extensionsOfType(type: 'entrypoint'): Observable>; extensionsOfType(type: 'custom'): Observable>; + extensionsOfType(type: 'externalLoginProvider'): Observable>; extensionsOfType(type: string): Observable>; extensionsOfType(type: string): Observable> { return this.extensions.pipe( diff --git a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/external-login-provider.models.ts b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/external-login-provider.models.ts new file mode 100644 index 0000000000..ebc0588bc9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/external-login-provider.models.ts @@ -0,0 +1,11 @@ +import type { ManifestElement } from './models'; + +export interface ManifestExternalLoginProvider extends ManifestElement { + type: 'externalLoginProvider'; + meta: MetaExternalLoginProvider; +} + +export interface MetaExternalLoginProvider { + label: string; + pathname: string; +} diff --git a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/models.ts b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/models.ts index f2193cc413..df15da06d4 100644 --- a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/models.ts +++ b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/models.ts @@ -9,6 +9,7 @@ import type { ManifestPropertyEditorUI, ManifestPropertyEditorModel } from './pr import type { ManifestDashboard } from './dashboard.models'; import type { ManifestPropertyAction } from './property-action.models'; import type { ManifestPackageView } from './package-view.models'; +import type { ManifestExternalLoginProvider } from './external-login-provider.models'; export * from './section.models'; export * from './section-view.models'; @@ -21,6 +22,7 @@ export * from './property-editor.models'; export * from './dashboard.models'; export * from './property-action.models'; export * from './package-view.models'; +export * from './external-login-provider.models'; export type ManifestTypes = | ManifestSection @@ -36,7 +38,8 @@ export type ManifestTypes = | ManifestPropertyAction | ManifestPackageView | ManifestEntrypoint - | ManifestCustom; + | ManifestCustom + | ManifestExternalLoginProvider; export type ManifestStandardTypes = | 'section' @@ -51,7 +54,8 @@ export type ManifestStandardTypes = | 'dashboard' | 'propertyAction' | 'packageView' - | 'entrypoint'; + | 'entrypoint' + | 'externalLoginProvider'; export type ManifestElementType = | ManifestSection diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index ceb30eab14..107f69f32e 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -2,10 +2,12 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, CSSResultGroup, html, LitElement } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { UmbModalHandler, UmbModalService } from '@umbraco-cms/services'; -import type { UserDetails } from '@umbraco-cms/models'; +import type { ManifestExternalLoginProvider, UserDetails } from '@umbraco-cms/models'; import { UmbUserStore } from 'src/core/stores/user/user.store'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; +import '../../../../backoffice/external-login-providers/external-login-provider-extension.element'; @customElement('umb-modal-layout-user-dialog') export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { @@ -35,6 +37,9 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb @state() private _currentUser?: UserDetails; + @state() + private _externalLoginProviders: Array = []; + private _userStore?: UmbUserStore; private _modalService?: UmbModalService; @@ -45,6 +50,8 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb this._modalService = instances['umbModalService']; this._observeCurrentUser(); }); + + this._observeExternalLoginProviders(); } private async _observeCurrentUser() { @@ -55,6 +62,16 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb }); } + private _observeExternalLoginProviders() { + this.observe( + umbExtensionsRegistry.extensionsOfType('externalLoginProvider'), + (loginProvider) => { + this._externalLoginProviders = loginProvider; + console.log('loginProvider', loginProvider); + } + ); + } + private _close() { this.modalHandler?.close(); } @@ -84,6 +101,14 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb Edit your Umbraco ID profile Change your Umbraco ID password + +
+ ${this._externalLoginProviders.map( + (provider) => + html`` + )} +
Close From 60691e872ef1c8bfa4bde006778ded6a74800a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Fri, 25 Nov 2022 11:28:47 +0100 Subject: [PATCH 064/223] external login provider styling --- .../external-login-provider-test.element.ts | 24 +++++++++++++++++-- .../modal-layout-user-dialog.element.ts | 17 ++++++++----- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test.element.ts index af85d3cc4f..8d502d2e98 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test.element.ts @@ -8,10 +8,30 @@ import { UmbObserverMixin } from '@umbraco-cms/observable-api'; export class UmbExternalLoginProviderTestElement extends UmbContextProviderMixin( UmbContextConsumerMixin(UmbObserverMixin(LitElement)) ) { - static styles = [UUITextStyles, css``]; + static styles = [ + UUITextStyles, + css` + :host { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-4); + padding: var(--uui-size-space-5); + border: 1px solid var(--uui-color-border); + background: var(--uui-color-surface-alt); + border-radius: var(--uui-border-radius); + } + p { + margin: 0; + } + `, + ]; render() { - return html`
MY CUSTOM EXTENSION LETS GOO
`; + return html` + Custom External Login Provider +

This is an example of a custom external login provider using the external login provider extension point

+ + `; } } diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index 107f69f32e..4b22d1685d 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -28,6 +28,11 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb flex-direction: column; gap: var(--uui-size-space-3); } + #umbraco-id-buttons { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-3); + } `, ]; @@ -98,17 +103,17 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb External login providers - Edit your Umbraco ID profile - Change your Umbraco ID password - - -
+
+ Edit your Umbraco ID profile + Change your Umbraco ID password +
+
${this._externalLoginProviders.map( (provider) => html`` )} -
+
Close From 8557c366bb158796b6e87398022d1fc5a569fdce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Fri, 25 Nov 2022 11:34:39 +0100 Subject: [PATCH 065/223] more external login provider examples --- .../external-login-provider-test2.element.ts | 57 +++++++++++++++++++ .../external-login-providers/manifests.ts | 14 ++++- .../modal-layout-user-dialog.element.ts | 4 ++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test2.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test2.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test2.element.ts new file mode 100644 index 0000000000..955ad87749 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test2.element.ts @@ -0,0 +1,57 @@ +import { css, html, LitElement } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement } from 'lit/decorators.js'; +import { UmbContextProviderMixin, UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; + +@customElement('umb-external-login-provider-test2') +export class UmbExternalLoginProviderTest2Element extends UmbContextProviderMixin( + UmbContextConsumerMixin(UmbObserverMixin(LitElement)) +) { + static styles = [ + UUITextStyles, + css` + :host { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-4); + padding: var(--uui-size-space-5); + border: 1px solid var(--uui-color-border); + background: var(--uui-color-surface-alt); + border-radius: var(--uui-border-radius); + } + p { + margin: 0; + } + uui-input { + width: 100%; + } + `, + ]; + + render() { + return html` + Another Custom External Login Provider +

This is an example of another custom external login provider

+ + Email + + + + `; + } +} + +export default UmbExternalLoginProviderTest2Element; + +declare global { + interface HTMLElementTagNameMap { + 'umb-external-login-provider-test2': UmbExternalLoginProviderTest2Element; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/manifests.ts index affde880c2..5812b461c8 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/manifests.ts @@ -7,10 +7,22 @@ export const manifests: Array> name: 'Test External Login Provider', elementName: 'umb-external-login-provider-test', loader: () => import('./external-login-provider-test.element'), - weight: 600, + weight: 2, meta: { label: 'Test External Login Provider', pathname: 'test/test/test', }, }, + { + type: 'externalLoginProvider', + alias: 'Umb.ExternalLoginProvider.Test2', + name: 'Test External Login Provider 2', + elementName: 'umb-external-login-provider-test2', + loader: () => import('./external-login-provider-test2.element'), + weight: 1, + meta: { + label: 'Test External Login Provider 2', + pathname: 'test/test/test', + }, + }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index 4b22d1685d..c74d824953 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -33,6 +33,10 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb flex-direction: column; gap: var(--uui-size-space-3); } + umb-external-login-provider-extension:not(:last-child) { + margin-bottom: var(--uui-size-space-3); + display: block; + } `, ]; From bce31c40c67b0c96f4e47050568bf13c55706972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Fri, 25 Nov 2022 12:13:14 +0100 Subject: [PATCH 066/223] user dashboard extension point at test extension --- .../src/backoffice/backoffice.element.ts | 2 + .../backoffice/user-dashboards/manifests.ts | 16 +++++++ .../user-dashboard-extension.element.ts | 44 +++++++++++++++++++ .../user-dashboard-test.element.ts | 44 +++++++++++++++++++ .../src/core/extensions-registry/models.ts | 8 +++- .../user-dashboard.models.ts | 11 +++++ .../modal-layout-user-dialog.element.ts | 27 +++++++++--- 7 files changed, 143 insertions(+), 9 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-extension.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-test.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/extensions-registry/user-dashboard.models.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index 70ffa658fc..ec29944136 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -32,6 +32,7 @@ import { manifests as treeManifests } from './trees/manifests'; import { manifests as editorManifests } from './editors/manifests'; import { manifests as propertyActionManifests } from './property-actions/manifests'; import { manifests as externalLoginProviderManifests } from './external-login-providers/manifests'; +import { manifests as userDashboards } from './user-dashboards/manifests'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import type { ManifestTypes, ManifestWithLoader } from '@umbraco-cms/models'; @@ -66,6 +67,7 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this._registerExtensions(propertyEditorUIManifests); this._registerExtensions(propertyActionManifests); this._registerExtensions(externalLoginProviderManifests); + this._registerExtensions(userDashboards); this._umbIconRegistry.attach(this); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/manifests.ts new file mode 100644 index 0000000000..d3bc69a31c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/manifests.ts @@ -0,0 +1,16 @@ +import type { ManifestExternalLoginProvider, ManifestWithLoader } from '@umbraco-cms/models'; + +export const manifests: Array> = [ + { + type: 'userDashboard', + alias: 'Umb.UserDashboard.Test', + name: 'Test User Dashboard', + elementName: 'umb-user-dashboard-test', + loader: () => import('./user-dashboard-test.element'), + weight: 2, + meta: { + label: 'Test User Dashboard', + pathname: 'test/test/test', + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-extension.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-extension.element.ts new file mode 100644 index 0000000000..85ad951331 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-extension.element.ts @@ -0,0 +1,44 @@ +import { CSSResultGroup, html, LitElement } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property, state } from 'lit/decorators.js'; +import { createExtensionElement } from '@umbraco-cms/extensions-api'; +import type { ManifestUserDashboard } from '@umbraco-cms/models'; + +@customElement('umb-user-dashboard-extension') +export class UmbUserDashboardExtensionElement extends LitElement { + static styles: CSSResultGroup = [UUITextStyles]; + + private _userDashboard?: ManifestUserDashboard; + + @property({ type: Object }) + public get userDashboard(): ManifestUserDashboard | undefined { + return this._userDashboard; + } + public set userDashboard(value: ManifestUserDashboard | undefined) { + this._userDashboard = value; + this._createElement(); + } + + @state() + private _element?: any; + + private async _createElement() { + if (!this.userDashboard) return; + + try { + this._element = (await createExtensionElement(this.userDashboard)) as any | undefined; + } catch (error) { + // TODO: loading JS failed so we should do some nice UI. (This does only happen if extension has a js prop, otherwise we concluded that no source was needed resolved the load.) + } + } + + render() { + return html`${this._element}`; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-user-dashboard-extension': UmbUserDashboardExtensionElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-test.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-test.element.ts new file mode 100644 index 0000000000..ede0abf1ff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-test.element.ts @@ -0,0 +1,44 @@ +import { css, html, LitElement } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement } from 'lit/decorators.js'; +import { UmbContextProviderMixin, UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; + +@customElement('umb-user-dashboard-test') +export class UmbUserDashboardTestElement extends UmbContextProviderMixin( + UmbContextConsumerMixin(UmbObserverMixin(LitElement)) +) { + static styles = [ + UUITextStyles, + css` + :host { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-4); + padding: var(--uui-size-space-5); + border: 1px solid var(--uui-color-border); + background: var(--uui-color-positive); + color: var(--uui-color-positive-contrast); + border-radius: var(--uui-border-radius); + } + p { + margin: 0; + } + `, + ]; + + render() { + return html` + Custom User Dashboard +

This is an example of a custom user dashboard using the user dashboard extension point

+ `; + } +} + +export default UmbUserDashboardTestElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-user-dashboard-test': UmbUserDashboardTestElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/models.ts b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/models.ts index df15da06d4..076f86078a 100644 --- a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/models.ts +++ b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/models.ts @@ -10,6 +10,7 @@ import type { ManifestDashboard } from './dashboard.models'; import type { ManifestPropertyAction } from './property-action.models'; import type { ManifestPackageView } from './package-view.models'; import type { ManifestExternalLoginProvider } from './external-login-provider.models'; +import { ManifestUserDashboard } from './user-dashboard.models'; export * from './section.models'; export * from './section-view.models'; @@ -23,6 +24,7 @@ export * from './dashboard.models'; export * from './property-action.models'; export * from './package-view.models'; export * from './external-login-provider.models'; +export * from './user-dashboard.models'; export type ManifestTypes = | ManifestSection @@ -39,7 +41,8 @@ export type ManifestTypes = | ManifestPackageView | ManifestEntrypoint | ManifestCustom - | ManifestExternalLoginProvider; + | ManifestExternalLoginProvider + | ManifestUserDashboard; export type ManifestStandardTypes = | 'section' @@ -55,7 +58,8 @@ export type ManifestStandardTypes = | 'propertyAction' | 'packageView' | 'entrypoint' - | 'externalLoginProvider'; + | 'externalLoginProvider' + | 'userDashboard'; export type ManifestElementType = | ManifestSection diff --git a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/user-dashboard.models.ts b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/user-dashboard.models.ts new file mode 100644 index 0000000000..a9fd823c55 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/user-dashboard.models.ts @@ -0,0 +1,11 @@ +import type { ManifestElement } from './models'; + +export interface ManifestUserDashboard extends ManifestElement { + type: 'userDashboard'; + meta: MetaUserDashboard; +} + +export interface MetaUserDashboard { + label: string; + pathname: string; +} diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index c74d824953..8918cb3214 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -2,12 +2,13 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, CSSResultGroup, html, LitElement } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { UmbModalHandler, UmbModalService } from '@umbraco-cms/services'; -import type { ManifestExternalLoginProvider, UserDetails } from '@umbraco-cms/models'; +import type { ManifestExternalLoginProvider, ManifestUserDashboard, UserDetails } from '@umbraco-cms/models'; import { UmbUserStore } from 'src/core/stores/user/user.store'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import '../../../../backoffice/external-login-providers/external-login-provider-extension.element'; +import '../../../../backoffice/user-dashboards/user-dashboard-extension.element'; @customElement('umb-modal-layout-user-dialog') export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { @@ -49,6 +50,9 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb @state() private _externalLoginProviders: Array = []; + @state() + private _userDashboards: Array = []; + private _userStore?: UmbUserStore; private _modalService?: UmbModalService; @@ -61,6 +65,7 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb }); this._observeExternalLoginProviders(); + this._observeUserDashboards(); } private async _observeCurrentUser() { @@ -76,11 +81,17 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb umbExtensionsRegistry.extensionsOfType('externalLoginProvider'), (loginProvider) => { this._externalLoginProviders = loginProvider; - console.log('loginProvider', loginProvider); } ); } + private _observeUserDashboards() { + this.observe(umbExtensionsRegistry.extensionsOfType('userDashboard'), (userDashboard) => { + this._userDashboards = userDashboard; + console.log(this._userDashboards); + }); + } + private _close() { this.modalHandler?.close(); } @@ -107,17 +118,19 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb External login providers -
- Edit your Umbraco ID profile - Change your Umbraco ID password -
-
${this._externalLoginProviders.map( (provider) => html`` )}
+ + User Dashboards + ${this._userDashboards.map( + (provider) => + html`` + )} +
Close From 17d0876716aad4a799f2bb050eb2a9428e90b107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Fri, 25 Nov 2022 15:39:56 +0100 Subject: [PATCH 067/223] fix styling --- .../modal/layouts/modal-layout-user-dialog.element.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index 8918cb3214..d75c9c6c32 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -124,13 +124,12 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb .externalLoginProvider=${provider}>` )} - - User Dashboards +
${this._userDashboards.map( (provider) => html`` )} - +
Close From ffcb9d4c2f49fa9ad73990f671d083017f959321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Mon, 28 Nov 2022 09:40:07 +0100 Subject: [PATCH 068/223] add history service --- .../src/backoffice/backoffice.element.ts | 2 ++ .../core/services/history/history.service.ts | 32 +++++++++++++++++++ .../src/core/services/history/index.ts | 1 + 3 files changed, 35 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/services/history/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index ec29944136..1ae4f5c181 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -36,6 +36,7 @@ import { manifests as userDashboards } from './user-dashboards/manifests'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import type { ManifestTypes, ManifestWithLoader } from '@umbraco-cms/models'; +import { UmbHistoryService } from 'src/core/services/history'; @defineElement('umb-backoffice') export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProviderMixin(LitElement)) { @@ -78,6 +79,7 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this.provideContext('umbUserStore', new UmbUserStore(this._umbEntityStore)); this.provideContext('umbUserGroupStore', new UmbUserGroupStore(this._umbEntityStore)); this.provideContext('umbNotificationService', new UmbNotificationService()); + this.provideContext('umbHistoryService', new UmbHistoryService()); this.provideContext('umbModalService', new UmbModalService()); this.provideContext('umbSectionStore', new UmbSectionStore()); } diff --git a/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts b/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts new file mode 100644 index 0000000000..fac73ae8d7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts @@ -0,0 +1,32 @@ +import { BehaviorSubject, Observable } from 'rxjs'; + +export type UmbModelType = 'dialog' | 'sidebar'; + +export type UmbHistoryItem = { + path: string; + icon?: string; +}; + +export class UmbHistoryService { + private _history: BehaviorSubject> = new BehaviorSubject(>[]); + public readonly history: Observable> = this._history.asObservable(); + + /** + * Pushes a new history item to the history array + * @public + * @param {UmbHistoryItem} historyItem + * @memberof UmbHistoryService + */ + public push(historyItem: UmbHistoryItem): void { + this._history.next([...this._history.getValue(), historyItem]); + } + + /** + * Clears the history array + * @public + * @memberof UmbHistoryService + */ + public clear() { + this._history.next([]); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/core/services/history/index.ts b/src/Umbraco.Web.UI.Client/src/core/services/history/index.ts new file mode 100644 index 0000000000..76f55618be --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/services/history/index.ts @@ -0,0 +1 @@ +export * from './history.service'; From 1be01a7599504b03f6949177a5f8e8fe440dd13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Mon, 28 Nov 2022 09:43:26 +0100 Subject: [PATCH 069/223] fix user dashboard manifest --- .../src/backoffice/user-dashboards/manifests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/manifests.ts index d3bc69a31c..9259cad147 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/manifests.ts @@ -1,6 +1,6 @@ -import type { ManifestExternalLoginProvider, ManifestWithLoader } from '@umbraco-cms/models'; +import type { ManifestUserDashboard, ManifestWithLoader } from '@umbraco-cms/models'; -export const manifests: Array> = [ +export const manifests: Array> = [ { type: 'userDashboard', alias: 'Umb.UserDashboard.Test', From e6c163e59be06f7a92f6dd90b64b3d921d1b4681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Mon, 28 Nov 2022 10:40:24 +0100 Subject: [PATCH 070/223] render history items --- .../core/services/history/history.service.ts | 15 +++- .../modal-layout-user-dialog.element.ts | 89 ++++++++++++++++--- 2 files changed, 93 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts b/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts index fac73ae8d7..380a12e166 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts @@ -4,11 +4,24 @@ export type UmbModelType = 'dialog' | 'sidebar'; export type UmbHistoryItem = { path: string; + label: string | Array; icon?: string; }; export class UmbHistoryService { - private _history: BehaviorSubject> = new BehaviorSubject(>[]); + private _history: BehaviorSubject> = new BehaviorSubject(>[ + { label: 'Users grid', path: 'section/users/view/users/overview/grid' }, + { label: ['User', 'Nat Linnane'], path: 'section/users/view/users/user/50f184d4-71f3-4a43-b8be-7a36340fbd0d' }, + { + label: ['User Group', 'Administrator'], + path: 'section/users/view/users/userGroup/10000000-0000-0000-0000-000000000000', + }, + { label: 'About us', path: 'section/content/document/74e4008a-ea4f-4793-b924-15e02fd380d2/view/content' }, + { + label: ['Blog', 'Look at this nice history page!'], + path: 'section/content/document/74e4008a-ea4f-4793-b924-15e02fd380d2/view/content', + }, + ]); public readonly history: Observable> = this._history.asObservable(); /** diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index d75c9c6c32..2ba707912d 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -1,6 +1,7 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { css, CSSResultGroup, html, LitElement } from 'lit'; +import { css, CSSResultGroup, html, LitElement, nothing } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; +import { UmbHistoryItem, UmbHistoryService } from '../../history'; import { UmbModalHandler, UmbModalService } from '@umbraco-cms/services'; import type { ManifestExternalLoginProvider, ManifestUserDashboard, UserDetails } from '@umbraco-cms/models'; import { UmbUserStore } from 'src/core/stores/user/user.store'; @@ -38,6 +39,33 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb margin-bottom: var(--uui-size-space-3); display: block; } + #recent-history { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-3); + } + #recent-history-items { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-2); + } + .history-item { + color: inherit; + text-decoration: none; + } + .history-item-name-separator { + margin: 0 var(--uui-size-space-1); + } + .history-item-path, + .history-item-name-separator { + opacity: 0.4; + } + .history-item-name, + .history-item-path { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } `, ]; @@ -53,29 +81,27 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb @state() private _userDashboards: Array = []; + @state() + private _history: Array = []; + private _userStore?: UmbUserStore; private _modalService?: UmbModalService; + private _historyService?: UmbHistoryService; constructor() { super(); - this.consumeAllContexts(['umbUserStore', 'umbModalService'], (instances) => { + this.consumeAllContexts(['umbUserStore', 'umbModalService', 'umbHistoryService'], (instances) => { this._userStore = instances['umbUserStore']; this._modalService = instances['umbModalService']; + this._historyService = instances['umbHistoryService']; this._observeCurrentUser(); + this._observeHistory(); }); this._observeExternalLoginProviders(); this._observeUserDashboards(); } - private async _observeCurrentUser() { - if (!this._userStore) return; - - this.observe(this._userStore.currentUser, (currentUser) => { - this._currentUser = currentUser; - }); - } - private _observeExternalLoginProviders() { this.observe( umbExtensionsRegistry.extensionsOfType('externalLoginProvider'), @@ -85,6 +111,21 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb ); } + private async _observeCurrentUser() { + if (!this._userStore) return; + + this.observe(this._userStore.currentUser, (currentUser) => { + this._currentUser = currentUser; + }); + } + private async _observeHistory() { + if (!this._historyService) return; + + this.observe>(this._historyService.history, (history) => { + this._history = history; + }); + } + private _observeUserDashboards() { this.observe(umbExtensionsRegistry.extensionsOfType('userDashboard'), (userDashboard) => { this._userDashboards = userDashboard; @@ -107,6 +148,30 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb this._modalService.changePassword(); } + private _renderHistoryItem(item: UmbHistoryItem) { + if (typeof item.label === 'string') { + return html` +
${item.label}
+
`; + } + if (Array.isArray(item.label)) { + console.log('hallo', item); + + return html` + +
+ ${item.label.map((name, index) => { + return html`${name}${index < item.label.length - 1 ? '>' : nothing}`; + })} +
+
+ `; + } + + return nothing; + } + render() { return html` @@ -130,6 +195,10 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb html`` )}
+
+ Recent History +
${this._history.map((item) => html`${this._renderHistoryItem(item)}`)}
+
Close From 9b7a7bb326590962f8969bad8d853850f5121d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Mon, 28 Nov 2022 10:43:43 +0100 Subject: [PATCH 071/223] make history service static --- .../src/backoffice/backoffice.element.ts | 3 --- .../src/core/services/history/history.service.ts | 4 +++- .../layouts/modal-layout-user-dialog.element.ts | 12 ++++-------- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index 1ae4f5c181..a5dde252d9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -36,8 +36,6 @@ import { manifests as userDashboards } from './user-dashboards/manifests'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import type { ManifestTypes, ManifestWithLoader } from '@umbraco-cms/models'; -import { UmbHistoryService } from 'src/core/services/history'; - @defineElement('umb-backoffice') export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProviderMixin(LitElement)) { static styles = [ @@ -79,7 +77,6 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this.provideContext('umbUserStore', new UmbUserStore(this._umbEntityStore)); this.provideContext('umbUserGroupStore', new UmbUserGroupStore(this._umbEntityStore)); this.provideContext('umbNotificationService', new UmbNotificationService()); - this.provideContext('umbHistoryService', new UmbHistoryService()); this.provideContext('umbModalService', new UmbModalService()); this.provideContext('umbSectionStore', new UmbSectionStore()); } diff --git a/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts b/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts index 380a12e166..1c346626be 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts @@ -8,7 +8,7 @@ export type UmbHistoryItem = { icon?: string; }; -export class UmbHistoryService { +class UmbHistoryService { private _history: BehaviorSubject> = new BehaviorSubject(>[ { label: 'Users grid', path: 'section/users/view/users/overview/grid' }, { label: ['User', 'Nat Linnane'], path: 'section/users/view/users/user/50f184d4-71f3-4a43-b8be-7a36340fbd0d' }, @@ -43,3 +43,5 @@ export class UmbHistoryService { this._history.next([]); } } + +export const umbHistoryService = new UmbHistoryService(); diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index 2ba707912d..86edf87f9a 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -1,7 +1,7 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, CSSResultGroup, html, LitElement, nothing } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; -import { UmbHistoryItem, UmbHistoryService } from '../../history'; +import { UmbHistoryItem, umbHistoryService } from '../../history'; import { UmbModalHandler, UmbModalService } from '@umbraco-cms/services'; import type { ManifestExternalLoginProvider, ManifestUserDashboard, UserDetails } from '@umbraco-cms/models'; import { UmbUserStore } from 'src/core/stores/user/user.store'; @@ -86,19 +86,17 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb private _userStore?: UmbUserStore; private _modalService?: UmbModalService; - private _historyService?: UmbHistoryService; constructor() { super(); - this.consumeAllContexts(['umbUserStore', 'umbModalService', 'umbHistoryService'], (instances) => { + this.consumeAllContexts(['umbUserStore', 'umbModalService'], (instances) => { this._userStore = instances['umbUserStore']; this._modalService = instances['umbModalService']; - this._historyService = instances['umbHistoryService']; this._observeCurrentUser(); - this._observeHistory(); }); this._observeExternalLoginProviders(); + this._observeHistory(); this._observeUserDashboards(); } @@ -119,9 +117,7 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb }); } private async _observeHistory() { - if (!this._historyService) return; - - this.observe>(this._historyService.history, (history) => { + this.observe>(umbHistoryService.history, (history) => { this._history = history; }); } From 9e8d825fae000cda11fd43bcf00c4eb88c813f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Mon, 28 Nov 2022 10:49:11 +0100 Subject: [PATCH 072/223] remove path --- .../modal/layouts/modal-layout-user-dialog.element.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index 86edf87f9a..b4d145f22e 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -56,12 +56,11 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb .history-item-name-separator { margin: 0 var(--uui-size-space-1); } - .history-item-path, + .history-item-name-separator { opacity: 0.4; } - .history-item-name, - .history-item-path { + .history-item-name { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; From 9b73c7a359d8f668c8b7c2ad77ba29925a050437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Mon, 28 Nov 2022 11:05:43 +0100 Subject: [PATCH 073/223] prevent duplicates in history --- .../core/services/history/history.service.ts | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts b/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts index 1c346626be..f1037e3816 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/history/history.service.ts @@ -9,19 +9,7 @@ export type UmbHistoryItem = { }; class UmbHistoryService { - private _history: BehaviorSubject> = new BehaviorSubject(>[ - { label: 'Users grid', path: 'section/users/view/users/overview/grid' }, - { label: ['User', 'Nat Linnane'], path: 'section/users/view/users/user/50f184d4-71f3-4a43-b8be-7a36340fbd0d' }, - { - label: ['User Group', 'Administrator'], - path: 'section/users/view/users/userGroup/10000000-0000-0000-0000-000000000000', - }, - { label: 'About us', path: 'section/content/document/74e4008a-ea4f-4793-b924-15e02fd380d2/view/content' }, - { - label: ['Blog', 'Look at this nice history page!'], - path: 'section/content/document/74e4008a-ea4f-4793-b924-15e02fd380d2/view/content', - }, - ]); + private _history: BehaviorSubject> = new BehaviorSubject(>[]); public readonly history: Observable> = this._history.asObservable(); /** @@ -31,7 +19,18 @@ class UmbHistoryService { * @memberof UmbHistoryService */ public push(historyItem: UmbHistoryItem): void { - this._history.next([...this._history.getValue(), historyItem]); + const history = this._history.getValue(); + const lastItem = history[history.length - 1]; + + // This prevents duplicate entries in the history array. + if (!lastItem || lastItem.path !== historyItem.path) { + this._history.next([...this._history.getValue(), historyItem]); + } else { + //Update existing item + const newHistory = this._history.getValue(); + newHistory[history.length - 1] = historyItem; + this._history.next(newHistory); + } } /** From 94cd54293f269ce1f2f5fb6a3f8c7df06c35884d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Mon, 28 Nov 2022 11:05:52 +0100 Subject: [PATCH 074/223] implement recent history --- .../src/backoffice/editors/user/editor-user.element.ts | 4 ++++ .../list-view-layouts/grid/editor-view-users-grid.element.ts | 2 ++ .../table/editor-view-users-table.element.ts | 2 ++ 3 files changed, 8 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts index a7020a3877..3fd2a81d29 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts @@ -16,6 +16,7 @@ import '../shared/editor-entity-layout/editor-entity-layout.element'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbModalService } from '@umbraco-cms/services'; +import { umbHistoryService } from 'src/core/services/history'; @customElement('umb-editor-user') export class UmbEditorUserElement extends UmbContextProviderMixin( @@ -115,6 +116,7 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( constructor() { super(); + this.consumeAllContexts(['umbUserStore', 'umbModalService'], (instances) => { this._userStore = instances['umbUserStore']; this._modalService = instances['umbModalService']; @@ -140,6 +142,8 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( this._user = user; if (!this._user) return; + umbHistoryService.push({ label: ['Users', user.name], path: 'section/users/view/users/user/' + user.key }); + if (!this._userContext) { this._userContext = new UmbUserContext(this._user); this.provideContext('umbUserContext', this._userContext); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/users/list-view-layouts/grid/editor-view-users-grid.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/users/list-view-layouts/grid/editor-view-users-grid.element.ts index 5193831ec3..22e80bf7e3 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/users/list-view-layouts/grid/editor-view-users-grid.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/users/list-view-layouts/grid/editor-view-users-grid.element.ts @@ -9,6 +9,7 @@ import { UmbUserStore } from '../../../../../../../core/stores/user/user.store'; import { getTagLookAndColor } from '../../../../user-extensions'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; import type { UserDetails, UserEntity } from '@umbraco-cms/models'; +import { umbHistoryService } from 'src/core/services/history'; @customElement('umb-editor-view-users-grid') export class UmbEditorViewUsersGridElement extends UmbContextConsumerMixin(LitElement) { @@ -53,6 +54,7 @@ export class UmbEditorViewUsersGridElement extends UmbContextConsumerMixin(LitEl connectedCallback(): void { super.connectedCallback(); + umbHistoryService.push({ label: 'Users grid', path: 'section/users/view/users/overview/grid' }); this.consumeContext('umbUserStore', (userStore: UmbUserStore) => { this._userStore = userStore; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/users/list-view-layouts/table/editor-view-users-table.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/users/list-view-layouts/table/editor-view-users-table.element.ts index 9592318b80..e131786a79 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/users/list-view-layouts/table/editor-view-users-table.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/users/list-view-layouts/table/editor-view-users-table.element.ts @@ -18,6 +18,7 @@ import type { UserDetails } from '@umbraco-cms/models'; import './column-layouts/name/user-table-name-column-layout.element'; import './column-layouts/status/user-table-status-column-layout.element'; +import { umbHistoryService } from 'src/core/services/history'; @customElement('umb-editor-view-users-table') export class UmbEditorViewUsersTableElement extends UmbContextConsumerMixin(LitElement) { @@ -75,6 +76,7 @@ export class UmbEditorViewUsersTableElement extends UmbContextConsumerMixin(LitE connectedCallback(): void { super.connectedCallback(); + umbHistoryService.push({ label: 'Users list', path: 'section/users/view/users/overview/list' }); this.consumeContext('umbUserStore', (userStore: UmbUserStore) => { this._userStore = userStore; From a2c60cee659230181e51f9accb4e95d30bef1cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Mon, 28 Nov 2022 11:26:58 +0100 Subject: [PATCH 075/223] packages and settings history --- .../dashboard-examine-management.element.ts | 12 ++++++++++++ .../views/section-view-examine-indexers.ts | 5 +++++ .../dashboard-models-builder.element.ts | 9 +++++++++ .../dashboard-published-status.element.ts | 5 +++++ .../telemetry/dashboard-telemetry.element.ts | 5 +++++ .../created/section-view-packages-created.element.ts | 6 ++++++ .../section-view-packages-installed.element.ts | 6 ++++++ .../views/repo/section-view-packages-repo.element.ts | 8 ++++++++ .../user-groups/editor-view-user-groups.element.ts | 12 ++++++------ 9 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/dashboard-examine-management.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/dashboard-examine-management.element.ts index f3b68b97a1..c086ee997c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/dashboard-examine-management.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/dashboard-examine-management.element.ts @@ -6,6 +6,7 @@ import { UmbDashboardExamineIndexElement } from './views/section-view-examine-in import { UmbDashboardExamineSearcherElement } from './views/section-view-examine-searchers'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { umbHistoryService } from 'src/core/services/history'; @customElement('umb-dashboard-examine-management') export class UmbDashboardExamineManagementElement extends UmbContextConsumerMixin(LitElement) { @@ -48,6 +49,17 @@ export class UmbDashboardExamineManagementElement extends UmbContextConsumerMixi @state() private _currentPath?: string; + /** + * + */ + constructor() { + super(); + umbHistoryService.push({ + label: ['Settings', 'Examine Management'], + path: 'section/settings/dashboard/examine-management', + }); + } + private _onRouteChange() { this._currentPath = path(); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/views/section-view-examine-indexers.ts b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/views/section-view-examine-indexers.ts index 188c5f0a73..8e70c340ae 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/views/section-view-examine-indexers.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/views/section-view-examine-indexers.ts @@ -10,6 +10,7 @@ import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; import './section-view-examine-searchers'; import { ApiError, ProblemDetails, Index, SearchResource } from '@umbraco-cms/backend-api'; +import { umbHistoryService } from 'src/core/services/history'; @customElement('umb-dashboard-examine-index') export class UmbDashboardExamineIndexElement extends UmbContextConsumerMixin(LitElement) { @@ -95,6 +96,10 @@ export class UmbDashboardExamineIndexElement extends UmbContextConsumerMixin(Lit try { const index = await SearchResource.getSearchIndexByIndexName({ indexName: this.indexName }); this._indexData = index; + umbHistoryService.push({ + label: ['Settings', 'Examine Management', this._indexData.name], + path: 'section/settings/dashboard/examine-management/index/ExternalIndex/' + this._indexData.name, + }); } catch (e) { if (e instanceof ApiError) { const error = e as ProblemDetails; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/models-builder/dashboard-models-builder.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/models-builder/dashboard-models-builder.element.ts index ee13ac50d5..ead297d2d4 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/models-builder/dashboard-models-builder.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/models-builder/dashboard-models-builder.element.ts @@ -1,11 +1,20 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html, LitElement } from 'lit'; import { customElement } from 'lit/decorators.js'; +import { umbHistoryService } from 'src/core/services/history'; @customElement('umb-dashboard-models-builder') export class UmbDashboardModelsBuilderElement extends LitElement { static styles = [UUITextStyles, css``]; + constructor() { + super(); + umbHistoryService.push({ + label: ['Settings', 'Models Builder'], + path: 'section/settings/dashboard/models-builder', + }); + } + render() { return html` diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/published-status/dashboard-published-status.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/published-status/dashboard-published-status.element.ts index 6d0d24b0be..41d33c6989 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/published-status/dashboard-published-status.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/published-status/dashboard-published-status.element.ts @@ -9,6 +9,7 @@ import { UmbNotificationDefaultData } from '../../../core/services/notification/ import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; import { ApiError, ProblemDetails, PublishedCacheResource } from '@umbraco-cms/backend-api'; +import { umbHistoryService } from 'src/core/services/history'; @customElement('umb-dashboard-published-status') export class UmbDashboardPublishedStatusElement extends UmbContextConsumerMixin(LitElement) { @@ -44,6 +45,10 @@ export class UmbDashboardPublishedStatusElement extends UmbContextConsumerMixin( constructor() { super(); + umbHistoryService.push({ + label: ['Settings', 'Published Status'], + path: 'section/settings/dashboard/published-status', + }); this.consumeAllContexts(['umbNotificationService', 'umbModalService'], (instances) => { this._notificationService = instances['umbNotificationService']; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/telemetry/dashboard-telemetry.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/telemetry/dashboard-telemetry.element.ts index d9c7f30e58..81012c0319 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/telemetry/dashboard-telemetry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/telemetry/dashboard-telemetry.element.ts @@ -3,6 +3,7 @@ import { css, html, LitElement } from 'lit'; import { unsafeHTML } from 'lit/directives/unsafe-html.js'; import { customElement, state } from 'lit/decorators.js'; import { ApiError, ProblemDetails, Telemetry, TelemetryLevel, TelemetryResource } from '@umbraco-cms/backend-api'; +import { umbHistoryService } from 'src/core/services/history'; export type SettingOption = 'Minimal' | 'Basic' | 'Detailed'; @@ -28,6 +29,10 @@ export class UmbDashboardTelemetryElement extends LitElement { constructor() { super(); + umbHistoryService.push({ + label: ['Settings', 'Telemetry Data'], + path: 'section/settings/dashboard/telemetry', + }); } connectedCallback(): void { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/created/section-view-packages-created.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/created/section-view-packages-created.element.ts index eb846fe01b..25f672a05e 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/created/section-view-packages-created.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/created/section-view-packages-created.element.ts @@ -1,6 +1,7 @@ import { html, LitElement } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { IRoute, IRoutingInfo } from 'router-slot'; +import { umbHistoryService } from 'src/core/services/history'; import { UmbEditorEntityElement } from '../../../../editors/shared/editor-entity/editor-entity.element'; @customElement('umb-section-view-packages-created') @@ -26,6 +27,11 @@ export class UmbSectionViewPackagesCreatedElement extends LitElement { }, ]; + constructor() { + super(); + umbHistoryService.push({ label: ['Packages', 'Created'], path: 'section/packages/view/created/overview' }); + } + render() { return html``; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/installed/section-view-packages-installed.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/installed/section-view-packages-installed.element.ts index 42a9355f04..0eafecd484 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/installed/section-view-packages-installed.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/installed/section-view-packages-installed.element.ts @@ -1,6 +1,7 @@ import { html, LitElement } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { IRoute, IRoutingInfo } from 'router-slot'; +import { umbHistoryService } from 'src/core/services/history'; import { UmbEditorEntityElement } from '../../../../editors/shared/editor-entity/editor-entity.element'; @customElement('umb-section-view-packages-installed') @@ -26,6 +27,11 @@ export class UmbSectionViewPackagesInstalledElement extends LitElement { }, ]; + constructor() { + super(); + umbHistoryService.push({ label: ['Packages', 'Installed'], path: 'section/packages/view/installed/overview' }); + } + render() { return html``; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/repo/section-view-packages-repo.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/repo/section-view-packages-repo.element.ts index 74e3136a3f..a0dfec9e88 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/repo/section-view-packages-repo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/repo/section-view-packages-repo.element.ts @@ -1,8 +1,16 @@ import { html, LitElement } from 'lit'; import { customElement } from 'lit/decorators.js'; +import { umbHistoryService } from 'src/core/services/history'; @customElement('umb-section-view-packages-repo') export class UmbSectionViewPackagesRepoElement extends LitElement { + /** + * + */ + constructor() { + super(); + umbHistoryService.push({ label: 'Packages', path: 'section/packages/view/packages' }); + } render() { return html` diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/user-groups/editor-view-user-groups.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/user-groups/editor-view-user-groups.element.ts index ed79c0b9c5..b11e5f80d3 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/user-groups/editor-view-user-groups.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/user-groups/editor-view-user-groups.element.ts @@ -15,6 +15,7 @@ import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; import type { UserGroupDetails } from '@umbraco-cms/models'; import './user-group-table-name-column-layout.element'; +import { umbHistoryService } from 'src/core/services/history'; @customElement('umb-editor-view-user-groups') export class UmbEditorViewUserGroupsElement extends UmbContextConsumerMixin(LitElement) { @@ -70,19 +71,18 @@ export class UmbEditorViewUserGroupsElement extends UmbContextConsumerMixin(LitE connectedCallback(): void { super.connectedCallback(); + umbHistoryService.push({ label: 'User groups', path: 'section/users/view/user-groups' }); - this.consumeContext('umbUserGroupStore', (userStore: UmbUserGroupStore) => { - this._userGroupStore = userStore; - this._observeUsers(); + this.consumeContext('umbUserGroupStore', (userGroupStore: UmbUserGroupStore) => { + this._userGroupStore = userGroupStore; + this._observeUserGroups(); }); } - private _observeUsers() { + private _observeUserGroups() { this._userGroupsSubscription?.unsubscribe(); this._userGroupsSubscription = this._userGroupStore?.getAll().subscribe((userGroups) => { this._userGroups = userGroups; - console.log('user groups', userGroups); - this._createTableItems(this._userGroups); }); } From 57ee922b27f32771b02c9a1742133634634a3044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= Date: Thu, 1 Dec 2022 14:13:00 +0100 Subject: [PATCH 076/223] recent history redesign --- .../dashboard-examine-management.element.ts | 2 +- .../views/section-view-examine-indexers.ts | 2 +- .../dashboard-models-builder.element.ts | 2 +- .../dashboard-published-status.element.ts | 2 +- .../telemetry/dashboard-telemetry.element.ts | 2 +- .../editors/user/editor-user.element.ts | 2 +- .../section-view-packages-created.element.ts | 2 +- ...section-view-packages-installed.element.ts | 2 +- .../modal-layout-user-dialog.element.ts | 77 +++++++++++-------- 9 files changed, 52 insertions(+), 41 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/dashboard-examine-management.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/dashboard-examine-management.element.ts index c086ee997c..44575ee75c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/dashboard-examine-management.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/dashboard-examine-management.element.ts @@ -55,7 +55,7 @@ export class UmbDashboardExamineManagementElement extends UmbContextConsumerMixi constructor() { super(); umbHistoryService.push({ - label: ['Settings', 'Examine Management'], + label: ['Examine Management', 'Settings'], path: 'section/settings/dashboard/examine-management', }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/views/section-view-examine-indexers.ts b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/views/section-view-examine-indexers.ts index 8e70c340ae..e54b79ac41 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/views/section-view-examine-indexers.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/views/section-view-examine-indexers.ts @@ -97,7 +97,7 @@ export class UmbDashboardExamineIndexElement extends UmbContextConsumerMixin(Lit const index = await SearchResource.getSearchIndexByIndexName({ indexName: this.indexName }); this._indexData = index; umbHistoryService.push({ - label: ['Settings', 'Examine Management', this._indexData.name], + label: [this._indexData.name, 'Settings', 'Examine Management'], path: 'section/settings/dashboard/examine-management/index/ExternalIndex/' + this._indexData.name, }); } catch (e) { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/models-builder/dashboard-models-builder.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/models-builder/dashboard-models-builder.element.ts index ead297d2d4..85c5e6dfee 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/models-builder/dashboard-models-builder.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/models-builder/dashboard-models-builder.element.ts @@ -10,7 +10,7 @@ export class UmbDashboardModelsBuilderElement extends LitElement { constructor() { super(); umbHistoryService.push({ - label: ['Settings', 'Models Builder'], + label: ['Models Builder', 'Settings'], path: 'section/settings/dashboard/models-builder', }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/published-status/dashboard-published-status.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/published-status/dashboard-published-status.element.ts index 41d33c6989..f0cd601678 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/published-status/dashboard-published-status.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/published-status/dashboard-published-status.element.ts @@ -46,7 +46,7 @@ export class UmbDashboardPublishedStatusElement extends UmbContextConsumerMixin( constructor() { super(); umbHistoryService.push({ - label: ['Settings', 'Published Status'], + label: ['Published Status', 'Settings'], path: 'section/settings/dashboard/published-status', }); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/telemetry/dashboard-telemetry.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/telemetry/dashboard-telemetry.element.ts index 81012c0319..e3d4773eca 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/telemetry/dashboard-telemetry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/telemetry/dashboard-telemetry.element.ts @@ -30,7 +30,7 @@ export class UmbDashboardTelemetryElement extends LitElement { constructor() { super(); umbHistoryService.push({ - label: ['Settings', 'Telemetry Data'], + label: ['Telemetry Data', 'Settings'], path: 'section/settings/dashboard/telemetry', }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts index 3fd2a81d29..b1169522b6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts @@ -142,7 +142,7 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( this._user = user; if (!this._user) return; - umbHistoryService.push({ label: ['Users', user.name], path: 'section/users/view/users/user/' + user.key }); + umbHistoryService.push({ label: [user.name, 'Users'], path: 'section/users/view/users/user/' + user.key }); if (!this._userContext) { this._userContext = new UmbUserContext(this._user); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/created/section-view-packages-created.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/created/section-view-packages-created.element.ts index 25f672a05e..546986cd3b 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/created/section-view-packages-created.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/created/section-view-packages-created.element.ts @@ -29,7 +29,7 @@ export class UmbSectionViewPackagesCreatedElement extends LitElement { constructor() { super(); - umbHistoryService.push({ label: ['Packages', 'Created'], path: 'section/packages/view/created/overview' }); + umbHistoryService.push({ label: ['Created', 'Packages'], path: 'section/packages/view/created/overview' }); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/installed/section-view-packages-installed.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/installed/section-view-packages-installed.element.ts index 0eafecd484..6e886faa3f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/installed/section-view-packages-installed.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/installed/section-view-packages-installed.element.ts @@ -29,7 +29,7 @@ export class UmbSectionViewPackagesInstalledElement extends LitElement { constructor() { super(); - umbHistoryService.push({ label: ['Packages', 'Installed'], path: 'section/packages/view/installed/overview' }); + umbHistoryService.push({ label: ['Installed', 'Packages'], path: 'section/packages/view/installed/overview' }); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index b4d145f22e..bc7bdcdd1d 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -47,20 +47,31 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb #recent-history-items { display: flex; flex-direction: column; - gap: var(--uui-size-space-2); + gap: var(--uui-size-space-4); } .history-item { - color: inherit; + display: grid; + grid-template-columns: 32px 1fr; + grid-template-rows: 1fr; + color: var(--uui-color-interactive); text-decoration: none; } - .history-item-name-separator { - margin: 0 var(--uui-size-space-1); + .history-item uui-icon { + margin-top: 2px; } - - .history-item-name-separator { - opacity: 0.4; + .history-item:hover { + color: var(--uui-color-interactive-emphasis); } - .history-item-name { + .history-item > div { + color: inherit; + text-decoration: none; + display: flex; + flex-direction: column; + line-height: 1.4em; + } + .history-item > div > span { + font-size: var(--uui-size-4); + opacity: 0.5; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; @@ -144,27 +155,25 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb } private _renderHistoryItem(item: UmbHistoryItem) { - if (typeof item.label === 'string') { - return html` -
${item.label}
-
`; - } - if (Array.isArray(item.label)) { - console.log('hallo', item); - - return html` - -
- ${item.label.map((name, index) => { - return html`${name}${index < item.label.length - 1 ? '>' : nothing}`; - })} -
-
- `; - } - - return nothing; + return html` + + +
+ ${Array.isArray(item.label) ? item.label[0] : item.label} + + ${Array.isArray(item.label) + ? item.label.map((label, index) => { + if (index === 0) return; + return html` + ${label} + ${index !== item.label.length - 1 ? html`${'>'}` : nothing} + `; + }) + : nothing} + +
+
+ `; } render() { @@ -190,10 +199,12 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb html`` )}
-
- Recent History -
${this._history.map((item) => html`${this._renderHistoryItem(item)}`)}
-
+ + Recent History +
+ ${this._history.reverse().map((item) => html` ${this._renderHistoryItem(item)} `)} +
+
Close From 8b90943c5166dbcbc491699583ffdb072f5f44ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Fri, 2 Dec 2022 16:29:28 +0100 Subject: [PATCH 077/223] admin access to user editor actions --- .../editors/user/editor-user.element.ts | 41 +++++++++++++------ .../src/core/mocks/data/users.data.ts | 1 + 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts index b1169522b6..ebced964b1 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts @@ -1,5 +1,5 @@ import { UUIInputElement, UUIInputEvent } from '@umbraco-ui/uui'; -import { css, html, LitElement, nothing } from 'lit'; +import { css, html, LitElement, nothing, TemplateResult } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, state } from 'lit/decorators.js'; import { Subscription } from 'rxjs'; @@ -214,19 +214,34 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( } private _renderActionButtons() { - if (this._currentUser?.key === this._user?.key) - return html` `; + const adminUserGroupKey = '10000000-0000-0000-0000-000000000000'; + const buttons: TemplateResult[] = []; - return html` ${this._user?.status !== 'invited' - ? html` - - ` - : nothing} - `; + if (this._currentUser?.userGroup !== adminUserGroupKey) return nothing; + + if (this._user?.status !== 'invited') + buttons.push( + html` + + ` + ); + + if (this._currentUser?.key !== this._user?.key) + buttons.push(html` `); + + buttons.push( + html` ` + ); + + return buttons; } private renderLeftColumn() { diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/users.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/users.data.ts index 571f81e118..b28d78200a 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/users.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/users.data.ts @@ -44,6 +44,7 @@ export const data: Array = [ updateDate: '8/27/2022', createDate: '9/19/2022', failedLoginAttempts: 52, + userGroup: '10000000-0000-0000-0000-000000000000', }, { key: '7c9c5510-a7b6-43fd-a2d1-51de0009eabf', From dff8e5445a7ff2dd889343acf888d89aad899e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Fri, 2 Dec 2022 16:49:00 +0100 Subject: [PATCH 078/223] change password modal reacts to admin state --- .../editors/user/editor-user.element.ts | 17 ++++++++++++----- .../modal-layout-change-password.element.ts | 10 +++++++--- .../src/core/services/modal/modal.service.ts | 5 +++-- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts index ebced964b1..06e3982f7d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts @@ -210,14 +210,21 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( } private _changePassword() { - this._modalService?.changePassword(); + this._modalService?.changePassword({ requireOldPassword: this._isCurrentUserAdmin === false }); + } + + private get _isCurrentUserAdmin(): boolean { + //TODO: Find a way to figure out if current user is in the admin group + const adminUserGroupKey = '10000000-0000-0000-0000-000000000000'; + return this._currentUser?.userGroup === adminUserGroupKey; } private _renderActionButtons() { - const adminUserGroupKey = '10000000-0000-0000-0000-000000000000'; + if (!this._user) return; + const buttons: TemplateResult[] = []; - if (this._currentUser?.userGroup !== adminUserGroupKey) return nothing; + if (this._isCurrentUserAdmin === false) return nothing; if (this._user?.status !== 'invited') buttons.push( @@ -225,8 +232,8 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( + color="${this._user.status === 'disabled' ? 'positive' : 'warning'}" + label="${this._user.status === 'disabled' ? 'Enable' : 'Disable'}"> ` ); diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts index 4223e2df85..47728db7a8 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts @@ -7,6 +7,10 @@ import { UmbUserStore } from 'src/core/stores/user/user.store'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +export interface UmbModalChangePasswordData { + requireOldPassword: boolean; +} + @customElement('umb-modal-layout-change-password') export class UmbModalLayoutChangePasswordElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { static styles: CSSResultGroup = [ @@ -30,8 +34,8 @@ export class UmbModalLayoutChangePasswordElement extends UmbContextConsumerMixin @property({ attribute: false }) modalHandler?: UmbModalHandler; - @state() - private _requireOldPassword = false; //TODO: Implement check to see if current user is an admin. + @property() + data?: UmbModalChangePasswordData; private _close() { this.modalHandler?.close(); @@ -73,7 +77,7 @@ export class UmbModalLayoutChangePasswordElement extends UmbContextConsumerMixin
- ${this._requireOldPassword ? this._renderOldPasswordInput() : nothing} + ${this.data?.requireOldPassword ? this._renderOldPasswordInput() : nothing} New password Date: Mon, 5 Dec 2022 16:53:44 +0100 Subject: [PATCH 079/223] current user is not a static service --- .../backoffice-header-tools.element.ts | 8 ++--- .../editors/user/editor-user.element.ts | 3 +- .../current-user/current-user.service.ts | 30 +++++++++++++++++++ .../src/core/services/current-user/index.ts | 1 + .../modal-layout-user-dialog.element.ts | 22 ++++++++------ .../src/core/stores/user/user.store.ts | 13 +------- 6 files changed, 49 insertions(+), 28 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/core/services/current-user/current-user.service.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/services/current-user/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts index 0c336cf22d..2e639b0d2a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/components/backoffice-header-tools.element.ts @@ -5,7 +5,7 @@ import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; import type { UserDetails } from '@umbraco-cms/models'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbModalService } from '@umbraco-cms/services'; -import { UmbUserStore } from 'src/core/stores/user/user.store'; +import { umbCurrentUserService } from 'src/core/services/current-user'; @customElement('umb-backoffice-header-tools') export class UmbBackofficeHeaderTools extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { @@ -27,22 +27,18 @@ export class UmbBackofficeHeaderTools extends UmbContextConsumerMixin(UmbObserve @state() private _currentUser?: UserDetails; - private _userStore?: UmbUserStore; private _modalService?: UmbModalService; constructor() { super(); this.consumeAllContexts(['umbUserStore', 'umbModalService'], (instances) => { - this._userStore = instances['umbUserStore']; this._modalService = instances['umbModalService']; this._observeCurrentUser(); }); } private async _observeCurrentUser() { - if (!this._userStore) return; - - this.observe(this._userStore.currentUser, (currentUser) => { + this.observe(umbCurrentUserService.currentUser, (currentUser) => { this._currentUser = currentUser; }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts index 06e3982f7d..c74fd54aca 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts @@ -17,6 +17,7 @@ import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbModalService } from '@umbraco-cms/services'; import { umbHistoryService } from 'src/core/services/history'; +import { umbCurrentUserService } from 'src/core/services/current-user'; @customElement('umb-editor-user') export class UmbEditorUserElement extends UmbContextProviderMixin( @@ -130,7 +131,7 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( private async _observeCurrentUser() { if (!this._userStore) return; - this.observe(this._userStore.currentUser, (currentUser) => { + this.observe(umbCurrentUserService.currentUser, (currentUser) => { this._currentUser = currentUser; }); } diff --git a/src/Umbraco.Web.UI.Client/src/core/services/current-user/current-user.service.ts b/src/Umbraco.Web.UI.Client/src/core/services/current-user/current-user.service.ts new file mode 100644 index 0000000000..217b873a18 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/services/current-user/current-user.service.ts @@ -0,0 +1,30 @@ +import { BehaviorSubject, Observable } from 'rxjs'; +import { umbUsersData } from '../../mocks/data/users.data'; +import type { UserDetails } from '@umbraco-cms/models'; +import { umbracoPath } from '@umbraco-cms/utils'; + +class UmbCurrentUserService { + private _currentUser = new BehaviorSubject(umbUsersData.getItems('user')[0]); //TODO: Temp solution to set the first user as the current logged in user + public readonly currentUser: Observable = this._currentUser.asObservable(); + + /** + * logs out the user + * @public + * @memberof UmbCurrentUserService + */ + public logout(): void { + fetch(umbracoPath('/user/logout').toString()) + .then((res) => res.json()) + .then((data) => { + console.log('User Logged out', data); + }); + } + + public get isAdmin(): boolean { + //TODO: Find a way to figure out if current user is in the admin group + const adminUserGroupKey = '10000000-0000-0000-0000-000000000000'; + return this._currentUser.getValue()?.userGroup === adminUserGroupKey; + } +} + +export const umbCurrentUserService = new UmbCurrentUserService(); diff --git a/src/Umbraco.Web.UI.Client/src/core/services/current-user/index.ts b/src/Umbraco.Web.UI.Client/src/core/services/current-user/index.ts new file mode 100644 index 0000000000..f895dd41e2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/services/current-user/index.ts @@ -0,0 +1 @@ +export * from './current-user.service'; diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts index bc7bdcdd1d..c2be231872 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-user-dialog.element.ts @@ -2,6 +2,7 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, CSSResultGroup, html, LitElement, nothing } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { UmbHistoryItem, umbHistoryService } from '../../history'; +import { umbCurrentUserService } from '../../current-user'; import { UmbModalHandler, UmbModalService } from '@umbraco-cms/services'; import type { ManifestExternalLoginProvider, ManifestUserDashboard, UserDetails } from '@umbraco-cms/models'; import { UmbUserStore } from 'src/core/stores/user/user.store'; @@ -94,17 +95,15 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb @state() private _history: Array = []; - private _userStore?: UmbUserStore; private _modalService?: UmbModalService; constructor() { super(); - this.consumeAllContexts(['umbUserStore', 'umbModalService'], (instances) => { - this._userStore = instances['umbUserStore']; + this.consumeAllContexts(['umbModalService'], (instances) => { this._modalService = instances['umbModalService']; - this._observeCurrentUser(); }); + this._observeCurrentUser(); this._observeExternalLoginProviders(); this._observeHistory(); this._observeUserDashboards(); @@ -120,9 +119,7 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb } private async _observeCurrentUser() { - if (!this._userStore) return; - - this.observe(this._userStore.currentUser, (currentUser) => { + this.observe(umbCurrentUserService.currentUser, (currentUser) => { this._currentUser = currentUser; }); } @@ -144,14 +141,17 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb } private _edit() { + console.log('Hello', this._currentUser); if (!this._currentUser) return; + history.pushState(null, '', '/section/users/view/users/user/' + this._currentUser.key); //TODO Change to a tag with href and make dynamic this._close(); } private _changePassword() { if (!this._modalService) return; - this._modalService.changePassword(); + + this._modalService.changePassword({ requireOldPassword: umbCurrentUserService.isAdmin }); } private _renderHistoryItem(item: UmbHistoryItem) { @@ -176,6 +176,10 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb `; } + private _logout() { + umbCurrentUserService.logout(); + } + render() { return html` @@ -208,7 +212,7 @@ export class UmbModalLayoutUserDialogElement extends UmbContextConsumerMixin(Umb
Close - Logout + Logout
`; diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/user/user.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/user/user.store.ts index 0d4a9a082b..80e6f80442 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/user/user.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/user/user.store.ts @@ -1,4 +1,4 @@ -import { BehaviorSubject, map, Observable, ReplaySubject, Subject } from 'rxjs'; +import { BehaviorSubject, map, Observable } from 'rxjs'; import type { UserDetails } from '../../models'; import { UmbEntityStore } from '../entity.store'; import { UmbDataStoreBase } from '../store'; @@ -15,20 +15,9 @@ export class UmbUserStore extends UmbDataStoreBase { private _totalUsers: BehaviorSubject = new BehaviorSubject(0); public readonly totalUsers: Observable = this._totalUsers.asObservable(); - private _currentUser: Subject = new ReplaySubject(); - public readonly currentUser: Observable = this._currentUser.asObservable(); - constructor(entityStore: UmbEntityStore) { super(); this._entityStore = entityStore; - - //TODO: Temp code to get the first user as the current user. Replace when login is implemented. - const subscription = this.getAll().subscribe((response) => { - if (response.length > 0) { - this._currentUser.next(response[0]); - subscription.unsubscribe(); - } - }); } getAll(): Observable> { From ed5d152f3ec1c81742c55e4bc52253e30e61839d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 12 Dec 2022 10:06:10 +0100 Subject: [PATCH 080/223] handle documents --- .../document/editor-document.element.ts | 8 ++- .../src/core/mocks/data/document.data.ts | 3 +- .../core/mocks/domains/document.handlers.ts | 35 ++++++++++++ .../core/stores/document/document.store.ts | 53 +++++++++++++++++++ 4 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/domains/document.handlers.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts index 55e8e7d6ce..88b4b8109c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts @@ -3,11 +3,13 @@ import { css, html, LitElement } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import type { ManifestEditorView, ManifestWithLoader } from '@umbraco-cms/models'; +import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import '../shared/editor-content/editor-node.element'; +import { UmbDocumentStore } from 'src/core/stores/document/document.store'; @customElement('umb-editor-document') -export class UmbEditorDocumentElement extends LitElement { +export class UmbEditorDocumentElement extends UmbContextConsumerMixin(UmbContextProviderMixin(LitElement)) { static styles = [ UUITextStyles, css` @@ -26,6 +28,10 @@ export class UmbEditorDocumentElement extends LitElement { super(); this._registerEditorViews(); + + this.consumeContext('umbDocumentStore', (documentStore: UmbDocumentStore) => { + this.provideContext('umbNodeStore', documentStore); + }); } private _registerEditorViews() { 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 ec0e5e066c..ec9afdfabe 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 @@ -1,6 +1,7 @@ import { UmbData } from './data'; import { DocumentTreeItem, PagedDocumentTreeItem } from '@umbraco-cms/backend-api'; import type { DocumentDetails } from '@umbraco-cms/models'; +import { UmbEntityData } from './entity.data'; export const data: Array = [ { @@ -180,7 +181,7 @@ export const data: Array = [ ]; // Temp mocked database -class UmbDocumentData extends UmbData { +class UmbDocumentData extends UmbEntityData { constructor() { super(data); } diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document.handlers.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document.handlers.ts new file mode 100644 index 0000000000..65d0c21ba7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/domains/document.handlers.ts @@ -0,0 +1,35 @@ +import { rest } from 'msw'; +import { umbDocumentData } from '../data/document.data'; +import type { DocumentDetails } from '@umbraco-cms/models'; + +// TODO: add schema +export const handlers = [ + rest.get('/umbraco/management/api/v1/document/details/:key', (req, res, ctx) => { + console.warn('Please move to schema'); + const key = req.params.key as string; + if (!key) return; + + const document = umbDocumentData.getByKey(key); + + return res(ctx.status(200), ctx.json([document])); + }), + + rest.post('/umbraco/management/api/v1/document/save', async (req, res, ctx) => { + console.warn('Please move to schema'); + const data = await req.json(); + if (!data) return; + + const saved = umbDocumentData.save(data); + + return res(ctx.status(200), ctx.json(saved)); + }), + + rest.post('/umbraco/management/api/v1/document/trash', async (req, res, ctx) => { + console.warn('Please move to schema'); + const keys = await req.json(); + + const trashed = umbDocumentData.trash(keys); + + return res(ctx.status(200), ctx.json(trashed)); + }), +]; diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts index 7aeecbc364..a65a7a3721 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts @@ -10,6 +10,59 @@ import { ApiError, DocumentResource, DocumentTreeItem, FolderTreeItem, ProblemDe * @description - Data Store for Documents */ export class UmbDocumentStore extends UmbDataStoreBase { + getByKey(key: string): Observable { + // fetch from server and update store + fetch(`/umbraco/management/api/v1/document/details/${key}`) + .then((res) => res.json()) + .then((data) => { + this.update(data); + }); + + return this.items.pipe(map((documents) => documents.find((document) => document.key === key) || null)); + } + + async trash(keys: Array) { + // fetch from server and update store + // TODO: Use node type to hit the right API, or have a general Node API? + const res = await fetch('/umbraco/backoffice/node/trash', { + method: 'POST', + body: JSON.stringify(keys), + headers: { + 'Content-Type': 'application/json', + }, + }); + const data = await res.json(); + this.update(data); + this._entityStore.update(data); + } + + // TODO: make sure UI somehow can follow the status of this action. + save(data: DocumentDetails[]): Promise { + // fetch from server and update store + // TODO: use Fetcher API. + let body: string; + + try { + body = JSON.stringify(data); + } catch (error) { + console.error(error); + return Promise.reject(); + } + + // TODO: Use node type to hit the right API, or have a general Node API? + return fetch('/umbraco/backoffice/node/save', { + method: 'POST', + body: body, + headers: { + 'Content-Type': 'application/json', + }, + }) + .then((res) => res.json()) + .then((data: Array) => { + this.update(data); + }); + } + getTreeRoot(): Observable> { DocumentResource.getTreeDocumentRoot({}).then( (res) => { From 441b5a13c9b52d491e9509a3e83d1acc37e1ff3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 12 Dec 2022 10:24:32 +0100 Subject: [PATCH 081/223] node-editor -> content-editor --- .../document/editor-document.element.ts | 4 ++-- .../editors/media/editor-media.element.ts | 4 ++-- ...de.element.ts => editor-content.element.ts} | 10 +++++----- .../editor-content/editor-content.stories.ts | 18 ++++++++++++++++++ .../editor-content/editor-node.stories.ts | 18 ------------------ 5 files changed, 27 insertions(+), 27 deletions(-) rename src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/{editor-node.element.ts => editor-content.element.ts} (95%) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.stories.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-node.stories.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts index 88b4b8109c..54e7a72183 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts @@ -5,7 +5,7 @@ import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import type { ManifestEditorView, ManifestWithLoader } from '@umbraco-cms/models'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; -import '../shared/editor-content/editor-node.element'; +import '../shared/editor-content/editor-content.element'; import { UmbDocumentStore } from 'src/core/stores/document/document.store'; @customElement('umb-editor-document') @@ -71,7 +71,7 @@ export class UmbEditorDocumentElement extends UmbContextConsumerMixin(UmbContext } render() { - return html``; + return html``; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts index 443acf8be0..d6432ab14a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts @@ -4,7 +4,7 @@ import { customElement, property } from 'lit/decorators.js'; import type { ManifestEditorView, ManifestWithLoader } from '@umbraco-cms/models'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; -import '../shared/editor-content/editor-node.element'; +import '../shared/editor-content/editor-content.element'; @customElement('umb-editor-media') export class UmbEditorMediaElement extends LitElement { @@ -65,7 +65,7 @@ export class UmbEditorMediaElement extends LitElement { } render() { - return html``; + return html``; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-node.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts similarity index 95% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-node.element.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts index a61320ef24..9498624c80 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-node.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts @@ -15,11 +15,11 @@ import '../editor-entity-layout/editor-entity-layout.element'; // Lazy load // TODO: Make this dynamic, use load-extensions method to loop over extensions for this node. -import './views/edit/editor-view-node-edit.element'; +import './views/edit/editor-view-content-edit.element'; import './views/info/editor-view-node-info.element'; -@customElement('umb-editor-node') -export class UmbEditorNodeElement extends UmbContextProviderMixin( +@customElement('umb-editor-content') +export class UmbEditorContentElement extends UmbContextProviderMixin( UmbContextConsumerMixin(UmbObserverMixin(LitElement)) ) { static styles = [ @@ -207,10 +207,10 @@ export class UmbEditorNodeElement extends UmbContextProviderMixin( } } -export default UmbEditorNodeElement; +export default UmbEditorContentElement; declare global { interface HTMLElementTagNameMap { - 'umb-editor-node': UmbEditorNodeElement; + 'umb-editor-content': UmbEditorContentElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.stories.ts new file mode 100644 index 0000000000..f3008ee0b1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.stories.ts @@ -0,0 +1,18 @@ +import './editor-content.element'; + +import { Meta, Story } from '@storybook/web-components'; +import { html } from 'lit-html'; + +import { data } from '../../../../core/mocks/data/node.data'; + +import type { UmbEditorContentElement } from './editor-content.element'; + +export default { + title: 'Editors/Shared/Node', + component: 'umb-editor-content', + id: 'umb-editor-content', +} as Meta; + +export const AAAOverview: Story = () => + html` `; +AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-node.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-node.stories.ts deleted file mode 100644 index 5291fec854..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-node.stories.ts +++ /dev/null @@ -1,18 +0,0 @@ -import './editor-node.element'; - -import { Meta, Story } from '@storybook/web-components'; -import { html } from 'lit-html'; - -import { data } from '../../../../core/mocks/data/node.data'; - -import type { UmbEditorNodeElement } from './editor-node.element'; - -export default { - title: 'Editors/Shared/Node', - component: 'umb-editor-node', - id: 'umb-editor-node', -} as Meta; - -export const AAAOverview: Story = () => - html` `; -AAAOverview.storyName = 'Overview'; From 2781575acae781525c0411a280e5350600bc80fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 12 Dec 2022 10:24:54 +0100 Subject: [PATCH 082/223] view-node-edit -> view-content-edit --- .../editors/document/editor-document.element.ts | 2 +- .../backoffice/editors/media/editor-media.element.ts | 2 +- ...lement.ts => editor-view-content-edit.element.ts} | 8 ++++---- ...tories.ts => editor-view-content-edit.stories.ts} | 12 ++++++------ 4 files changed, 12 insertions(+), 12 deletions(-) rename src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/{editor-view-node-edit.element.ts => editor-view-content-edit.element.ts} (84%) rename src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/{editor-view-node-edit.stories.ts => editor-view-content-edit.stories.ts} (57%) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts index 54e7a72183..41f1957ce9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts @@ -40,7 +40,7 @@ export class UmbEditorDocumentElement extends UmbContextConsumerMixin(UmbContext type: 'editorView', alias: 'Umb.EditorView.Document.Edit', name: 'Document Editor Edit View', - loader: () => import('../shared/editor-content/views/edit/editor-view-node-edit.element'), + loader: () => import('../shared/editor-content/views/edit/editor-view-content-edit.element'), weight: 200, meta: { editors: ['Umb.Editor.Document'], diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts index d6432ab14a..cd40bfc12f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts @@ -34,7 +34,7 @@ export class UmbEditorMediaElement extends LitElement { type: 'editorView', alias: 'Umb.EditorView.Media.Edit', name: 'Media Editor Edit View', - loader: () => import('../shared/editor-content/views/edit/editor-view-node-edit.element'), + loader: () => import('../shared/editor-content/views/edit/editor-view-content-edit.element'), weight: 200, meta: { editors: ['Umb.Editor.Media'], diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-node-edit.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-content-edit.element.ts similarity index 84% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-node-edit.element.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-content-edit.element.ts index 88b90634ff..9fe57681d6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-node-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-content-edit.element.ts @@ -9,8 +9,8 @@ import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; import '../../../../../components/node-property/node-property.element'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; -@customElement('umb-editor-view-node-edit') -export class UmbEditorViewNodeEditElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { +@customElement('umb-editor-view-content-edit') +export class UmbEditorViewContentEditElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { static styles = [UUITextStyles]; @state() @@ -54,10 +54,10 @@ export class UmbEditorViewNodeEditElement extends UmbContextConsumerMixin(UmbObs } } -export default UmbEditorViewNodeEditElement; +export default UmbEditorViewContentEditElement; declare global { interface HTMLElementTagNameMap { - 'umb-editor-view-node-edit': UmbEditorViewNodeEditElement; + 'umb-editor-view-content-edit': UmbEditorViewContentEditElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-node-edit.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-content-edit.stories.ts similarity index 57% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-node-edit.stories.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-content-edit.stories.ts index 8fd877dbcb..b3e4314c00 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-node-edit.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/edit/editor-view-content-edit.stories.ts @@ -1,4 +1,4 @@ -import './editor-view-node-edit.element'; +import './editor-view-content-edit.element'; import { Meta, Story } from '@storybook/web-components'; import { html } from 'lit-html'; @@ -6,12 +6,12 @@ import { html } from 'lit-html'; import { data } from '../../../../../../core/mocks/data/node.data'; import { UmbNodeContext } from '../../node.context'; -import type { UmbEditorViewNodeEditElement } from './editor-view-node-edit.element'; +import type { UmbEditorViewContentEditElement } from './editor-view-content-edit.element'; export default { title: 'Editors/Shared/Node/Views/Edit', - component: 'umb-editor-view-node-edit', - id: 'umb-editor-view-node-edit', + component: 'umb-editor-view-content-edit', + id: 'umb-editor-view-content-edit', decorators: [ (story) => html` @@ -20,6 +20,6 @@ export default { ], } as Meta; -export const AAAOverview: Story = () => - html` `; +export const AAAOverview: Story = () => + html` `; AAAOverview.storyName = 'Overview'; From 2217f8a41b4ff0c8f523da55b6a6b437ec4c8009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 12 Dec 2022 10:26:40 +0100 Subject: [PATCH 083/223] view-node-info -> view-content-info --- .../editors/document/editor-document.element.ts | 2 +- .../backoffice/editors/media/editor-media.element.ts | 2 +- .../shared/editor-content/editor-content.element.ts | 2 +- ...lement.ts => editor-view-content-info.element.ts} | 8 ++++---- ...tories.ts => editor-view-content-info.stories.ts} | 12 ++++++------ 5 files changed, 13 insertions(+), 13 deletions(-) rename src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/{editor-view-node-info.element.ts => editor-view-content-info.element.ts} (79%) rename src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/{editor-view-node-info.stories.ts => editor-view-content-info.stories.ts} (57%) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts index 41f1957ce9..846fd29be8 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/document/editor-document.element.ts @@ -53,7 +53,7 @@ export class UmbEditorDocumentElement extends UmbContextConsumerMixin(UmbContext type: 'editorView', alias: 'Umb.EditorView.Document.Info', name: 'Document Editor Info View', - loader: () => import('../shared/editor-content/views/info/editor-view-node-info.element'), + loader: () => import('../shared/editor-content/views/info/editor-view-content-info.element'), weight: 100, meta: { editors: ['Umb.Editor.Document'], diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts index cd40bfc12f..7dd4de4067 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts @@ -47,7 +47,7 @@ export class UmbEditorMediaElement extends LitElement { type: 'editorView', alias: 'Umb.EditorView.Media.Info', name: 'Media Editor Info View', - loader: () => import('../shared/editor-content/views/info/editor-view-node-info.element'), + loader: () => import('../shared/editor-content/views/info/editor-view-content-info.element'), weight: 100, meta: { editors: ['Umb.Editor.Media'], diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts index 9498624c80..18d03e63f2 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts @@ -16,7 +16,7 @@ import '../editor-entity-layout/editor-entity-layout.element'; // Lazy load // TODO: Make this dynamic, use load-extensions method to loop over extensions for this node. import './views/edit/editor-view-content-edit.element'; -import './views/info/editor-view-node-info.element'; +import './views/info/editor-view-content-info.element'; @customElement('umb-editor-content') export class UmbEditorContentElement extends UmbContextProviderMixin( diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-node-info.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-content-info.element.ts similarity index 79% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-node-info.element.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-content-info.element.ts index d93394afde..1097d97afc 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-node-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-content-info.element.ts @@ -7,8 +7,8 @@ import type { NodeEntity } from '../../../../../../core/mocks/data/node.data'; import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; -@customElement('umb-editor-view-node-info') -export class UmbEditorViewNodeInfoElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { +@customElement('umb-editor-view-content-info') +export class UmbEditorViewContentInfoElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { static styles = [UUITextStyles, css``]; private _nodeContext?: UmbNodeContext; @@ -38,10 +38,10 @@ export class UmbEditorViewNodeInfoElement extends UmbContextConsumerMixin(UmbObs } } -export default UmbEditorViewNodeInfoElement; +export default UmbEditorViewContentInfoElement; declare global { interface HTMLElementTagNameMap { - 'umb-editor-view-node-info': UmbEditorViewNodeInfoElement; + 'umb-editor-view-content-info': UmbEditorViewContentInfoElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-node-info.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-content-info.stories.ts similarity index 57% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-node-info.stories.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-content-info.stories.ts index d6da71d954..340f341a5d 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-node-info.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/views/info/editor-view-content-info.stories.ts @@ -1,4 +1,4 @@ -import './editor-view-node-info.element'; +import './editor-view-content-info.element'; import { Meta, Story } from '@storybook/web-components'; import { html } from 'lit-html'; @@ -6,12 +6,12 @@ import { html } from 'lit-html'; import { data } from '../../../../../../core/mocks/data/node.data'; import { UmbNodeContext } from '../../node.context'; -import type { UmbEditorViewNodeInfoElement } from './editor-view-node-info.element'; +import type { UmbEditorViewContentInfoElement } from './editor-view-content-info.element'; export default { title: 'Editors/Shared/Node/Views/Info', - component: 'umb-editor-view-node-info', - id: 'umb-editor-view-node-info', + component: 'umb-editor-view-content-info', + id: 'umb-editor-view-content-info', decorators: [ (story) => html` @@ -20,6 +20,6 @@ export default { ], } as Meta; -export const AAAOverview: Story = () => - html` `; +export const AAAOverview: Story = () => + html` `; AAAOverview.storyName = 'Overview'; From 510bd10aa388325cff590dd0379f56d2c3c35853 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 12 Dec 2022 11:23:47 +0100 Subject: [PATCH 084/223] save document --- src/Umbraco.Web.UI.Client/src/core/mocks/browser-handlers.ts | 3 +++ .../src/core/stores/document/document.store.ts | 5 ++--- 2 files changed, 5 insertions(+), 3 deletions(-) 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 a5cc2f2e5a..98d6ec1b19 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 @@ -15,6 +15,8 @@ import { handlers as examineManagementHandlers } from './domains/examine-managem import { handlers as modelsBuilderHandlers } from './domains/modelsbuilder.handlers'; import { handlers as profilingHandlers } from './domains/performance-profiling.handlers'; +import { handlers as documentHandlers } from './domains/document.handlers'; + // treeHandlers import { handlers as treeDocumentHandlers } from './domains/tree-document.handlers'; import { handlers as treeMediaHandlers } from './domains/tree-media.handlers'; @@ -30,6 +32,7 @@ const handlers = [ ...installHandlers, ...upgradeHandlers, ...userHandlers, + ...documentHandlers, ...dataTypeHandlers, ...documentTypeHandlers, ...treeHandlers, diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts index a65a7a3721..b3b2b10e88 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts @@ -24,7 +24,7 @@ export class UmbDocumentStore extends UmbDataStoreBase) { // fetch from server and update store // TODO: Use node type to hit the right API, or have a general Node API? - const res = await fetch('/umbraco/backoffice/node/trash', { + const res = await fetch('/umbraco/management/api/v1/document/trash', { method: 'POST', body: JSON.stringify(keys), headers: { @@ -33,7 +33,6 @@ export class UmbDocumentStore extends UmbDataStoreBase Date: Mon, 12 Dec 2022 11:31:47 +0100 Subject: [PATCH 085/223] umb-editor-layout -> umb-body-layout --- .../public-assets/App_Plugins/package-view.js | 4 +- .../body-layout/body-layout.element.ts} | 38 ++++++++----------- .../body-layout/body-layout.stories.ts} | 12 +++--- .../editor-entity-layout.element.ts | 6 +-- .../modal-layout-content-picker.stories.ts | 2 +- .../modal-layout-icon-picker.stories.ts | 2 +- ...ayout-property-editor-ui-picker.stories.ts | 2 +- 7 files changed, 29 insertions(+), 37 deletions(-) rename src/Umbraco.Web.UI.Client/src/backoffice/{editors/shared/editor-layout/editor-layout.element.ts => components/body-layout/body-layout.element.ts} (63%) rename src/Umbraco.Web.UI.Client/src/backoffice/{editors/shared/editor-layout/editor-layout.stories.ts => components/body-layout/body-layout.stories.ts} (62%) diff --git a/src/Umbraco.Web.UI.Client/public-assets/App_Plugins/package-view.js b/src/Umbraco.Web.UI.Client/public-assets/App_Plugins/package-view.js index 00dfd78079..3150e99e19 100644 --- a/src/Umbraco.Web.UI.Client/public-assets/App_Plugins/package-view.js +++ b/src/Umbraco.Web.UI.Client/public-assets/App_Plugins/package-view.js @@ -1,6 +1,6 @@ const template = document.createElement('template'); template.innerHTML = ` - +

My package view

@@ -10,7 +10,7 @@ template.innerHTML = ` Close -
+ `; export default class MyPackageViewCustom extends HTMLElement { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-layout/editor-layout.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/components/body-layout/body-layout.element.ts similarity index 63% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-layout/editor-layout.element.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/components/body-layout/body-layout.element.ts index b4180bd213..32d31aee54 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-layout/editor-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/components/body-layout/body-layout.element.ts @@ -2,22 +2,16 @@ import { css, html, LitElement } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement } from 'lit/decorators.js'; -@customElement('umb-editor-layout') -export class UmbEditorLayout extends LitElement { +@customElement('umb-body-layout') +export class UmbBodyLayout extends LitElement { static styles = [ UUITextStyles, css` :host { - display: block; - width: 100%; - height: 100%; - } - - #editor-frame { + display: flex; background-color: var(--uui-color-background); width: 100%; height: 100%; - display: flex; flex-direction: column; } @@ -26,7 +20,7 @@ export class UmbEditorLayout extends LitElement { width: 100%; border-bottom: 1px solid var(--uui-color-border); box-sizing: border-box; - padding: 0 var(--uui-size-6); + /* padding: 0 var(--uui-size-6); */ } #main { @@ -41,7 +35,7 @@ export class UmbEditorLayout extends LitElement { align-items: center; height: 70px; width: 100%; - padding: 0 var(--uui-size-6); + /*padding: 0 var(--uui-size-6);*/ border-top: 1px solid var(--uui-color-border); background-color: var(--uui-color-surface); box-sizing: border-box; @@ -51,17 +45,15 @@ export class UmbEditorLayout extends LitElement { render() { return html` -
- - - - - + + + + + `; } @@ -69,6 +61,6 @@ export class UmbEditorLayout extends LitElement { declare global { interface HTMLElementTagNameMap { - 'umb-editor-layout': UmbEditorLayout; + 'umb-body-layout': UmbBodyLayout; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-layout/editor-layout.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/components/body-layout/body-layout.stories.ts similarity index 62% rename from src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-layout/editor-layout.stories.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/components/body-layout/body-layout.stories.ts index 7b4127d906..549353c284 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-layout/editor-layout.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/components/body-layout/body-layout.stories.ts @@ -1,19 +1,19 @@ -import './editor-layout.element'; +import './body-layout.element'; import { Meta, Story } from '@storybook/web-components'; import { html } from 'lit-html'; -import type { UmbEditorLayout } from './editor-layout.element'; +import type { UmbBodyLayout } from './body-layout.element'; export default { title: 'Editors/Shared/Editor Layout', - component: 'umb-editor-layout', - id: 'umb-editor-layout', + component: 'umb-body-layout', + id: 'umb-body-layout', } as Meta; -export const AAAOverview: Story = () => html` +export const AAAOverview: Story = () => html`
Header slot
Main slot
Footer slot
-
`; +`; AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-entity-layout/editor-entity-layout.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-entity-layout/editor-entity-layout.element.ts index 2ff1d4507e..986d588ef5 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-entity-layout/editor-entity-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-entity-layout/editor-entity-layout.element.ts @@ -10,7 +10,7 @@ import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; import type { ManifestEditorAction, ManifestEditorView } from '@umbraco-cms/models'; -import '../editor-layout/editor-layout.element'; +import '../../../components/body-layout/body-layout.element'; import '../editor-action-extension/editor-action-extension.element'; /** @@ -191,7 +191,7 @@ export class UmbEditorEntityLayout extends UmbContextConsumerMixin(UmbObserverMi render() { return html` - + - + `; } } diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.stories.ts index 66ae3873e6..cf475acbc9 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.stories.ts @@ -1,4 +1,4 @@ -import '../../../../../backoffice/editors/shared/editor-layout/editor-layout.element'; +import '../../../../../backoffice/components/body-layout/body-layout.element'; import './modal-layout-content-picker.element'; import { Meta, Story } from '@storybook/web-components'; diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/icon-picker/modal-layout-icon-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/icon-picker/modal-layout-icon-picker.stories.ts index ecf8656afa..8dc519f180 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/icon-picker/modal-layout-icon-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/icon-picker/modal-layout-icon-picker.stories.ts @@ -1,4 +1,4 @@ -import '../../../../../backoffice/editors/shared/editor-layout/editor-layout.element'; +import '../../../../../backoffice/components/body-layout/body-layout.element'; import './modal-layout-icon-picker.element'; import { Meta, Story } from '@storybook/web-components'; diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.stories.ts index ca81b73929..a718cac41a 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.stories.ts @@ -6,7 +6,7 @@ import type { } from './modal-layout-property-editor-ui-picker.element'; import './modal-layout-property-editor-ui-picker.element'; -import '../../../../../backoffice/editors/shared/editor-layout/editor-layout.element'; +import '../../../../../backoffice/components/body-layout/body-layout.element'; export default { title: 'API/Modals/Layouts/Property Editor UI Picker', From 883f4606900240ba1ac30d3d216e6ad3e729afd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 12 Dec 2022 11:34:58 +0100 Subject: [PATCH 086/223] add margin to data-type editor --- .../views/edit/editor-view-data-type-edit.element.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/views/edit/editor-view-data-type-edit.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/views/edit/editor-view-data-type-edit.element.ts index a28cbaa0c8..ea249de073 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/views/edit/editor-view-data-type-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/data-type/views/edit/editor-view-data-type-edit.element.ts @@ -13,7 +13,15 @@ import '../../../../components/ref-property-editor-ui/ref-property-editor-ui.ele @customElement('umb-editor-view-data-type-edit') export class UmbEditorViewDataTypeEditElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { - static styles = [UUITextStyles, css``]; + static styles = [ + UUITextStyles, + css` + :host { + display:block; + margin: var(--uui-size-layout-1); + } + ` + ]; @state() _dataType?: DataTypeDetails; From 4c66d0926a6f729c030e04762d2072d022e50c3a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 12 Dec 2022 12:45:11 +0100 Subject: [PATCH 087/223] trash documents --- .../actions/action-document-delete.element.ts | 12 +++--- .../trees/documents/tree-documents.element.ts | 8 ++-- .../core/stores/document/document.store.ts | 41 ++++++++++--------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/actions/action-document-delete.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/actions/action-document-delete.element.ts index 4e93c0806d..b94e77b50f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/actions/action-document-delete.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/actions/action-document-delete.element.ts @@ -2,7 +2,7 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, html } from 'lit'; import { customElement } from 'lit/decorators.js'; import { UmbModalService } from '../../../../core/services/modal'; -import { UmbNodeStore } from '../../../../core/stores/node.store'; +import { UmbDocumentStore } from '../../../../core/stores/document/document.store'; import UmbTreeItemActionElement from '../../shared/tree-item-action.element'; import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; @@ -11,7 +11,7 @@ export default class UmbTreeActionDocumentDeleteElement extends UmbContextConsum static styles = [UUITextStyles, css``]; private _modalService?: UmbModalService; - private _nodeStore?: UmbNodeStore; + private _documentStore?: UmbDocumentStore; connectedCallback(): void { super.connectedCallback(); @@ -20,8 +20,8 @@ export default class UmbTreeActionDocumentDeleteElement extends UmbContextConsum this._modalService = modalService; }); - this.consumeContext('umbNodeStore', (nodeStore: UmbNodeStore) => { - this._nodeStore = nodeStore; + this.consumeContext('umbDocumentStore', (documentStore: UmbDocumentStore) => { + this._documentStore = documentStore; }); } @@ -34,8 +34,8 @@ export default class UmbTreeActionDocumentDeleteElement extends UmbContextConsum }); modalHandler?.onClose().then(({ confirmed }: any) => { - if (confirmed && this._treeContextMenuService && this._nodeStore && this._activeTreeItem) { - this._nodeStore?.trash([this._activeTreeItem.key]); + if (confirmed && this._treeContextMenuService && this._documentStore && this._activeTreeItem) { + this._documentStore?.trash([this._activeTreeItem.key]); this._treeContextMenuService.close(); } }); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts index a21b9052e0..8d48a4ca0a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts @@ -7,8 +7,8 @@ import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import { UmbDocumentStore } from 'src/core/stores/document/document.store'; import '../shared/tree-navigator.element'; -@customElement('umb-tree-document') -export class UmbTreeDocumentElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { +@customElement('umb-tree-documents') +export class UmbTreeDocumentsElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { constructor() { super(); @@ -70,10 +70,10 @@ export class UmbTreeDocumentElement extends UmbContextProviderMixin(UmbContextCo } } -export default UmbTreeDocumentElement; +export default UmbTreeDocumentsElement; declare global { interface HTMLElementTagNameMap { - 'umb-tree-document': UmbTreeDocumentElement; + 'umb-tree-documents': UmbTreeDocumentsElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts index b3b2b10e88..764aa192d9 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/document/document.store.ts @@ -17,24 +17,10 @@ export class UmbDocumentStore extends UmbDataStoreBase { this.update(data); }); - + return this.items.pipe(map((documents) => documents.find((document) => document.key === key) || null)); } - async trash(keys: Array) { - // fetch from server and update store - // TODO: Use node type to hit the right API, or have a general Node API? - const res = await fetch('/umbraco/management/api/v1/document/trash', { - method: 'POST', - body: JSON.stringify(keys), - headers: { - 'Content-Type': 'application/json', - }, - }); - const data = await res.json(); - this.update(data); - } - // TODO: make sure UI somehow can follow the status of this action. save(data: DocumentDetails[]): Promise { // fetch from server and update store @@ -62,6 +48,21 @@ export class UmbDocumentStore extends UmbDataStoreBase) { + // fetch from server and update store + // TODO: Use node type to hit the right API, or have a general Node API? + const res = await fetch('/umbraco/management/api/v1/document/trash', { + method: 'POST', + body: JSON.stringify(keys), + headers: { + 'Content-Type': 'application/json', + }, + }); + const data = await res.json(); + this.update(data); + } + getTreeRoot(): Observable> { DocumentResource.getTreeDocumentRoot({}).then( (res) => { @@ -76,8 +77,9 @@ export class UmbDocumentStore extends UmbDataStoreBase items.filter((item) => item.parentKey === null))); + + // TODO: how do we handle trashed items? + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null && item.isTrashed === false))); } getTreeItemChildren(key: string): Observable> { @@ -96,8 +98,9 @@ export class UmbDocumentStore extends UmbDataStoreBase items.filter((item) => item.parentKey === key))); + + // TODO: how do we handle trashed items? + return this.items.pipe(map((items) => items.filter((item) => item.parentKey === key && item.isTrashed === false))); } getTreeItems(keys: Array): Observable> { From 4de39ce51305e542dd4d82092f68e7bff7ad8bd9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 12 Dec 2022 13:29:55 +0100 Subject: [PATCH 088/223] fetch media items --- .../editors/media/editor-media.element.ts | 8 ++- .../editor-content/editor-content.element.ts | 43 +++++++------ .../trees/media/tree-media.element.ts | 1 + .../src/core/mocks/browser-handlers.ts | 2 + .../src/core/mocks/data/media.data.ts | 5 +- .../src/core/mocks/domains/media.handlers.ts | 35 +++++++++++ .../src/core/stores/media/media.store.ts | 63 +++++++++++++++++-- .../src/core/stores/member/member.store.ts | 0 8 files changed, 131 insertions(+), 26 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/core/mocks/domains/media.handlers.ts create mode 100644 src/Umbraco.Web.UI.Client/src/core/stores/member/member.store.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts index 7dd4de4067..2a1658587c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/media/editor-media.element.ts @@ -3,11 +3,13 @@ import { css, html, LitElement } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import type { ManifestEditorView, ManifestWithLoader } from '@umbraco-cms/models'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; +import { UmbMediaStore } from 'src/core/stores/media/media.store'; +import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import '../shared/editor-content/editor-content.element'; @customElement('umb-editor-media') -export class UmbEditorMediaElement extends LitElement { +export class UmbEditorMediaElement extends UmbContextConsumerMixin(UmbContextProviderMixin(LitElement)) { static styles = [ UUITextStyles, css` @@ -26,6 +28,10 @@ export class UmbEditorMediaElement extends LitElement { super(); this._registerEditorViews(); + + this.consumeContext('umbMediaStore', (mediaStore: UmbMediaStore) => { + this.provideContext('umbContentStore', mediaStore); + }); } private _registerEditorViews() { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts index 18d03e63f2..8309db9ea6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts @@ -17,6 +17,8 @@ import '../editor-entity-layout/editor-entity-layout.element'; // TODO: Make this dynamic, use load-extensions method to loop over extensions for this node. import './views/edit/editor-view-content-edit.element'; import './views/info/editor-view-content-info.element'; +import { UmbDocumentStore } from 'src/core/stores/document/document.store'; +import { UmbMediaStore } from 'src/core/stores/media/media.store'; @customElement('umb-editor-content') export class UmbEditorContentElement extends UmbContextProviderMixin( @@ -60,19 +62,19 @@ export class UmbEditorContentElement extends UmbContextProviderMixin( alias!: string; @state() - _node?: NodeEntity; + _content?: NodeEntity; - private _nodeStore?: UmbNodeStore; + private _store?: UmbDocumentStore | UmbMediaStore; private _nodeContext?: UmbNodeContext; private _notificationService?: UmbNotificationService; constructor() { super(); - this.consumeAllContexts(['umbNodeStore', 'umbNotificationService'], (instances) => { - this._nodeStore = instances['umbNodeStore']; + this.consumeAllContexts(['umbContentStore', 'umbNotificationService'], (instances) => { + this._store = instances['umbContentStore']; this._notificationService = instances['umbNotificationService']; - this._useNode(); + this._observeContent(); }); this.addEventListener('property-value-change', this._onPropertyValueChange); @@ -82,7 +84,7 @@ export class UmbEditorContentElement extends UmbContextProviderMixin( const target = e.composedPath()[0] as any; // TODO: Set value. - const property = this._node?.properties.find((x) => x.alias === target.alias); + const property = this._content?.properties.find((x) => x.alias === target.alias); if (property) { this._setPropertyValue(property.alias, target.value); } else { @@ -91,28 +93,29 @@ export class UmbEditorContentElement extends UmbContextProviderMixin( }; private _setPropertyValue(alias: string, value: unknown) { - this._node?.data.forEach((data) => { + this._content?.data.forEach((data) => { if (data.alias === alias) { data.value = value; } }); } - private _useNode() { - if (!this._nodeStore) return; + private _observeContent() { + if (!this._store) return; - this.observe(this._nodeStore.getByKey(this.entityKey), (node) => { - if (!node) return; // TODO: Handle nicely if there is no node. + this.observe(this._store.getByKey(this.entityKey), (content) => { + debugger + if (!content) return; // TODO: Handle nicely if there is no node. if (!this._nodeContext) { - this._nodeContext = new UmbNodeContext(node); + this._nodeContext = new UmbNodeContext(content); this.provideContext('umbNodeContext', this._nodeContext); } else { - this._nodeContext.update(node); + this._nodeContext.update(content); } this.observe(this._nodeContext.data.pipe(distinctUntilChanged()), (data) => { - this._node = data; + this._content = data; }); }); } @@ -122,9 +125,9 @@ export class UmbEditorContentElement extends UmbContextProviderMixin( } private _onSave() { - // TODO: What if store is not present, what if node is not loaded.... - if (this._node) { - this._nodeStore?.save([this._node]).then(() => { + // TODO: What if store is not present, what if content is not loaded.... + if (this._content) { + this._store?.save([this._content]).then(() => { const data: UmbNotificationDefaultData = { message: 'Document Saved' }; this._notificationService?.peek('positive', { data }); }); @@ -161,9 +164,9 @@ export class UmbEditorContentElement extends UmbContextProviderMixin( return html`
- + - ${this._node && this._node.variants.length > 0 + ${this._content && this._content.variants.length > 0 ? html`
@@ -176,7 +179,7 @@ export class UmbEditorContentElement extends UmbContextProviderMixin( - ${this._node && this._node.variants.length > 0 + ${this._content && this._content.variants.length > 0 ? html`