From 7100f90e3296b39769f0ca9c6959f1e666e78665 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Mon, 11 Mar 2024 13:14:29 +0100
Subject: [PATCH 001/280] document blueprints workspace
---
.../src/assets/lang/en-us.ts | 6 +--
...cument-blueprint-root-workspace.element.ts | 50 ++++++++++++++++++-
2 files changed, 51 insertions(+), 5 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts
index b292ea7099..06fbdd808a 100644
--- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts
+++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts
@@ -2467,13 +2467,13 @@ export default {
contentTemplatesDashboard: {
whatHeadline: 'What are Content Blueprints?',
whatDescription:
- 'Content Blueprinta are pre-defined content that can be selected when creating a new\n content node.\n ',
+ 'Content Blueprints are pre-defined content that can be selected when creating a new content node.',
createHeadline: 'How do I create a Content Blueprint?',
createDescription:
- '\n
There are two ways to create a Content Blueprint:
\n \n Right-click a content node and select "Create Content Blueprint" to create a new Content Blueprint. \n Right-click the Content Blueprints tree in the Settings section and select the Document Type you want to create a Content Blueprint for. \n \n Once given a name, editors can start using the Content Blueprint as a foundation for their new page.
\n ',
+ 'There are two ways to create a Content Blueprint:
Right-click a content node and select "Create Content Blueprint" to create a new Content Blueprint. Right-click the Content Blueprints tree in the Settings section and select the Document Type you want to create a Content Blueprint for. Once given a name, editors can start using the Content Blueprint as a foundation for their new page.
',
manageHeadline: 'How do I manage Content Blueprints?',
manageDescription:
- 'You can edit and delete Content Blueprints from the "Content Blueprints" tree in the\n Settings section. Expand the Document Type which the Content Blueprint is based on and click it to edit or delete\n it.\n ',
+ 'You can edit and delete Content Blueprints from the "Content Blueprints" tree in the Settings section. Expand the Document Type which the Content Blueprint is based on and click it to edit or delete it.',
},
preview: {
endLabel: 'End',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-root-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-root-workspace.element.ts
index 327dde4e40..283e3422f8 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-root-workspace.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-root-workspace.element.ts
@@ -1,11 +1,57 @@
-import { html, customElement } from '@umbraco-cms/backoffice/external/lit';
+import { html, customElement, css } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
@customElement('umb-document-blueprint-root-workspace')
export class UmbDocumentBlueprintRootWorkspaceElement extends UmbLitElement {
render() {
- return html`Document Blueprint Root Workspace
`;
+ return html`
+
+
+
+ What are Content Blueprints?
+
+
+ Content Blueprints are pre-defined content that can be selected when creating a new content node.
+
+
+
+ How do I create a Content Blueprint?
+
+
+
+ There are two ways to create a Content Blueprint:
+
+
+ Right-click a content node and select "Create Content Blueprint" to create a new Content Blueprint.
+
+
+ Right-click the Content Blueprints tree in the Settings section and select the Document Type you want to
+ create a Content Blueprint for.
+
+
+ Once given a name, editors can start using the Content Blueprint as a foundation for their new page.
+
+
+
+ How do I manage Content Blueprints?
+
+
+
+ You can edit and delete Content Blueprints from the "Content Blueprints" tree in the Settings section.
+ Expand the Document Type which the Content Blueprint is based on and click it to edit or delete it.
+
+
+
+ `;
}
+
+ static styles = [
+ css`
+ #wrapper {
+ margin: var(--uui-size-layout-1);
+ }
+ `,
+ ];
}
export default UmbDocumentBlueprintRootWorkspaceElement;
From 05bffeb4986d233b05ae85a2bae7b7dffbd0ebb5 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Mon, 11 Mar 2024 14:16:50 +0100
Subject: [PATCH 002/280] manifests, types, etc
---
.../entity-actions/create/create.action.ts | 17 ++++++
.../entity-actions/manifests.ts | 52 +++++++++++++++++++
.../documents/document-blueprints/entity.ts | 9 ++++
.../documents/document-blueprints/index.ts | 1 +
.../document-blueprints/manifests.ts | 3 +-
.../menu-item/manifests.ts | 6 ++-
.../document-blueprints/tree/index.ts | 10 ++++
.../document-blueprints/tree/types.ts | 18 +++++++
.../workspace/manifests.ts | 7 ++-
.../src/packages/documents/index.ts | 1 +
10 files changed, 119 insertions(+), 5 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/create.action.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/types.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/create.action.ts
new file mode 100644
index 0000000000..0b13db78b3
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/create.action.ts
@@ -0,0 +1,17 @@
+import type { UmbEntityActionArgs } from '@umbraco-cms/backoffice/entity-action';
+import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+
+export class UmbCreateEntityAction extends UmbEntityActionBase {
+ constructor(host: UmbControllerHost, args: UmbEntityActionArgs) {
+ super(host, args);
+ }
+
+ async execute() {
+ const url = `section/settings/workspace/document-blueprint/create/parent/${this.args.entityType}/${
+ this.args.unique || 'null'
+ }`;
+ // TODO: how do we handle this with a href?
+ history.pushState(null, '', url);
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts
new file mode 100644
index 0000000000..2580b43adf
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts
@@ -0,0 +1,52 @@
+/*import {
+ UMB_DOCUMENT_BLUEPRINT_DETAIL_REPOSITORY_ALIAS,
+ UMB_DOCUMENT_BLUEPRINT_ITEM_REPOSITORY_ALIAS,
+} from '../repository/index.js';*/
+import {
+ UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
+ UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
+ UMB_DOCUMENT_BLUEPRINT_ITEM_ENTITY_TYPE,
+} from '../entity.js';
+import { UmbCreateEntityAction } from './create/create.action.js';
+import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
+
+const entityActions: Array = [
+ {
+ type: 'entityAction',
+ kind: 'default',
+ alias: 'Umb.EntityAction.DocumentBlueprint.Create',
+ name: 'Create Document Blueprint Entity Action',
+ api: UmbCreateEntityAction,
+ forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE],
+ meta: {
+ icon: 'icon-add',
+ label: 'Create',
+ },
+ },
+ {
+ type: 'entityAction',
+ kind: 'default',
+ alias: 'Umb.EntityAction.DocumentBlueprintItem.Create',
+ name: 'Create Document Blueprint Item Entity Action',
+ api: UmbCreateEntityAction,
+ forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE],
+ meta: {
+ icon: 'icon-add',
+ label: 'Create',
+ },
+ } /*
+ {
+ type: 'entityAction',
+ kind: 'delete',
+ alias: 'Umb.EntityAction.DocumentBlueprintItem.Delete',
+ name: 'Delete Document Blueprint Item Entity Action',
+ forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_ITEM_ENTITY_TYPE],
+ meta: {
+ detailRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_DETAIL_REPOSITORY_ALIAS,
+ itemRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_ITEM_REPOSITORY_ALIAS,
+ },
+ },
+ */,
+];
+
+export const manifests = [...entityActions];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity.ts
new file mode 100644
index 0000000000..3513e0fa94
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity.ts
@@ -0,0 +1,9 @@
+export const UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE = 'document-blueprint-root';
+export const UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE = 'document-blueprint';
+
+export const UMB_DOCUMENT_BLUEPRINT_ITEM_ENTITY_TYPE = 'document-blueprint-item';
+
+export type UmbDocumentBlueprintRootEntityType = typeof UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE;
+export type UmbDocumentBlueprintEntityType = typeof UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE;
+
+export type UmbDocumentBlueprintItemEntityType = typeof UMB_DOCUMENT_BLUEPRINT_ITEM_ENTITY_TYPE;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/index.ts
index e69de29bb2..dab908bbad 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/index.ts
@@ -0,0 +1 @@
+export * from './entity.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/manifests.ts
index ea4e6d7613..de4d9342c5 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/manifests.ts
@@ -1,4 +1,5 @@
import { manifests as menuItemManifests } from './menu-item/manifests.js';
import { manifests as workspaceManifests } from './workspace/manifests.js';
+import { manifests as entityActionManifests } from './entity-actions/manifests.js';
-export const manifests = [...menuItemManifests, ...workspaceManifests];
+export const manifests = [...menuItemManifests, ...workspaceManifests, ...entityActionManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts
index 6c936aa77c..d02216abf6 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts
@@ -1,11 +1,13 @@
-import type { ManifestMenuItem } from '@umbraco-cms/backoffice/extension-registry';
+import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
-const menuItem: ManifestMenuItem = {
+const menuItem: ManifestTypes = {
type: 'menuItem',
+ //kind: 'tree',
alias: 'Umb.MenuItem.DocumentBlueprints',
name: 'Document Blueprints Menu Item',
weight: 100,
meta: {
+ //treeAlias: [UMB_DOCUMENT_BLUEPRINT_TREE_ALIAS]
label: 'Document Blueprints',
icon: 'icon-blueprint',
entityType: 'document-blueprint-root',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts
new file mode 100644
index 0000000000..b4743acd7a
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts
@@ -0,0 +1,10 @@
+/*export { UmbTemplateTreeRepository } from './template-tree.repository.js';
+export {
+ UMB_TEMPLATE_TREE_REPOSITORY_ALIAS,
+ UMB_TEMPLATE_TREE_STORE_ALIAS,
+ UMB_TEMPLATE_TREE_ALIAS,
+} from './manifests.js';
+export { UMB_TEMPLATE_TREE_STORE_CONTEXT } from './template-tree.store.js';
+export { type UmbTemplateTreeStore } from './template-tree.store.js';
+export * from './types.js';
+*/
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/types.ts
new file mode 100644
index 0000000000..ac8ca29477
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/types.ts
@@ -0,0 +1,18 @@
+import type {
+ UmbDocumentBlueprintEntityType,
+ UmbDocumentBlueprintRootEntityType,
+ UmbDocumentBlueprintItemEntityType,
+} from '../entity.js';
+import type { UmbUniqueTreeItemModel, UmbUniqueTreeRootModel } from '@umbraco-cms/backoffice/tree';
+
+export interface UmbDocumentBlueprintTreeItemModel extends UmbUniqueTreeItemModel {
+ entityType: UmbDocumentBlueprintEntityType;
+}
+
+export interface UmbDocumentBlueprintItemTreeItemModel extends UmbUniqueTreeItemModel {
+ entityType: UmbDocumentBlueprintItemEntityType;
+}
+
+export interface UmbDocumentBlueprintTreeRootModel extends UmbUniqueTreeRootModel {
+ entityType: UmbDocumentBlueprintRootEntityType;
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts
index 7983bf294f..08702a94e8 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts
@@ -1,12 +1,15 @@
+import { UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE } from '../entity.js';
import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry';
+export const UMB_DOCUMENT_BLUEPRINT_ROOT_WORKSPACE_ALIAS = 'Umb.Workspace.DocumentBlueprint.Root';
+
const workspace: ManifestWorkspace = {
type: 'workspace',
- alias: 'Umb.Workspace.DocumentBlueprint.Root',
+ alias: UMB_DOCUMENT_BLUEPRINT_ROOT_WORKSPACE_ALIAS,
name: 'Document Blueprint Root Workspace',
element: () => import('./document-blueprint-root-workspace.element.js'),
meta: {
- entityType: 'document-blueprint-root',
+ entityType: UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
},
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/index.ts
index b9cc5c0340..e0f90f8c40 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/index.ts
@@ -1,4 +1,5 @@
import './document-types/index.js';
import './documents/index.js';
+import './document-blueprints/index.js';
export * from './manifests.js';
From e8967bb9349984a01aae5babae2d007b0eac8bc0 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Tue, 12 Mar 2024 10:24:29 +0100
Subject: [PATCH 003/280] mock data
---
.../src/mocks/browser-handlers.ts | 2 +
.../document-blueprint.data.ts | 45 +++++++
.../document-blueprint.db.ts | 110 ++++++++++++++++++
.../document-blueprint/detail.handlers.ts | 48 ++++++++
.../handlers/document-blueprint/index.ts | 5 +
.../document-blueprint/item.handlers.ts | 13 +++
.../mocks/handlers/document-blueprint/slug.ts | 1 +
.../document-blueprint/tree.handlers.ts | 22 ++++
8 files changed, 246 insertions(+)
create mode 100644 src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.data.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.db.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/detail.handlers.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/item.handlers.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/slug.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/tree.handlers.ts
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts
index 161d6e9823..aeb362ecb4 100644
--- a/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts
+++ b/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts
@@ -38,6 +38,7 @@ import { handlers as userHandlers } from './handlers/user/index.js';
import { relationHandlers, relationTypeHandlers } from './handlers/relations/index.js';
import * as manifestsHandlers from './handlers/manifests.handlers.js';
import * as serverHandlers from './handlers/server.handlers.js';
+import { handlers as documentBlueprintHandlers } from './handlers/document-blueprint/index.js';
const handlers = [
...auditLogHandlers,
@@ -79,6 +80,7 @@ const handlers = [
...upgradeHandlers,
...userGroupsHandlers,
...userHandlers,
+ ...documentBlueprintHandlers,
serverHandlers.serverInformationHandler,
];
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.data.ts
new file mode 100644
index 0000000000..6b362e7995
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.data.ts
@@ -0,0 +1,45 @@
+import type { UmbMockDocumentModel } from '../document/document.data.js';
+import { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api';
+
+export interface UmbMockDocumentBlueprintModel extends UmbMockDocumentModel {}
+
+export const data: Array = [
+ {
+ urls: [
+ {
+ culture: 'en-US',
+ url: '/',
+ },
+ ],
+ template: null,
+ id: 'the-simplest-document-id',
+ parent: null,
+ documentType: {
+ id: 'the-simplest-document-type-id',
+ icon: 'icon-document',
+ },
+ hasChildren: false,
+ noAccess: false,
+ isProtected: false,
+ isTrashed: false,
+ variants: [
+ {
+ state: DocumentVariantStateModel.DRAFT,
+ publishDate: '2023-02-06T15:32:24.957009',
+ culture: 'en-us',
+ segment: null,
+ name: 'The Simplest Document',
+ createDate: '2023-02-06T15:32:05.350038',
+ updateDate: '2023-02-06T15:32:24.957009',
+ },
+ ],
+ values: [
+ {
+ alias: 'prop1',
+ culture: null,
+ segment: null,
+ value: 'my blueprint value',
+ },
+ ],
+ },
+];
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.db.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.db.ts
new file mode 100644
index 0000000000..9166a603dc
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.db.ts
@@ -0,0 +1,110 @@
+import { UmbMockEntityTreeManager } from '../utils/entity/entity-tree.manager.js';
+import { UmbMockEntityItemManager } from '../utils/entity/entity-item.manager.js';
+import { UmbMockEntityDetailManager } from '../utils/entity/entity-detail.manager.js';
+import { umbDocumentTypeMockDb } from '../document-type/document-type.db.js';
+import { UmbEntityMockDbBase } from '../utils/entity/entity-base.js';
+import { data } from './document-blueprint.data.js';
+import type { UmbMockDocumentBlueprintModel } from './document-blueprint.data.js';
+import { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api';
+import { UmbId } from '@umbraco-cms/backoffice/id';
+import type {
+ CreateDocumentRequestModel,
+ DocumentItemResponseModel,
+ DocumentResponseModel,
+ DocumentTreeItemResponseModel,
+} from '@umbraco-cms/backoffice/external/backend-api';
+
+export class UmbDocumentBlueprintMockDB extends UmbEntityMockDbBase {
+ tree = new UmbMockEntityTreeManager(this, treeItemMapper);
+ item = new UmbMockEntityItemManager(this, itemMapper);
+ detail = new UmbMockEntityDetailManager(
+ this,
+ createMockDocumentBlueprintMapper,
+ detailResponseMapper,
+ );
+
+ constructor(data: Array) {
+ super(data);
+ }
+}
+
+const treeItemMapper = (model: UmbMockDocumentBlueprintModel): Omit => {
+ const documentType = umbDocumentTypeMockDb.read(model.documentType.id);
+ if (!documentType) throw new Error(`Document type with id ${model.documentType.id} not found`);
+
+ return {
+ documentType: {
+ icon: documentType.icon,
+ id: documentType.id,
+ },
+ hasChildren: model.hasChildren,
+ id: model.id,
+ isProtected: model.isProtected,
+ isTrashed: model.isTrashed,
+ noAccess: model.noAccess,
+ parent: model.parent,
+ variants: model.variants,
+ };
+};
+
+const createMockDocumentBlueprintMapper = (request: CreateDocumentRequestModel): UmbMockDocumentBlueprintModel => {
+ const documentType = umbDocumentTypeMockDb.read(request.documentType.id);
+ if (!documentType) throw new Error(`Document type with id ${request.documentType.id} not found`);
+
+ const now = new Date().toString();
+
+ return {
+ documentType: {
+ id: documentType.id,
+ icon: documentType.icon,
+ collection: undefined, // TODO: get list from doc type when ready
+ },
+ hasChildren: false,
+ id: request.id ? request.id : UmbId.new(),
+ isProtected: false,
+ isTrashed: false,
+ noAccess: false,
+ parent: request.parent,
+ values: request.values,
+ variants: request.variants.map((variantRequest) => {
+ return {
+ culture: variantRequest.culture,
+ segment: variantRequest.segment,
+ name: variantRequest.name,
+ createDate: now,
+ updateDate: now,
+ state: DocumentVariantStateModel.DRAFT,
+ publishDate: null,
+ };
+ }),
+ urls: [],
+ };
+};
+
+const detailResponseMapper = (model: UmbMockDocumentBlueprintModel): DocumentResponseModel => {
+ return {
+ documentType: model.documentType,
+ id: model.id,
+ isTrashed: model.isTrashed,
+ template: model.template,
+ urls: model.urls,
+ values: model.values,
+ variants: model.variants,
+ };
+};
+
+const itemMapper = (model: UmbMockDocumentBlueprintModel): DocumentItemResponseModel => {
+ return {
+ documentType: {
+ collection: model.documentType.collection,
+ icon: model.documentType.icon,
+ id: model.documentType.id,
+ },
+ id: model.id,
+ isProtected: model.isProtected,
+ isTrashed: model.isTrashed,
+ variants: model.variants,
+ };
+};
+
+export const umbDocumentBlueprintMockDb = new UmbDocumentBlueprintMockDB(data);
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/detail.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/detail.handlers.ts
new file mode 100644
index 0000000000..80722ba2a8
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/detail.handlers.ts
@@ -0,0 +1,48 @@
+const { rest } = window.MockServiceWorker;
+import { umbDocumentBlueprintMockDb } from '../../data/document-blueprint/document-blueprint.db.js';
+import { UMB_SLUG } from './slug.js';
+import type {
+ CreateDocumentRequestModel,
+ UpdateDocumentRequestModel,
+} from '@umbraco-cms/backoffice/external/backend-api';
+import { umbracoPath } from '@umbraco-cms/backoffice/utils';
+
+export const detailHandlers = [
+ rest.post(umbracoPath(`${UMB_SLUG}`), async (req, res, ctx) => {
+ const requestBody = (await req.json()) as CreateDocumentRequestModel;
+ if (!requestBody) return res(ctx.status(400, 'no body found'));
+
+ const id = umbDocumentBlueprintMockDb.detail.create(requestBody);
+
+ return res(
+ ctx.status(201),
+ ctx.set({
+ Location: req.url.href + '/' + id,
+ 'Umb-Generated-Resource': id,
+ }),
+ );
+ }),
+
+ rest.get(umbracoPath(`${UMB_SLUG}/:id`), (req, res, ctx) => {
+ const id = req.params.id as string;
+ if (!id) return res(ctx.status(400));
+ const response = umbDocumentBlueprintMockDb.detail.read(id);
+ return res(ctx.status(200), ctx.json(response));
+ }),
+
+ rest.put(umbracoPath(`${UMB_SLUG}/:id`), async (req, res, ctx) => {
+ const id = req.params.id as string;
+ if (!id) return res(ctx.status(400));
+ const requestBody = (await req.json()) as UpdateDocumentRequestModel;
+ if (!requestBody) return res(ctx.status(400, 'no body found'));
+ umbDocumentBlueprintMockDb.detail.update(id, requestBody);
+ return res(ctx.status(200));
+ }),
+
+ rest.delete(umbracoPath(`${UMB_SLUG}/:id`), (req, res, ctx) => {
+ const id = req.params.id as string;
+ if (!id) return res(ctx.status(400));
+ umbDocumentBlueprintMockDb.detail.delete(id);
+ return res(ctx.status(200));
+ }),
+];
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/index.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/index.ts
new file mode 100644
index 0000000000..236354678a
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/index.ts
@@ -0,0 +1,5 @@
+import { treeHandlers } from './tree.handlers.js';
+import { itemHandlers } from './item.handlers.js';
+import { detailHandlers } from './detail.handlers.js';
+
+export const handlers = [...treeHandlers, ...itemHandlers, ...detailHandlers];
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/item.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/item.handlers.ts
new file mode 100644
index 0000000000..377e4343d8
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/item.handlers.ts
@@ -0,0 +1,13 @@
+const { rest } = window.MockServiceWorker;
+import { umbDocumentBlueprintMockDb } from '../../data/document-blueprint/document-blueprint.db.js';
+import { UMB_SLUG } from './slug.js';
+import { umbracoPath } from '@umbraco-cms/backoffice/utils';
+
+export const itemHandlers = [
+ rest.get(umbracoPath(`/item${UMB_SLUG}`), (req, res, ctx) => {
+ const ids = req.url.searchParams.getAll('id');
+ if (!ids) return;
+ const items = umbDocumentBlueprintMockDb.item.getItems(ids);
+ return res(ctx.status(200), ctx.json(items));
+ }),
+];
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/slug.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/slug.ts
new file mode 100644
index 0000000000..f877ec0b7a
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/slug.ts
@@ -0,0 +1 @@
+export const UMB_SLUG = '/document-blueprint';
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/tree.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/tree.handlers.ts
new file mode 100644
index 0000000000..fda1cfb47f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-blueprint/tree.handlers.ts
@@ -0,0 +1,22 @@
+const { rest } = window.MockServiceWorker;
+import { umbDocumentBlueprintMockDb } from '../../data/document-blueprint/document-blueprint.db.js';
+import { UMB_SLUG } from './slug.js';
+import { umbracoPath } from '@umbraco-cms/backoffice/utils';
+
+export const treeHandlers = [
+ rest.get(umbracoPath(`/tree${UMB_SLUG}/root`), (req, res, ctx) => {
+ const skip = Number(req.url.searchParams.get('skip'));
+ const take = Number(req.url.searchParams.get('take'));
+ const response = umbDocumentBlueprintMockDb.tree.getRoot({ skip, take });
+ return res(ctx.status(200), ctx.json(response));
+ }),
+
+ rest.get(umbracoPath(`/tree${UMB_SLUG}/children`), (req, res, ctx) => {
+ const parentId = req.url.searchParams.get('parentId');
+ if (!parentId) return;
+ const skip = Number(req.url.searchParams.get('skip'));
+ const take = Number(req.url.searchParams.get('take'));
+ const response = umbDocumentBlueprintMockDb.tree.getChildrenOf({ parentId, skip, take });
+ return res(ctx.status(200), ctx.json(response));
+ }),
+];
From c2e8dc11a59c6793b830ceaf89e666d25d7b1192 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Tue, 12 Mar 2024 10:50:30 +0100
Subject: [PATCH 004/280] tree
---
.../documents/document-blueprints/entity.ts | 6 +-
.../document-blueprint-tree.repository.ts | 28 ++++
...ument-blueprint-tree.server.data-source.ts | 57 ++++++++
.../tree/document-blueprint-tree.store.ts | 40 ++++++
.../document-blueprint-folder.repository.ts | 9 ++
...ent-blueprint-folder.server.data-source.ts | 122 ++++++++++++++++++
.../document-blueprints/tree/folder/index.ts | 2 +
.../tree/folder/manifests.ts | 37 ++++++
.../document-blueprints/tree/folder/types.ts | 6 +
.../document-blueprints/tree/index.ts | 12 +-
.../document-blueprints/tree/manifests.ts | 56 ++++++++
.../reload-tree-item-children/manifests.ts | 21 +++
.../document-blueprints/tree/types.ts | 8 +-
13 files changed, 384 insertions(+), 20 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.repository.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.store.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.repository.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.server.data-source.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/types.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/reload-tree-item-children/manifests.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity.ts
index 3513e0fa94..8aa8201389 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity.ts
@@ -1,9 +1,7 @@
export const UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE = 'document-blueprint-root';
export const UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE = 'document-blueprint';
-
-export const UMB_DOCUMENT_BLUEPRINT_ITEM_ENTITY_TYPE = 'document-blueprint-item';
+export const UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE = 'document-blueprint-folder';
export type UmbDocumentBlueprintRootEntityType = typeof UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE;
export type UmbDocumentBlueprintEntityType = typeof UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE;
-
-export type UmbDocumentBlueprintItemEntityType = typeof UMB_DOCUMENT_BLUEPRINT_ITEM_ENTITY_TYPE;
+export type UmbDocumentBlueprintFolderEntityType = typeof UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.repository.ts
new file mode 100644
index 0000000000..31dd948145
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.repository.ts
@@ -0,0 +1,28 @@
+import { UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE } from '../entity.js';
+import { UmbDocumentBlueprintTreeServerDataSource } from './document-blueprint-tree.server.data-source.js';
+import { UMB_DOCUMENT_BLUEPRINT_TREE_STORE_CONTEXT } from './document-blueprint-tree.store.js';
+import type { UmbDocumentBlueprintTreeItemModel, UmbDocumentBlueprintTreeRootModel } from './types.js';
+import { UmbTreeRepositoryBase } from '@umbraco-cms/backoffice/tree';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
+
+export class UmbDocumentBlueprintTreeRepository
+ extends UmbTreeRepositoryBase
+ implements UmbApi
+{
+ constructor(host: UmbControllerHost) {
+ super(host, UmbDocumentBlueprintTreeServerDataSource, UMB_DOCUMENT_BLUEPRINT_TREE_STORE_CONTEXT);
+ }
+
+ async requestTreeRoot() {
+ const data: UmbDocumentBlueprintTreeRootModel = {
+ unique: null,
+ entityType: UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
+ name: 'Document Blueprints',
+ hasChildren: true,
+ isFolder: true,
+ };
+
+ return { data };
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts
new file mode 100644
index 0000000000..9c69239988
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts
@@ -0,0 +1,57 @@
+import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE, UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../entity.js';
+import type { UmbDocumentBlueprintTreeItemModel } from './types.js';
+import type { UmbTreeChildrenOfRequestArgs, UmbTreeRootItemsRequestArgs } from '@umbraco-cms/backoffice/tree';
+import { UmbTreeServerDataSourceBase } from '@umbraco-cms/backoffice/tree';
+import type { DocumentBlueprintTreeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
+import { DocumentBlueprintResource } from '@umbraco-cms/backoffice/external/backend-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+
+/**
+ * A data source for a data type tree that fetches data from the server
+ * @export
+ * @class UmbDocumentBlueprintTreeServerDataSource
+ * @implements {DocumentTreeDataSource}
+ */
+export class UmbDocumentBlueprintTreeServerDataSource extends UmbTreeServerDataSourceBase<
+ DocumentBlueprintTreeItemResponseModel,
+ UmbDocumentBlueprintTreeItemModel
+> {
+ /**
+ * Creates an instance of UmbDocumentBlueprintTreeServerDataSource.
+ * @param {UmbControllerHost} host
+ * @memberof UmbDocumentBlueprintTreeServerDataSource
+ */
+ constructor(host: UmbControllerHost) {
+ super(host, {
+ getRootItems,
+ getChildrenOf,
+ mapper,
+ });
+ }
+}
+
+const getRootItems = (args: UmbTreeRootItemsRequestArgs) =>
+ // eslint-disable-next-line local-rules/no-direct-api-import
+ DocumentBlueprintResource.getTreeDocumentBlueprintRoot({ skip: args.skip, take: args.take });
+
+const getChildrenOf = (args: UmbTreeChildrenOfRequestArgs) => {
+ if (args.parentUnique === null) {
+ return getRootItems(args);
+ } else {
+ // eslint-disable-next-line local-rules/no-direct-api-import
+ return DocumentBlueprintResource.getTreeDocumentBlueprintChildren({
+ parentId: args.parentUnique,
+ });
+ }
+};
+
+const mapper = (item: DocumentBlueprintTreeItemResponseModel): UmbDocumentBlueprintTreeItemModel => {
+ return {
+ unique: item.id,
+ parentUnique: item.parent?.id || null,
+ name: item.name,
+ entityType: item.isFolder ? UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE : UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
+ isFolder: item.isFolder,
+ hasChildren: item.hasChildren,
+ };
+};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.store.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.store.ts
new file mode 100644
index 0000000000..543f5fa479
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.store.ts
@@ -0,0 +1,40 @@
+import { UMB_DOCUMENT_BLUEPRINT_DETAIL_STORE_CONTEXT } from '../repository/index.js';
+import type { UmbDocumentBlueprintDetailModel } from '../types.js';
+import type { UmbDocumentBlueprintTreeItemModel } from './types.js';
+import { UmbUniqueTreeStore } from '@umbraco-cms/backoffice/tree';
+import { UmbStoreConnector } from '@umbraco-cms/backoffice/store';
+import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+
+/**
+ * @export
+ * @class UmbDocumentBlueprintTreeStore
+ * @extends {UmbStoreBase}
+ * @description - Tree Data Store for Document Blueprints
+ */
+export class UmbDocumentBlueprintTreeStore extends UmbUniqueTreeStore {
+ /**
+ * Creates an instance of UmbDocumentBlueprintTreeStore.
+ * @param {UmbControllerHost} host
+ * @memberof UmbDocumentBlueprintTreeStore
+ */
+ constructor(host: UmbControllerHost) {
+ super(host, UMB_DOCUMENT_BLUEPRINT_TREE_STORE_CONTEXT.toString());
+
+ new UmbStoreConnector(host, {
+ store: this,
+ connectToStoreAlias: UMB_DOCUMENT_BLUEPRINT_DETAIL_STORE_CONTEXT,
+ updateStoreItemMapper: (item) => this.#updateTreeItemMapper(item),
+ });
+ }
+
+ #updateTreeItemMapper = (item: UmbDocumentBlueprintDetailModel) => {
+ return {
+ name: item.name,
+ };
+ };
+}
+
+export const UMB_DOCUMENT_BLUEPRINT_TREE_STORE_CONTEXT = new UmbContextToken(
+ 'UmbDocumentBlueprintTreeStore',
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.repository.ts
new file mode 100644
index 0000000000..4510666a59
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.repository.ts
@@ -0,0 +1,9 @@
+import { UmbDocumentBlueprintFolderServerDataSource } from './document-blueprint-folder.server.data-source.js';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { UmbFolderRepositoryBase } from '@umbraco-cms/backoffice/tree';
+
+export class UmbDocumentBlueprintFolderRepository extends UmbFolderRepositoryBase {
+ constructor(host: UmbControllerHost) {
+ super(host, UmbDocumentBlueprintFolderServerDataSource);
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.server.data-source.ts
new file mode 100644
index 0000000000..a3dd268887
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.server.data-source.ts
@@ -0,0 +1,122 @@
+import type { UmbCreateFolderModel, UmbFolderDataSource, UmbUpdateFolderModel } from '@umbraco-cms/backoffice/tree';
+import { DocumentBlueprintResource } from '@umbraco-cms/backoffice/external/backend-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
+
+/**
+ * A data source for a Document Blueprint folder that fetches data from the server
+ * @export
+ * @class UmbDocumentBlueprintFolderServerDataSource
+ * @implements {RepositoryDetailDataSource}
+ */
+export class UmbDocumentBlueprintFolderServerDataSource implements UmbFolderDataSource {
+ #host: UmbControllerHost;
+
+ /**
+ * Creates an instance of UmbDocumentBlueprintFolderServerDataSource.
+ * @param {UmbControllerHost} host
+ * @memberof UmbDocumentBlueprintFolderServerDataSource
+ */
+ constructor(host: UmbControllerHost) {
+ this.#host = host;
+ }
+
+ /**
+ * Fetches a Document Blueprint folder from the server
+ * @param {string} unique
+ * @return {*}
+ * @memberof UmbDocumentBlueprintFolderServerDataSource
+ */
+ async read(unique: string) {
+ if (!unique) throw new Error('Unique is missing');
+
+ const { data, error } = await tryExecuteAndNotify(
+ this.#host,
+ DocumentBlueprintResource.getDocumentBlueprintFolderById({
+ id: unique,
+ }),
+ );
+
+ if (data) {
+ const mappedData = {
+ unique: data.id,
+ name: data.name,
+ };
+
+ return { data: mappedData };
+ }
+
+ return { error };
+ }
+
+ /**
+ * Creates a Document Blueprint folder on the server
+ * @param {UmbCreateFolderModel} args
+ * @return {*}
+ * @memberof UmbDocumentBlueprintFolderServerDataSource
+ */
+ async create(args: UmbCreateFolderModel) {
+ if (args.parentUnique === undefined) throw new Error('Parent unique is missing');
+ if (!args.name) throw new Error('Name is missing');
+
+ const requestBody = {
+ id: args.unique,
+ parent: args.parentUnique ? { id: args.parentUnique } : null,
+ name: args.name,
+ };
+
+ const { error } = await tryExecuteAndNotify(
+ this.#host,
+ DocumentBlueprintResource.postDocumentBlueprintFolder({
+ requestBody,
+ }),
+ );
+
+ if (!error) {
+ return this.read(args.unique);
+ }
+
+ return { error };
+ }
+
+ /**
+ * Updates a Document Blueprint folder on the server
+ * @param {UmbUpdateFolderModel} args
+ * @return {*}
+ * @memberof UmbDocumentBlueprintFolderServerDataSource
+ */
+ async update(args: UmbUpdateFolderModel) {
+ if (!args.unique) throw new Error('Unique is missing');
+ if (!args.name) throw new Error('Folder name is missing');
+
+ const { error } = await tryExecuteAndNotify(
+ this.#host,
+ DocumentBlueprintResource.putDocumentBlueprintFolderById({
+ id: args.unique,
+ requestBody: { name: args.name },
+ }),
+ );
+
+ if (!error) {
+ return this.read(args.unique);
+ }
+
+ return { error };
+ }
+
+ /**
+ * Deletes a Document Blueprint folder on the server
+ * @param {string} unique
+ * @return {*}
+ * @memberof UmbDocumentBlueprintServerDataSource
+ */
+ async delete(unique: string) {
+ if (!unique) throw new Error('Unique is missing');
+ return tryExecuteAndNotify(
+ this.#host,
+ DocumentBlueprintResource.deleteDocumentBlueprintFolderById({
+ id: unique,
+ }),
+ );
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/index.ts
new file mode 100644
index 0000000000..29904de469
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/index.ts
@@ -0,0 +1,2 @@
+export { UmbDocumentBlueprintFolderRepository } from './document-blueprint-folder.repository.js';
+export { UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS } from './manifests.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/manifests.ts
new file mode 100644
index 0000000000..9eef583220
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/manifests.ts
@@ -0,0 +1,37 @@
+import { UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../../entity.js';
+import { UmbDocumentBlueprintFolderRepository } from './document-blueprint-folder.repository.js';
+import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
+
+export const UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS = 'Umb.Repository.DocumentBlueprint.Folder';
+
+const folderRepository: ManifestRepository = {
+ type: 'repository',
+ alias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS,
+ name: 'Document Blueprint Folder Repository',
+ api: UmbDocumentBlueprintFolderRepository,
+};
+
+const entityActions: Array = [
+ {
+ type: 'entityAction',
+ kind: 'folderUpdate',
+ alias: 'Umb.EntityAction.DocumentBlueprint.Folder.Rename',
+ name: 'Rename Document Blueprint Folder Entity Action',
+ forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE],
+ meta: {
+ folderRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS,
+ },
+ },
+ {
+ type: 'entityAction',
+ kind: 'folderDelete',
+ alias: 'Umb.EntityAction.DocumentBlueprint.Folder.Delete',
+ name: 'Delete Document Blueprint Folder Entity Action',
+ forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE],
+ meta: {
+ folderRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS,
+ },
+ },
+];
+
+export const manifests = [folderRepository, ...entityActions];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/types.ts
new file mode 100644
index 0000000000..dd70703d94
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/types.ts
@@ -0,0 +1,6 @@
+import type { UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../../entity.js';
+import type { UmbDocumentBlueprintTreeItemModel } from '../types.js';
+
+export interface UmbDocumentBlueprintFolderTreeItemModel extends UmbDocumentBlueprintTreeItemModel {
+ entityType: typeof UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE;
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts
index b4743acd7a..f098c0956c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts
@@ -1,10 +1,2 @@
-/*export { UmbTemplateTreeRepository } from './template-tree.repository.js';
-export {
- UMB_TEMPLATE_TREE_REPOSITORY_ALIAS,
- UMB_TEMPLATE_TREE_STORE_ALIAS,
- UMB_TEMPLATE_TREE_ALIAS,
-} from './manifests.js';
-export { UMB_TEMPLATE_TREE_STORE_CONTEXT } from './template-tree.store.js';
-export { type UmbTemplateTreeStore } from './template-tree.store.js';
-export * from './types.js';
-*/
+export { UMB_DOCUMENT_BLUEPRINT_TREE_STORE_CONTEXT } from './document-blueprint-tree.store.js';
+export * from './folder/index.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/manifests.ts
new file mode 100644
index 0000000000..f69949127f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/manifests.ts
@@ -0,0 +1,56 @@
+import {
+ UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
+ UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE,
+ UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
+} from '../entity.js';
+import { manifests as folderManifests } from './folder/manifests.js';
+import { manifests as reloadManifests } from './reload-tree-item-children/manifests.js';
+import { UmbDocumentBlueprintTreeRepository } from './document-blueprint-tree.repository.js';
+import { UmbDocumentBlueprintTreeStore } from './document-blueprint-tree.store.js';
+import type {
+ ManifestRepository,
+ ManifestTree,
+ ManifestTreeItem,
+ ManifestTreeStore,
+} from '@umbraco-cms/backoffice/extension-registry';
+
+export const UMB_DOCUMENT_BLUEPRINT_TREE_REPOSITORY_ALIAS = 'Umb.Repository.DocumentBlueprint.Tree';
+export const UMB_DOCUMENT_BLUEPRINT_TREE_STORE_ALIAS = 'Umb.Store.DocumentBlueprint.Tree';
+
+const treeRepository: ManifestRepository = {
+ type: 'repository',
+ alias: UMB_DOCUMENT_BLUEPRINT_TREE_REPOSITORY_ALIAS,
+ name: 'Document Blueprint Tree Repository',
+ api: UmbDocumentBlueprintTreeRepository,
+};
+
+const treeStore: ManifestTreeStore = {
+ type: 'treeStore',
+ alias: UMB_DOCUMENT_BLUEPRINT_TREE_STORE_ALIAS,
+ name: 'Document Blueprint Tree Store',
+ api: UmbDocumentBlueprintTreeStore,
+};
+
+const tree: ManifestTree = {
+ type: 'tree',
+ kind: 'default',
+ alias: 'Umb.Tree.DocumentBlueprint',
+ name: 'Document Blueprints Tree',
+ meta: {
+ repositoryAlias: UMB_DOCUMENT_BLUEPRINT_TREE_REPOSITORY_ALIAS,
+ },
+};
+
+const treeItem: ManifestTreeItem = {
+ type: 'treeItem',
+ kind: 'default',
+ alias: 'Umb.TreeItem.DocumentBlueprint',
+ name: 'Document Blueprint Tree Item',
+ forEntityTypes: [
+ UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
+ UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
+ UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE,
+ ],
+};
+
+export const manifests = [treeRepository, treeStore, tree, treeItem, ...folderManifests, ...reloadManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/reload-tree-item-children/manifests.ts
new file mode 100644
index 0000000000..d2071f88c7
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/reload-tree-item-children/manifests.ts
@@ -0,0 +1,21 @@
+import {
+ UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
+ UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE,
+ UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
+} from '../../entity.js';
+import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifests: Array = [
+ {
+ type: 'entityAction',
+ kind: 'reloadTreeItemChildren',
+ alias: 'Umb.EntityAction.DocumentBlueprint.Tree.ReloadChildrenOf',
+ name: 'Reload Document Blueprint Tree Item Children Entity Action',
+ forEntityTypes: [
+ UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
+ UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
+ UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE,
+ ],
+ meta: {},
+ },
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/types.ts
index ac8ca29477..3d58af58a2 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/types.ts
@@ -1,16 +1,12 @@
import type {
UmbDocumentBlueprintEntityType,
+ UmbDocumentBlueprintFolderEntityType,
UmbDocumentBlueprintRootEntityType,
- UmbDocumentBlueprintItemEntityType,
} from '../entity.js';
import type { UmbUniqueTreeItemModel, UmbUniqueTreeRootModel } from '@umbraco-cms/backoffice/tree';
export interface UmbDocumentBlueprintTreeItemModel extends UmbUniqueTreeItemModel {
- entityType: UmbDocumentBlueprintEntityType;
-}
-
-export interface UmbDocumentBlueprintItemTreeItemModel extends UmbUniqueTreeItemModel {
- entityType: UmbDocumentBlueprintItemEntityType;
+ entityType: UmbDocumentBlueprintEntityType | UmbDocumentBlueprintFolderEntityType;
}
export interface UmbDocumentBlueprintTreeRootModel extends UmbUniqueTreeRootModel {
From 671335cdbe4decff28c53f4e59e59701c79fcd2d Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Tue, 12 Mar 2024 12:45:10 +0100
Subject: [PATCH 005/280] blueprint repo
---
.../document-blueprints/manifests.ts | 3 +-
.../menu-item/manifests.ts | 4 +-
.../document-blueprint-detail.repository.ts | 11 +
...ent-blueprint-detail.server.data-source.ts | 206 ++++++++++++++++++
.../detail/document-blueprint-detail.store.ts | 25 +++
.../repository/detail/index.ts | 3 +
.../repository/detail/manifests.ts | 23 ++
.../document-blueprints/repository/index.ts | 7 +
.../document-blueprint-item.repository.ts | 11 +
...ument-blueprint-item.server.data-source.ts | 54 +++++
.../item/document-blueprint-item.store.ts | 26 +++
.../repository/item/index.ts | 2 +
.../repository/item/manifests.ts | 22 ++
.../repository/item/types.ts | 23 ++
.../repository/manifests.ts | 4 +
...ument-blueprint-tree.server.data-source.ts | 4 +-
.../tree/document-blueprint-tree.store.ts | 6 +-
.../documents/document-blueprints/types.ts | 39 ++++
.../workspace/manifests.ts | 27 ++-
19 files changed, 489 insertions(+), 11 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.repository.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.store.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.repository.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.server.data-source.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.store.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/types.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/manifests.ts
index de4d9342c5..74655fc3d7 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/manifests.ts
@@ -1,5 +1,6 @@
import { manifests as menuItemManifests } from './menu-item/manifests.js';
import { manifests as workspaceManifests } from './workspace/manifests.js';
import { manifests as entityActionManifests } from './entity-actions/manifests.js';
+import { manifests as treeManifests } from './tree/manifests.js';
-export const manifests = [...menuItemManifests, ...workspaceManifests, ...entityActionManifests];
+export const manifests = [...menuItemManifests, ...workspaceManifests, ...entityActionManifests, ...treeManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts
index d02216abf6..a7547172ba 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts
@@ -2,12 +2,12 @@ import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
const menuItem: ManifestTypes = {
type: 'menuItem',
- //kind: 'tree',
+ kind: 'tree',
alias: 'Umb.MenuItem.DocumentBlueprints',
name: 'Document Blueprints Menu Item',
weight: 100,
meta: {
- //treeAlias: [UMB_DOCUMENT_BLUEPRINT_TREE_ALIAS]
+ treeAlias: 'Umb.Tree.DocumentBlueprint',
label: 'Document Blueprints',
icon: 'icon-blueprint',
entityType: 'document-blueprint-root',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.repository.ts
new file mode 100644
index 0000000000..0ba747f00b
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.repository.ts
@@ -0,0 +1,11 @@
+import type { UmbDocumentBlueprintDetailModel } from '../../types.js';
+import { UmbDocumentBlueprintServerDataSource } from './document-blueprint-detail.server.data-source.js';
+import { UMB_DOCUMENT_BLUEPRINT_DETAIL_STORE_CONTEXT } from './document-blueprint-detail.store.js';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { UmbDetailRepositoryBase } from '@umbraco-cms/backoffice/repository';
+
+export class UmbDocumentBlueprintDetailRepository extends UmbDetailRepositoryBase {
+ constructor(host: UmbControllerHost) {
+ super(host, UmbDocumentBlueprintServerDataSource, UMB_DOCUMENT_BLUEPRINT_DETAIL_STORE_CONTEXT);
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts
new file mode 100644
index 0000000000..3cfc56e569
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts
@@ -0,0 +1,206 @@
+import type { UmbDocumentBlueprintDetailModel, UmbDocumentBlueprintVariantModel } from '../../types.js';
+import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE } from '../../entity.js';
+import { UmbId } from '@umbraco-cms/backoffice/id';
+import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository';
+import type {
+ CreateDocumentRequestModel,
+ UpdateDocumentRequestModel,
+} from '@umbraco-cms/backoffice/external/backend-api';
+import { DocumentResource } from '@umbraco-cms/backoffice/external/backend-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
+
+/**
+ * A data source for the Document that fetches data from the server
+ * @export
+ * @class UmbDocumentBlueprintServerDataSource
+ * @implements {RepositoryDetailDataSource}
+ */
+export class UmbDocumentBlueprintServerDataSource implements UmbDetailDataSource {
+ #host: UmbControllerHost;
+
+ /**
+ * Creates an instance of UmbDocumentBlueprintServerDataSource.
+ * @param {UmbControllerHost} host
+ * @memberof UmbDocumentBlueprintServerDataSource
+ */
+ constructor(host: UmbControllerHost) {
+ this.#host = host;
+ }
+
+ /**
+ * Creates a new Document scaffold
+ * @return { UmbDocumentBlueprintDetailModel }
+ * @memberof UmbDocumentBlueprintServerDataSource
+ */
+ async createScaffold(preset: Partial = {}) {
+ const data: UmbDocumentBlueprintDetailModel = {
+ entityType: UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
+ unique: UmbId.new(),
+ urls: [],
+ template: null,
+ documentType: {
+ unique: '',
+ collection: null,
+ },
+ isTrashed: false,
+ values: [],
+ variants: [],
+ ...preset,
+ };
+
+ return { data };
+ }
+
+ /**
+ * Creates a new variant scaffold.
+ * @returns A new variant scaffold.
+ */
+ /*
+ // TDOD: remove if not used
+ createVariantScaffold(): UmbDocumentBlueprintVariantModel {
+ return {
+ state: null,
+ culture: null,
+ segment: null,
+ name: '',
+ publishDate: null,
+ createDate: null,
+ updateDate: null,
+ };
+ }
+ */
+
+ /**
+ * Fetches a Document with the given id from the server
+ * @param {string} unique
+ * @return {*}
+ * @memberof UmbDocumentBlueprintServerDataSource
+ */
+ async read(unique: string) {
+ if (!unique) throw new Error('Unique is missing');
+
+ const { data, error } = await tryExecuteAndNotify(this.#host, DocumentResource.getDocumentById({ id: unique }));
+
+ if (error || !data) {
+ return { error };
+ }
+
+ // TODO: make data mapper to prevent errors
+ const document: UmbDocumentBlueprintDetailModel = {
+ entityType: UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
+ unique: data.id,
+ values: data.values.map((value) => {
+ return {
+ alias: value.alias,
+ culture: value.culture || null,
+ segment: value.segment || null,
+ value: value.value,
+ };
+ }),
+ variants: data.variants.map((variant) => {
+ return {
+ state: variant.state,
+ culture: variant.culture || null,
+ segment: variant.segment || null,
+ name: variant.name,
+ publishDate: variant.publishDate || null,
+ createDate: variant.createDate,
+ updateDate: variant.updateDate,
+ };
+ }),
+ urls: data.urls.map((url) => {
+ return {
+ culture: url.culture || null,
+ url: url.url,
+ };
+ }),
+ template: data.template ? { unique: data.template.id } : null,
+ documentType: {
+ unique: data.documentType.id,
+ collection: data.documentType.collection ? { unique: data.documentType.collection.id } : null,
+ },
+ isTrashed: data.isTrashed,
+ };
+
+ return { data: document };
+ }
+
+ /**
+ * Inserts a new Document on the server
+ * @param {UmbDocumentBlueprintDetailModel} model
+ * @return {*}
+ * @memberof UmbDocumentBlueprintServerDataSource
+ */
+ async create(model: UmbDocumentBlueprintDetailModel, parentUnique: string | null = null) {
+ if (!model) throw new Error('Document is missing');
+ if (!model.unique) throw new Error('Document unique is missing');
+
+ // TODO: make data mapper to prevent errors
+ const requestBody: CreateDocumentRequestModel = {
+ id: model.unique,
+ parent: parentUnique ? { id: parentUnique } : null,
+ documentType: { id: model.documentType.unique },
+ template: model.template ? { id: model.template.unique } : null,
+ values: model.values,
+ variants: model.variants,
+ };
+
+ const { data, error } = await tryExecuteAndNotify(
+ this.#host,
+ DocumentResource.postDocument({
+ requestBody,
+ }),
+ );
+
+ if (data) {
+ return this.read(data);
+ }
+
+ return { error };
+ }
+
+ /**
+ * Updates a Document on the server
+ * @param {UmbDocumentBlueprintDetailModel} Document
+ * @return {*}
+ * @memberof UmbDocumentBlueprintServerDataSource
+ */
+ async update(model: UmbDocumentBlueprintDetailModel) {
+ if (!model.unique) throw new Error('Unique is missing');
+
+ // TODO: make data mapper to prevent errors
+ const requestBody: UpdateDocumentRequestModel = {
+ template: model.template ? { id: model.template.unique } : null,
+ values: model.values,
+ variants: model.variants,
+ };
+
+ const { error } = await tryExecuteAndNotify(
+ this.#host,
+ DocumentResource.putDocumentById({
+ id: model.unique,
+ requestBody,
+ }),
+ );
+
+ if (!error) {
+ return this.read(model.unique);
+ }
+
+ return { error };
+ }
+
+ /**
+ * Deletes a Document on the server
+ * @param {string} unique
+ * @return {*}
+ * @memberof UmbDocumentBlueprintServerDataSource
+ */
+ async delete(unique: string) {
+ if (!unique) throw new Error('Unique is missing');
+
+ // TODO: update to delete when implemented
+ return tryExecuteAndNotify(this.#host, DocumentResource.putDocumentByIdMoveToRecycleBin({ id: unique }));
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.store.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.store.ts
new file mode 100644
index 0000000000..844ad7543e
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.store.ts
@@ -0,0 +1,25 @@
+import type { UmbDocumentBlueprintDetailModel } from '../../types.js';
+import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
+import { UmbDetailStoreBase } from '@umbraco-cms/backoffice/store';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+
+/**
+ * @export
+ * @class UmbDocumentBlueprintDetailStore
+ * @extends {UmbStoreBase}
+ * @description - Data Store for Document Blueprint Details
+ */
+export class UmbDocumentBlueprintDetailStore extends UmbDetailStoreBase {
+ /**
+ * Creates an instance of UmbDocumentBlueprintDetailStore.
+ * @param {UmbControllerHost} host
+ * @memberof UmbDocumentBlueprintDetailStore
+ */
+ constructor(host: UmbControllerHost) {
+ super(host, UMB_DOCUMENT_BLUEPRINT_DETAIL_STORE_CONTEXT.toString());
+ }
+}
+
+export const UMB_DOCUMENT_BLUEPRINT_DETAIL_STORE_CONTEXT = new UmbContextToken(
+ 'UmbDocumentBlueprintDetailStore',
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/index.ts
new file mode 100644
index 0000000000..8f95154dd2
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/index.ts
@@ -0,0 +1,3 @@
+export { UmbDocumentBlueprintDetailRepository } from './document-blueprint-detail.repository.js';
+export { UMB_DOCUMENT_BLUEPRINT_DETAIL_REPOSITORY_ALIAS } from './manifests.js';
+export { UMB_DOCUMENT_BLUEPRINT_DETAIL_STORE_CONTEXT } from './document-blueprint-detail.store.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/manifests.ts
new file mode 100644
index 0000000000..923eb105ae
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/manifests.ts
@@ -0,0 +1,23 @@
+import { UmbDocumentBlueprintDetailRepository } from './document-blueprint-detail.repository.js';
+import { UmbDocumentBlueprintDetailStore } from './document-blueprint-detail.store.js';
+import type { ManifestRepository, ManifestStore } from '@umbraco-cms/backoffice/extension-registry';
+
+export const UMB_DOCUMENT_BLUEPRINT_DETAIL_REPOSITORY_ALIAS = 'Umb.Repository.DocumentBlueprint.Detail';
+
+const repository: ManifestRepository = {
+ type: 'repository',
+ alias: UMB_DOCUMENT_BLUEPRINT_DETAIL_REPOSITORY_ALIAS,
+ name: 'Document Blueprint Detail Repository',
+ api: UmbDocumentBlueprintDetailRepository,
+};
+
+export const UMB_DOCUMENT_BLUEPRINT_DETAIL_STORE_ALIAS = 'Umb.Store.DocumentBlueprint.Detail';
+
+const store: ManifestStore = {
+ type: 'store',
+ alias: UMB_DOCUMENT_BLUEPRINT_DETAIL_STORE_ALIAS,
+ name: 'Document Blueprint Detail Store',
+ api: UmbDocumentBlueprintDetailStore,
+};
+
+export const manifests = [repository, store];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/index.ts
new file mode 100644
index 0000000000..45e331149c
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/index.ts
@@ -0,0 +1,7 @@
+export {
+ UmbDocumentBlueprintDetailRepository,
+ UMB_DOCUMENT_BLUEPRINT_DETAIL_REPOSITORY_ALIAS,
+} from './detail/index.js';
+export { UmbDocumentBlueprintItemRepository, UMB_DOCUMENT_BLUEPRINT_ITEM_REPOSITORY_ALIAS } from './item/index.js';
+
+export type { UmbDocumentBlueprintItemModel } from './item/types.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.repository.ts
new file mode 100644
index 0000000000..36d29289ff
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.repository.ts
@@ -0,0 +1,11 @@
+import { UmbDocumentBlueprintItemServerDataSource } from './document-blueprint-item.server.data-source.js';
+import { UMB_DOCUMENT_BLUEPRINT_ITEM_STORE_CONTEXT } from './document-blueprint-item.store.js';
+import type { UmbDocumentBlueprintItemModel } from './types.js';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { UmbItemRepositoryBase } from '@umbraco-cms/backoffice/repository';
+
+export class UmbDocumentBlueprintItemRepository extends UmbItemRepositoryBase {
+ constructor(host: UmbControllerHost) {
+ super(host, UmbDocumentBlueprintItemServerDataSource, UMB_DOCUMENT_BLUEPRINT_ITEM_STORE_CONTEXT);
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.server.data-source.ts
new file mode 100644
index 0000000000..1e8df1b933
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.server.data-source.ts
@@ -0,0 +1,54 @@
+import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE } from '../../entity.js';
+import type { UmbDocumentBlueprintItemModel } from './types.js';
+import type { DocumentItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
+import { DocumentResource } from '@umbraco-cms/backoffice/external/backend-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository';
+
+/**
+ * A data source for Document Blueprint items that fetches data from the server
+ * @export
+ * @class UmbDocumentBlueprintItemServerDataSource
+ * @implements {DocumentTreeDataSource}
+ */
+export class UmbDocumentBlueprintItemServerDataSource extends UmbItemServerDataSourceBase<
+ DocumentItemResponseModel,
+ UmbDocumentBlueprintItemModel
+> {
+ /**
+ * Creates an instance of UmbDocumentBlueprintItemServerDataSource.
+ * @param {UmbControllerHost} host
+ * @memberof UmbDocumentBlueprintItemServerDataSource
+ */
+ constructor(host: UmbControllerHost) {
+ super(host, {
+ getItems,
+ mapper,
+ });
+ }
+}
+
+/* eslint-disable local-rules/no-direct-api-import */
+const getItems = (uniques: Array) => DocumentResource.getItemDocument({ id: uniques });
+
+const mapper = (item: DocumentItemResponseModel): UmbDocumentBlueprintItemModel => {
+ return {
+ entityType: UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
+ unique: item.id,
+ isTrashed: item.isTrashed,
+ isProtected: item.isProtected,
+ documentType: {
+ unique: item.documentType.id,
+ icon: item.documentType.icon,
+ collection: item.documentType.collection ? { unique: item.documentType.collection.id } : null,
+ },
+ variants: item.variants.map((variant) => {
+ return {
+ culture: variant.culture || null,
+ name: variant.name,
+ state: variant.state,
+ };
+ }),
+ name: item.variants[0]?.name, // TODO: this is not correct. We need to get it from the variants. This is a temp solution.
+ };
+};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.store.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.store.ts
new file mode 100644
index 0000000000..188f50afca
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.store.ts
@@ -0,0 +1,26 @@
+import type { UmbDocumentBlueprintDetailModel } from '../../types.js';
+import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { UmbItemStoreBase } from '@umbraco-cms/backoffice/store';
+
+/**
+ * @export
+ * @class UmbDocumentBlueprintItemStore
+ * @extends {UmbStoreBase}
+ * @description - Data Store for Document items
+ */
+
+export class UmbDocumentBlueprintItemStore extends UmbItemStoreBase {
+ /**
+ * Creates an instance of UmbDocumentBlueprintItemStore.
+ * @param {UmbControllerHost} host
+ * @memberof UmbDocumentBlueprintItemStore
+ */
+ constructor(host: UmbControllerHost) {
+ super(host, UMB_DOCUMENT_BLUEPRINT_ITEM_STORE_CONTEXT.toString());
+ }
+}
+
+export const UMB_DOCUMENT_BLUEPRINT_ITEM_STORE_CONTEXT = new UmbContextToken(
+ 'UmbDocumentBlueprintItemStore',
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/index.ts
new file mode 100644
index 0000000000..6b47360768
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/index.ts
@@ -0,0 +1,2 @@
+export { UmbDocumentBlueprintItemRepository } from './document-blueprint-item.repository.js';
+export { UMB_DOCUMENT_BLUEPRINT_ITEM_REPOSITORY_ALIAS } from './manifests.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/manifests.ts
new file mode 100644
index 0000000000..5674ac938e
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/manifests.ts
@@ -0,0 +1,22 @@
+import { UmbDocumentBlueprintItemStore } from './document-blueprint-item.store.js';
+import { UmbDocumentBlueprintItemRepository } from './document-blueprint-item.repository.js';
+import type { ManifestRepository, ManifestItemStore } from '@umbraco-cms/backoffice/extension-registry';
+
+export const UMB_DOCUMENT_BLUEPRINT_ITEM_REPOSITORY_ALIAS = 'Umb.Repository.DocumentBlueprint.Item';
+export const UMB_DOCUMENT_BLUEPRINT_STORE_ALIAS = 'Umb.Store.DocumentBlueprint.Item';
+
+const itemRepository: ManifestRepository = {
+ type: 'repository',
+ alias: UMB_DOCUMENT_BLUEPRINT_ITEM_REPOSITORY_ALIAS,
+ name: 'Document Blueprint Item Repository',
+ api: UmbDocumentBlueprintItemRepository,
+};
+
+const itemStore: ManifestItemStore = {
+ type: 'itemStore',
+ alias: UMB_DOCUMENT_BLUEPRINT_STORE_ALIAS,
+ name: 'Document Blueprint Item Store',
+ api: UmbDocumentBlueprintItemStore,
+};
+
+export const manifests = [itemRepository, itemStore];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/types.ts
new file mode 100644
index 0000000000..e054aac1d5
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/types.ts
@@ -0,0 +1,23 @@
+import type { UmbDocumentBlueprintEntityType } from '../../entity.js';
+import type { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api';
+import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models';
+
+export interface UmbDocumentBlueprintItemModel {
+ entityType: UmbDocumentBlueprintEntityType;
+ name: string; // TODO: this is not correct. We need to get it from the variants. This is a temp solution.
+ unique: string;
+ isTrashed: boolean;
+ isProtected: boolean;
+ documentType: {
+ unique: string;
+ icon: string;
+ collection: UmbReferenceByUnique | null;
+ };
+ variants: Array;
+}
+
+export interface UmbDocumentBlueprintItemVariantModel {
+ name: string;
+ culture: string | null;
+ state: DocumentVariantStateModel | null;
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/manifests.ts
new file mode 100644
index 0000000000..bb35952020
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/manifests.ts
@@ -0,0 +1,4 @@
+import { manifests as detailManifests } from './detail/manifests.js';
+import { manifests as itemManifests } from './item/manifests.js';
+
+export const manifests = [...detailManifests, ...itemManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts
index 9c69239988..17943b9a89 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts
@@ -50,8 +50,8 @@ const mapper = (item: DocumentBlueprintTreeItemResponseModel): UmbDocumentBluepr
unique: item.id,
parentUnique: item.parent?.id || null,
name: item.name,
- entityType: item.isFolder ? UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE : UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
- isFolder: item.isFolder,
+ entityType: UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
+ isFolder: false,
hasChildren: item.hasChildren,
};
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.store.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.store.ts
index 543f5fa479..5a2d338793 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.store.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.store.ts
@@ -1,4 +1,4 @@
-import { UMB_DOCUMENT_BLUEPRINT_DETAIL_STORE_CONTEXT } from '../repository/index.js';
+import { UMB_DOCUMENT_BLUEPRINT_DETAIL_STORE_CONTEXT } from '../repository/detail/index.js';
import type { UmbDocumentBlueprintDetailModel } from '../types.js';
import type { UmbDocumentBlueprintTreeItemModel } from './types.js';
import { UmbUniqueTreeStore } from '@umbraco-cms/backoffice/tree';
@@ -29,9 +29,7 @@ export class UmbDocumentBlueprintTreeStore extends UmbUniqueTreeStore {
}
#updateTreeItemMapper = (item: UmbDocumentBlueprintDetailModel) => {
- return {
- name: item.name,
- };
+ return { ...item, name: item.variants.map((variant) => variant.name)[0] };
};
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts
new file mode 100644
index 0000000000..6cbcb6199b
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts
@@ -0,0 +1,39 @@
+import type { UmbDocumentBlueprintEntityType } from './entity.js';
+import type { UmbVariantModel, UmbVariantOptionModel } from '@umbraco-cms/backoffice/variant';
+import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models';
+import { DocumentVariantStateModel as UmbDocumentBlueprintVariantState } from '@umbraco-cms/backoffice/external/backend-api';
+export { UmbDocumentBlueprintVariantState };
+
+export interface UmbDocumentBlueprintDetailModel {
+ documentType: {
+ unique: string;
+ collection: UmbReferenceByUnique | null;
+ };
+ entityType: UmbDocumentBlueprintEntityType;
+ isTrashed: boolean;
+ template: { unique: string } | null;
+ unique: string;
+ urls: Array;
+ values: Array;
+ variants: Array;
+}
+
+export interface UmbDocumentBlueprintVariantModel extends UmbVariantModel {
+ state: UmbDocumentBlueprintVariantState | null;
+ publishDate: string | null;
+}
+
+export interface UmbDocumentBlueprintUrlInfoModel {
+ culture: string | null;
+ url: string;
+}
+
+export interface UmbDocumentBlueprintValueModel {
+ culture: string | null;
+ segment: string | null;
+ alias: string;
+ value: ValueType;
+}
+
+export interface UmbDocumentBlueprintVariantOptionModel
+ extends UmbVariantOptionModel {}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts
index 08702a94e8..9d79e676fe 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts
@@ -1,5 +1,6 @@
import { UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE } from '../entity.js';
-import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry';
+import { UmbSaveWorkspaceAction } from '@umbraco-cms/backoffice/workspace';
+import type { ManifestWorkspace, ManifestWorkspaceActions } from '@umbraco-cms/backoffice/extension-registry';
export const UMB_DOCUMENT_BLUEPRINT_ROOT_WORKSPACE_ALIAS = 'Umb.Workspace.DocumentBlueprint.Root';
@@ -13,4 +14,26 @@ const workspace: ManifestWorkspace = {
},
};
-export const manifests = [workspace];
+const workspaceActions: Array = [
+ {
+ type: 'workspaceAction',
+ kind: 'default',
+ alias: 'Umb.WorkspaceAction.DocumentBlueprint.Save',
+ name: 'Save Document Workspace Action',
+ weight: 80,
+ api: UmbSaveWorkspaceAction,
+ meta: {
+ label: 'Save',
+ look: 'secondary',
+ color: 'positive',
+ },
+ conditions: [
+ {
+ alias: 'Umb.Condition.WorkspaceAlias',
+ match: workspace.alias,
+ },
+ ],
+ },
+];
+
+export const manifests = [workspace, ...workspaceActions];
From d0e6ed5adb2bc7735da7ac5327ae0ed0c0bcb677 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Wed, 13 Mar 2024 12:37:43 +0100
Subject: [PATCH 006/280] hack
---
.../document-blueprint-tree.server.data-source.ts | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts
index 17943b9a89..d7b30c8318 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts
@@ -2,7 +2,10 @@ import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE, UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTIT
import type { UmbDocumentBlueprintTreeItemModel } from './types.js';
import type { UmbTreeChildrenOfRequestArgs, UmbTreeRootItemsRequestArgs } from '@umbraco-cms/backoffice/tree';
import { UmbTreeServerDataSourceBase } from '@umbraco-cms/backoffice/tree';
-import type { DocumentBlueprintTreeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
+import type {
+ DocumentBlueprintTreeItemResponseModel,
+ DocumentTreeItemResponseModel,
+} from '@umbraco-cms/backoffice/external/backend-api';
import { DocumentBlueprintResource } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
@@ -38,18 +41,23 @@ const getChildrenOf = (args: UmbTreeChildrenOfRequestArgs) => {
if (args.parentUnique === null) {
return getRootItems(args);
} else {
+ throw new Error('Not implemented');
+ /*
// eslint-disable-next-line local-rules/no-direct-api-import
return DocumentBlueprintResource.getTreeDocumentBlueprintChildren({
parentId: args.parentUnique,
});
+ */
}
};
const mapper = (item: DocumentBlueprintTreeItemResponseModel): UmbDocumentBlueprintTreeItemModel => {
+ //TODO remove temp hack when api endpoints are fixed
+ const hack = item as Partial;
return {
unique: item.id,
parentUnique: item.parent?.id || null,
- name: item.name,
+ name: hack?.variants?.[0].name ?? '',
entityType: UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
isFolder: false,
hasChildren: item.hasChildren,
From 11148ebe394cb3dfe71399b58aaba3ff60d29bf6 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Wed, 13 Mar 2024 15:22:18 +0100
Subject: [PATCH 007/280] workspaces
---
.../documents/document-blueprints/index.ts | 6 +
.../document-blueprints/manifests.ts | 16 +-
.../menu-item/manifests.ts | 3 +-
...ment-blueprint-workspace-editor.element.ts | 130 +++++
...-blueprint-workspace-split-view.element.ts | 87 +++
...ument-blueprint-workspace.context-token.ts | 14 +
.../document-blueprint-workspace.context.ts | 503 ++++++++++++++++++
.../document-blueprint-workspace.element.ts | 87 +++
.../document-blueprints/workspace/index.ts | 1 +
.../workspace/manifests.ts | 2 +-
10 files changed, 843 insertions(+), 6 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-split-view.element.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context-token.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.element.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/index.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/index.ts
index dab908bbad..188be00f10 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/index.ts
@@ -1 +1,7 @@
export * from './entity.js';
+
+export * from './workspace/index.js';
+
+export * from './repository/index.js';
+export * from './tree/types.js';
+export * from './types.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/manifests.ts
index 74655fc3d7..7cfe9c73e2 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/manifests.ts
@@ -1,6 +1,14 @@
-import { manifests as menuItemManifests } from './menu-item/manifests.js';
-import { manifests as workspaceManifests } from './workspace/manifests.js';
import { manifests as entityActionManifests } from './entity-actions/manifests.js';
-import { manifests as treeManifests } from './tree/manifests.js';
+import { manifests as menuItemManifests } from './menu-item/manifests.js';
-export const manifests = [...menuItemManifests, ...workspaceManifests, ...entityActionManifests, ...treeManifests];
+import { manifests as repositoryManifests } from './repository/manifests.js';
+import { manifests as treeManifests } from './tree/manifests.js';
+import { manifests as workspaceManifests } from './workspace/manifests.js';
+
+export const manifests = [
+ ...entityActionManifests,
+ ...menuItemManifests,
+ ...repositoryManifests,
+ ...treeManifests,
+ ...workspaceManifests,
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts
index a7547172ba..cbddb145af 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts
@@ -1,3 +1,4 @@
+import { UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE } from '../entity.js';
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
const menuItem: ManifestTypes = {
@@ -10,7 +11,7 @@ const menuItem: ManifestTypes = {
treeAlias: 'Umb.Tree.DocumentBlueprint',
label: 'Document Blueprints',
icon: 'icon-blueprint',
- entityType: 'document-blueprint-root',
+ entityType: UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
menus: ['Umb.Menu.Settings'],
},
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts
new file mode 100644
index 0000000000..7b17e80df5
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts
@@ -0,0 +1,130 @@
+import type { UmbDocumentBlueprintVariantOptionModel } from '../types.js';
+import { UmbDocumentBlueprintWorkspaceSplitViewElement } from './document-blueprint-workspace-split-view.element.js';
+import { UMB_DOCUMENT_BLUEPRINT_WORKSPACE_CONTEXT } from './document-blueprint-workspace.context-token.js';
+import { customElement, state, css, html } from '@umbraco-cms/backoffice/external/lit';
+import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
+import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
+import type { UmbRoute, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router';
+
+// TODO: This seem fully identical with Media Workspace Editor, so we can refactor this to a generic component. [NL]
+@customElement('umb-document-blueprint-workspace-editor')
+export class UmbDocumentBlueprintWorkspaceEditorElement extends UmbLitElement {
+ //
+ // TODO: Refactor: when having a split view/variants context token, we can rename the split view/variants component to a generic and make this component generic as well. [NL]
+ private splitViewElement = new UmbDocumentBlueprintWorkspaceSplitViewElement();
+
+ #workspaceContext?: typeof UMB_DOCUMENT_BLUEPRINT_WORKSPACE_CONTEXT.TYPE;
+
+ @state()
+ _routes?: Array;
+
+ constructor() {
+ super();
+
+ this.consumeContext(UMB_DOCUMENT_BLUEPRINT_WORKSPACE_CONTEXT, (instance) => {
+ this.#workspaceContext = instance;
+ this.#observeVariants();
+ });
+ }
+
+ #observeVariants() {
+ if (!this.#workspaceContext) return;
+ // TODO: the variantOptions observable is like too broad as this will be triggered then there is any change in the variant options, we need to only update routes when there is a relevant change to them. [NL]
+ this.observe(this.#workspaceContext.variantOptions, (options) => this._generateRoutes(options), '_observeVariants');
+ }
+
+ private _handleVariantFolderPart(index: number, folderPart: string) {
+ const variantSplit = folderPart.split('_');
+ const culture = variantSplit[0];
+ const segment = variantSplit[1];
+ this.#workspaceContext?.splitView.setActiveVariant(index, culture, segment);
+ }
+
+ private async _generateRoutes(options: Array) {
+ if (!options || options.length === 0) return;
+
+ // Generate split view routes for all available routes
+ const routes: Array = [];
+
+ // Split view routes:
+ options.forEach((variantA) => {
+ options.forEach((variantB) => {
+ routes.push({
+ // TODO: When implementing Segments, be aware if using the unique is URL Safe... [NL]
+ path: variantA.unique + '_&_' + variantB.unique,
+ component: this.splitViewElement,
+ setup: (_component, info) => {
+ // Set split view/active info..
+ const variantSplit = info.match.fragments.consumed.split('_&_');
+ variantSplit.forEach((part, index) => {
+ this._handleVariantFolderPart(index, part);
+ });
+ },
+ });
+ });
+ });
+
+ // Single view:
+ options.forEach((variant) => {
+ routes.push({
+ // TODO: When implementing Segments, be aware if using the unique is URL Safe... [NL]
+ path: variant.unique,
+ component: this.splitViewElement,
+ setup: (_component, info) => {
+ // cause we might come from a split-view, we need to reset index 1.
+ this.#workspaceContext?.splitView.removeActiveVariant(1);
+ this._handleVariantFolderPart(0, info.match.fragments.consumed);
+ },
+ });
+ });
+
+ if (routes.length !== 0) {
+ // Using first single view as the default route for now (hence the math below):
+ routes.push({
+ path: '',
+ redirectTo: routes[options.length * options.length]?.path,
+ });
+ }
+
+ const oldValue = this._routes;
+
+ // is there any differences in the amount ot the paths? [NL]
+ // TODO: if we make a memorization function as the observer, we can avoid this check and avoid the whole build of routes. [NL]
+ if (oldValue && oldValue.length === routes.length) {
+ // is there any differences in the paths? [NL]
+ const hasDifferences = oldValue.some((route, index) => route.path !== routes[index].path);
+ if (!hasDifferences) return;
+ }
+ this._routes = routes;
+ this.requestUpdate('_routes', oldValue);
+ }
+
+ private _gotWorkspaceRoute = (e: UmbRouterSlotInitEvent) => {
+ this.#workspaceContext?.splitView.setWorkspaceRoute(e.target.absoluteRouterPath);
+ };
+
+ render() {
+ return this._routes && this._routes.length > 0
+ ? html` `
+ : '';
+ }
+
+ static styles = [
+ UmbTextStyles,
+ css`
+ :host {
+ display: block;
+ width: 100%;
+ height: 100%;
+ }
+ `,
+ ];
+}
+
+export default UmbDocumentBlueprintWorkspaceEditorElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-document-blueprint-workspace-editor': UmbDocumentBlueprintWorkspaceEditorElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-split-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-split-view.element.ts
new file mode 100644
index 0000000000..533e7c36ed
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-split-view.element.ts
@@ -0,0 +1,87 @@
+import { UMB_DOCUMENT_BLUEPRINT_WORKSPACE_CONTEXT } from './document-blueprint-workspace.context-token.js';
+import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
+import { css, html, nothing, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit';
+import type { ActiveVariant } from '@umbraco-cms/backoffice/workspace';
+import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
+
+@customElement('umb-document-blueprint-workspace-split-view')
+export class UmbDocumentBlueprintWorkspaceSplitViewElement extends UmbLitElement {
+ // TODO: Refactor: use the split view context token:
+ private _workspaceContext?: typeof UMB_DOCUMENT_BLUEPRINT_WORKSPACE_CONTEXT.TYPE;
+
+ @state()
+ _variants?: Array;
+
+ constructor() {
+ super();
+
+ // TODO: Refactor: use a split view workspace context token:
+ this.consumeContext(UMB_DOCUMENT_BLUEPRINT_WORKSPACE_CONTEXT, (context) => {
+ this._workspaceContext = context;
+ this._observeActiveVariantInfo();
+ });
+ }
+
+ private _observeActiveVariantInfo() {
+ if (!this._workspaceContext) return;
+ this.observe(
+ this._workspaceContext.splitView.activeVariantsInfo,
+ (variants) => {
+ this._variants = variants;
+ },
+ '_observeActiveVariantsInfo',
+ );
+ }
+
+ render() {
+ return this._variants
+ ? html`
+ ${repeat(
+ this._variants,
+ (view) =>
+ view.index + '_' + (view.culture ?? '') + '_' + (view.segment ?? '') + '_' + this._variants!.length,
+ (view) => html`
+
+ `,
+ )}
+
+
+ `
+ : nothing;
+ }
+
+ static styles = [
+ UmbTextStyles,
+ css`
+ :host {
+ width: 100%;
+ height: 100%;
+
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ }
+
+ #splitViews {
+ display: flex;
+ width: 100%;
+ height: calc(100% - var(--umb-footer-layout-height));
+ }
+
+ #breadcrumbs {
+ margin: 0 var(--uui-size-layout-1);
+ }
+ `,
+ ];
+}
+
+export default UmbDocumentBlueprintWorkspaceSplitViewElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-document-blueprint-workspace-split-view': UmbDocumentBlueprintWorkspaceSplitViewElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context-token.ts
new file mode 100644
index 0000000000..0bf889c505
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context-token.ts
@@ -0,0 +1,14 @@
+import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE } from '../entity.js';
+import type { UmbDocumentBlueprintWorkspaceContext } from './document-blueprint-workspace.context.js';
+import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
+import type { UmbSaveableWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
+
+export const UMB_DOCUMENT_BLUEPRINT_WORKSPACE_CONTEXT = new UmbContextToken<
+ UmbSaveableWorkspaceContextInterface,
+ UmbDocumentBlueprintWorkspaceContext
+>(
+ 'UmbWorkspaceBlueprintContext',
+ undefined,
+ (context): context is UmbDocumentBlueprintWorkspaceContext =>
+ context.getEntityType?.() === UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts
new file mode 100644
index 0000000000..a0279b8906
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts
@@ -0,0 +1,503 @@
+import { UmbDocumentPropertyDataContext } from '../../documents/property-dataset-context/document-property-dataset-context.js';
+import { UmbDocumentTypeDetailRepository } from '../../document-types/repository/detail/document-type-detail.repository.js';
+import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE } from '../entity.js';
+import { UmbDocumentBlueprintDetailRepository } from '../repository/index.js';
+import type {
+ UmbDocumentBlueprintDetailModel,
+ UmbDocumentBlueprintValueModel,
+ UmbDocumentBlueprintVariantModel,
+ UmbDocumentBlueprintVariantOptionModel,
+} from '../types.js';
+//import { umbPickDocumentVariantModal, type UmbDocumentBlueprintVariantPickerModalType } from '../modals/index.js';
+import { UMB_DOCUMENT_BLUEPRINT_ROOT_WORKSPACE_ALIAS } from './manifests.js';
+import { UMB_INVARIANT_CULTURE, UmbVariantId } from '@umbraco-cms/backoffice/variant';
+import { UmbContentTypePropertyStructureManager } from '@umbraco-cms/backoffice/content-type';
+import {
+ UmbEditableWorkspaceContextBase,
+ UmbWorkspaceSplitViewManager,
+ type UmbVariantableWorkspaceContextInterface,
+} from '@umbraco-cms/backoffice/workspace';
+import {
+ appendToFrozenArray,
+ mergeObservables,
+ jsonStringComparison,
+ UmbArrayState,
+ UmbObjectState,
+} from '@umbraco-cms/backoffice/observable-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { UmbLanguageCollectionRepository, type UmbLanguageDetailModel } from '@umbraco-cms/backoffice/language';
+import { type Observable, firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs';
+import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
+import { UmbReloadTreeItemChildrenRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree';
+import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/event';
+
+type EntityType = UmbDocumentBlueprintDetailModel;
+export class UmbDocumentBlueprintWorkspaceContext
+ extends UmbEditableWorkspaceContextBase
+ implements UmbVariantableWorkspaceContextInterface
+{
+ //
+ public readonly repository = new UmbDocumentBlueprintDetailRepository(this);
+
+ #parent?: { entityType: string; unique: string | null };
+
+ /**
+ * The document is the current state/draft version of the document.
+ */
+ #persistedData = new UmbObjectState(undefined);
+ #currentData = new UmbObjectState(undefined);
+ #getDataPromise?: Promise;
+ // TODo: Optimize this so it uses either a App Language Context? [NL]
+ #languageRepository = new UmbLanguageCollectionRepository(this);
+ #languages = new UmbArrayState([], (x) => x.unique);
+ public readonly languages = this.#languages.asObservable();
+
+ public isLoaded() {
+ return this.#getDataPromise;
+ }
+
+ readonly unique = this.#currentData.asObservablePart((data) => data?.unique);
+
+ readonly contentTypeUnique = this.#currentData.asObservablePart((data) => data?.documentType.unique);
+ readonly contentTypeHasCollection = this.#currentData.asObservablePart((data) => !!data?.documentType.collection);
+ readonly variants = this.#currentData.asObservablePart((data) => data?.variants ?? []);
+
+ readonly urls = this.#currentData.asObservablePart((data) => data?.urls || []);
+ readonly templateId = this.#currentData.asObservablePart((data) => data?.template?.unique || null);
+
+ readonly structure = new UmbContentTypePropertyStructureManager(this, new UmbDocumentTypeDetailRepository(this));
+ readonly variesByCulture = this.structure.ownerContentTypePart((x) => x?.variesByCulture);
+ //#variesByCulture?: boolean;
+ readonly variesBySegment = this.structure.ownerContentTypePart((x) => x?.variesBySegment);
+ //#variesBySegment?: boolean;
+ readonly varies = this.structure.ownerContentTypePart((x) =>
+ x ? x.variesByCulture || x.variesBySegment : undefined,
+ );
+ #varies?: boolean;
+
+ readonly splitView = new UmbWorkspaceSplitViewManager();
+
+ readonly variantOptions = mergeObservables(
+ [this.varies, this.variants, this.languages],
+ ([varies, variants, languages]) => {
+ // TODO: When including segments, when be aware about the case of segment varying when not culture varying. [NL]
+ if (varies === true) {
+ return languages.map((language) => {
+ return {
+ variant: variants.find((x) => x.culture === language.unique),
+ language,
+ // TODO: When including segments, this object should be updated to include a object for the segment. [NL]
+ // TODO: When including segments, the unique should be updated to include the segment as well. [NL]
+ unique: language.unique, // This must be a variantId string!
+ culture: language.unique,
+ segment: null,
+ } as UmbDocumentBlueprintVariantOptionModel;
+ });
+ } else if (varies === false) {
+ return [
+ {
+ variant: variants.find((x) => x.culture === null),
+ language: languages.find((x) => x.isDefault),
+ culture: null,
+ segment: null,
+ unique: UMB_INVARIANT_CULTURE, // This must be a variantId string!
+ } as UmbDocumentBlueprintVariantOptionModel,
+ ];
+ }
+ return [] as Array;
+ },
+ );
+
+ constructor(host: UmbControllerHost) {
+ super(host, UMB_DOCUMENT_BLUEPRINT_ROOT_WORKSPACE_ALIAS);
+
+ this.observe(this.contentTypeUnique, (unique) => this.structure.loadType(unique));
+ this.observe(this.varies, (varies) => (this.#varies = varies));
+
+ this.loadLanguages();
+ }
+
+ resetState() {
+ super.resetState();
+ this.#persistedData.setValue(undefined);
+ this.#currentData.setValue(undefined);
+ }
+
+ async loadLanguages() {
+ // TODO: If we don't end up having a Global Context for languages, then we should at least change this into using a asObservable which should be returned from the repository. [Nl]
+ const { data } = await this.#languageRepository.requestCollection({});
+ this.#languages.setValue(data?.items ?? []);
+ }
+
+ async load(unique: string) {
+ console.log('load');
+ this.resetState();
+ this.#getDataPromise = this.repository.requestByUnique(unique);
+ const { data } = await this.#getDataPromise;
+ if (!data) return undefined;
+
+ this.setIsNew(false);
+ this.#persistedData.setValue(data);
+ this.#currentData.setValue(data);
+ return data || undefined;
+ }
+
+ async create(parent: { entityType: string; unique: string | null }, documentTypeUnique: string) {
+ this.resetState();
+ this.#parent = parent;
+ this.#getDataPromise = this.repository.createScaffold({
+ documentType: {
+ unique: documentTypeUnique,
+ collection: null,
+ },
+ });
+ const { data } = await this.#getDataPromise;
+ if (!data) return undefined;
+
+ this.setIsNew(true);
+ this.#persistedData.setValue(undefined);
+ this.#currentData.setValue(data);
+ return data;
+ }
+
+ getData() {
+ return this.#currentData.getValue();
+ }
+
+ getUnique() {
+ return this.getData()?.unique;
+ }
+
+ getEntityType() {
+ return UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE;
+ }
+
+ getContentTypeId() {
+ return this.getData()?.documentType.unique;
+ }
+
+ // TODO: Check if this is used:
+ getVaries() {
+ return this.#varies;
+ }
+ /*
+ getVariesByCulture() {
+ return this.#variesByCulture;
+ }
+ getVariesBySegment() {
+ return this.#variesBySegment;
+ }*/
+
+ variantById(variantId: UmbVariantId) {
+ return this.#currentData.asObservablePart((data) => data?.variants?.find((x) => variantId.compare(x)));
+ }
+
+ getVariant(variantId: UmbVariantId) {
+ return this.#currentData.getValue()?.variants?.find((x) => variantId.compare(x));
+ }
+
+ getName(variantId?: UmbVariantId) {
+ const variants = this.#currentData.getValue()?.variants;
+ if (!variants) return;
+ if (variantId) {
+ return variants.find((x) => variantId.compare(x))?.name;
+ } else {
+ return variants[0]?.name;
+ }
+ }
+
+ setName(name: string, variantId?: UmbVariantId) {
+ /*
+ const oldVariants = this.#currentData.getValue()?.variants || [];
+ const variants = partialUpdateFrozenArray(
+ oldVariants,
+ { name },
+ variantId ? (x) => variantId.compare(x) : () => true,
+ );
+ this.#currentData.update({ variants });
+ */
+ // TODO: We should move this type of logic to the act of saving [NL]
+ this.#updateVariantData(variantId ?? UmbVariantId.CreateInvariant(), { name });
+ }
+
+ setTemplate(templateUnique: string) {
+ this.#currentData.update({ template: { unique: templateUnique } });
+ }
+
+ async propertyStructureById(propertyId: string) {
+ return this.structure.propertyStructureById(propertyId);
+ }
+
+ async propertyValueByAlias(
+ propertyAlias: string,
+ variantId?: UmbVariantId,
+ ): Promise | undefined> {
+ return this.#currentData.asObservablePart(
+ (data) =>
+ data?.values?.find((x) => x?.alias === propertyAlias && (variantId ? variantId.compare(x) : true))
+ ?.value as PropertyValueType,
+ );
+ }
+
+ /**
+ * Get the current value of the property with the given alias and variantId.
+ * @param alias
+ * @param variantId
+ * @returns The value or undefined if not set or found.
+ */
+ getPropertyValue(alias: string, variantId?: UmbVariantId) {
+ const currentData = this.getData();
+ if (currentData) {
+ const newDataSet = currentData.values?.find(
+ (x) => x.alias === alias && (variantId ? variantId.compare(x) : true),
+ );
+ return newDataSet?.value as ReturnType;
+ }
+ return undefined;
+ }
+ async setPropertyValue(alias: string, value: ValueType, variantId?: UmbVariantId) {
+ variantId ??= UmbVariantId.CreateInvariant();
+
+ const entry = { ...variantId.toObject(), alias, value } as UmbDocumentBlueprintValueModel;
+ const currentData = this.getData();
+ if (currentData) {
+ const values = appendToFrozenArray(
+ currentData.values ?? [],
+ entry,
+ (x) => x.alias === alias && variantId!.compare(x),
+ );
+ this.#currentData.update({ values });
+
+ // TODO: We should move this type of logic to the act of saving [NL]
+ this.#updateVariantData(variantId);
+ }
+ }
+
+ #calculateChangedVariants() {
+ const persisted = this.#persistedData.getValue();
+ const current = this.#currentData.getValue();
+ if (!current) throw new Error('Current data is missing');
+
+ const changedVariants = current?.variants.map((variant) => {
+ const persistedVariant = persisted?.variants.find((x) => UmbVariantId.Create(variant).compare(x));
+ return {
+ culture: variant.culture,
+ segment: variant.segment,
+ equal: persistedVariant ? jsonStringComparison(variant, persistedVariant) : false,
+ };
+ });
+
+ const changedProperties = current?.values.map((value) => {
+ const persistedValues = persisted?.values.find((x) => UmbVariantId.Create(value).compare(x));
+ return {
+ culture: value.culture,
+ segment: value.segment,
+ equal: persistedValues ? jsonStringComparison(value, persistedValues) : false,
+ };
+ });
+
+ // calculate the variantIds of those who either have a change in properties or in variants:
+ return (
+ changedVariants
+ ?.concat(changedProperties ?? [])
+ .filter((x) => x.equal === false)
+ .map((x) => new UmbVariantId(x.culture, x.segment)) ?? []
+ );
+ }
+
+ #updateVariantData(variantId: UmbVariantId, update?: Partial) {
+ const currentData = this.getData();
+ if (!currentData) throw new Error('Data is missing');
+ if (this.#varies === true) {
+ // If variant Id is invariant, we don't to have the variant appended to our data.
+ if (variantId.isInvariant()) return;
+ const variant = currentData.variants.find((x) => variantId.compare(x));
+ const newVariants = appendToFrozenArray(
+ currentData.variants,
+ {
+ state: null,
+ name: '',
+ publishDate: null,
+ createDate: null,
+ updateDate: null,
+ ...variantId.toObject(),
+ ...variant,
+ ...update,
+ },
+ (x) => variantId.compare(x),
+ );
+ this.#currentData.update({ variants: newVariants });
+ } else if (this.#varies === false) {
+ // TODO: Beware about segments, in this case we need to also consider segments, if its allowed to vary by segments.
+ const invariantVariantId = UmbVariantId.CreateInvariant();
+ const variant = currentData.variants.find((x) => invariantVariantId.compare(x));
+ // Cause we are invariant, we will just overwrite all variants with this one:
+ const newVariants = [
+ {
+ state: null,
+ name: '',
+ publishDate: null,
+ createDate: null,
+ updateDate: null,
+ ...invariantVariantId.toObject(),
+ ...variant,
+ ...update,
+ },
+ ];
+ this.#currentData.update({ variants: newVariants });
+ } else {
+ throw new Error('Varies by culture is missing');
+ }
+ }
+ /*
+ async #runUserFlorFor(type: UmbDocumentBlueprintVariantPickerModalType): Promise {
+ const activeVariants = this.splitView.getActiveVariants();
+
+ const activeVariantIds = activeVariants.map((activeVariant) => UmbVariantId.Create(activeVariant));
+ // TODO: We need to filter the selected array, so it only contains one of each variantId. [NL]
+ const changedVariantIds = this.#calculateChangedVariants();
+ const selected = activeVariantIds.concat(changedVariantIds);
+ // Selected can contain entries that are not part of the options, therefor the modal filters selection based on options.
+
+ const options = await firstValueFrom(this.variantOptions);
+
+ // If there is only one variant, we don't need to open the modal.
+ if (options.length === 0) {
+ throw new Error('No variants are available');
+ } else if (options.length === 1) {
+ // If only one option we will skip ahead and save the document with the only variant available:
+ const firstVariant = UmbVariantId.Create(options[0]);
+ return this.#performSaveOrCreate([firstVariant]);
+ }
+
+ const selectedVariants = await umbPickDocumentVariantModal(this, { type, options, selected });
+
+ // If no variants are selected, we don't save anything.
+ if (!selectedVariants.length) return [];
+
+ return this.#performSaveOrCreate(selectedVariants);
+ }
+ */
+
+ #buildSaveData(selectedVariants: Array): UmbDocumentBlueprintDetailModel {
+ const data = this.getData();
+ if (!data) throw new Error('Data is missing');
+ if (!data.unique) throw new Error('Unique is missing');
+ const invariantVariantId = UmbVariantId.CreateInvariant();
+ if (this.#varies === false) {
+ // If we do not vary, we wil just do this for the invariant variant id.
+ selectedVariants = [invariantVariantId];
+ }
+
+ const persistedData = this.#persistedData.getValue();
+
+ const variantIdsToParseForValues = [...selectedVariants];
+ if (this.#varies === true) {
+ // If we vary then We need to include the invariant variant id for invariant values to be saved, as we always want to save the invariant values.
+ variantIdsToParseForValues.push(invariantVariantId);
+ }
+
+ // Combine data and persisted data depending on the selectedVariants. Always use the invariant values from the data.
+ // loops over each entry in values, determine wether the value should be from the data or the persisted data, depending on wether its a selectedVariant or an invariant value.
+ // loops over each entry in variants, determine wether the variant should be from the data or the persisted data, depending on the selectedVariants.
+ return {
+ ...data,
+ values: data.values
+ .map((value) => {
+ // Should this value be saved?
+ if (variantIdsToParseForValues.some((x) => x.compare(value))) {
+ return value;
+ } else {
+ // If not we will find the value in the persisted data and use that instead.
+ return persistedData?.values.find(
+ (x) => x.alias === value.alias && x.culture === value.culture && x.segment === value.segment,
+ );
+ }
+ })
+ .filter((x) => x !== undefined) as Array>,
+ variants: data.variants
+ .map((variant) => {
+ // Should this value be saved?
+ if (selectedVariants.some((x) => x.compare(variant))) {
+ return variant;
+ } else {
+ // If not we will find the value in the persisted data and use that instead.
+ return persistedData?.variants.find((x) => x.culture === variant.culture && x.segment === variant.segment);
+ }
+ })
+ .filter((x) => x !== undefined) as Array,
+ };
+ }
+
+ async #performSaveOrCreate(selectedVariants: Array) {
+ const saveData = this.#buildSaveData(selectedVariants);
+
+ if (this.getIsNew()) {
+ if (!this.#parent) throw new Error('Parent is not set');
+
+ const { data: create, error } = await this.repository.create(saveData, this.#parent.unique);
+ if (!create || error) {
+ console.error('Error creating document', error);
+ throw new Error('Error creating document');
+ }
+
+ this.setIsNew(false);
+
+ // TODO: this might not be the right place to alert the tree, but it works for now
+ const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT);
+ const event = new UmbReloadTreeItemChildrenRequestEntityActionEvent({
+ entityType: this.#parent.entityType,
+ unique: this.#parent.unique,
+ });
+ eventContext.dispatchEvent(event);
+ } else {
+ const { data: save, error } = await this.repository.save(saveData);
+ if (!save || error) {
+ console.error('Error saving document', error);
+ throw new Error('Error saving document');
+ }
+
+ const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT);
+ const event = new UmbRequestReloadStructureForEntityEvent({
+ unique: this.getUnique()!,
+ entityType: this.getEntityType(),
+ });
+
+ actionEventContext.dispatchEvent(event);
+ }
+
+ return selectedVariants;
+ }
+
+ async save() {
+ //await this.#runUserFlorFor('save');
+ const data = this.getData();
+ if (!data) throw new Error('Data is missing');
+
+ this.#persistedData.setValue(data);
+ this.#currentData.setValue(data);
+
+ this.workspaceComplete(data);
+ }
+
+ async delete() {
+ const id = this.getUnique();
+ if (id) {
+ await this.repository.delete(id);
+ }
+ }
+
+ public createPropertyDatasetContext(host: UmbControllerHost, variantId: UmbVariantId) {
+ return new UmbDocumentPropertyDataContext(host, this as any, variantId);
+ }
+
+ public destroy(): void {
+ this.#persistedData.destroy();
+ this.#currentData.destroy();
+ this.structure.destroy();
+ this.#languageRepository.destroy();
+ super.destroy();
+ }
+}
+
+export default UmbDocumentBlueprintWorkspaceContext;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.element.ts
new file mode 100644
index 0000000000..495489dfe9
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.element.ts
@@ -0,0 +1,87 @@
+import type { UmbDocumentBlueprintWorkspaceContext } from './document-blueprint-workspace.context.js';
+import { UmbDocumentBlueprintWorkspaceEditorElement } from './document-blueprint-workspace-editor.element.js';
+import { UmbDocumentBlueprintRootWorkspaceElement } from './document-blueprint-root-workspace.element.js';
+import { html, customElement, css, state } from '@umbraco-cms/backoffice/external/lit';
+import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
+import { type UmbApi, createExtensionApi, UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api';
+import { umbExtensionsRegistry, type ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry';
+
+import type { UmbRoute } from '@umbraco-cms/backoffice/router';
+import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/workspace';
+
+@customElement('umb-document-blueprint-workspace')
+export class UmbDocumentBlueprintWorkspaceElement extends UmbLitElement {
+ #workspaceContext?: UmbDocumentBlueprintWorkspaceContext;
+ #editorElement = () => new UmbDocumentBlueprintWorkspaceEditorElement();
+ #rootElement = () => new UmbDocumentBlueprintRootWorkspaceElement();
+
+ @state()
+ _routes: UmbRoute[] = [];
+
+ public set manifest(manifest: ManifestWorkspace) {
+ createExtensionApi(this, manifest).then((context) => {
+ if (context) {
+ this.#gotWorkspaceContext(context);
+ }
+ });
+ }
+
+ #gotWorkspaceContext(context: UmbApi) {
+ this.#workspaceContext = context as UmbDocumentBlueprintWorkspaceContext;
+
+ this._routes = [
+ {
+ path: 'create/parent/:entityType/:parentUnique/:documentTypeUnique',
+ component: this.#editorElement,
+ setup: async (_component, info) => {
+ // TODO: Remember the perspective of permissions here, we need to check if the user has access to create a document of this type under this parent?
+ const parentEntityType = info.match.params.entityType;
+ const parentUnique = info.match.params.parentUnique === 'null' ? null : info.match.params.parentUnique;
+ const documentTypeUnique = info.match.params.documentTypeUnique;
+ this.#workspaceContext!.create({ entityType: parentEntityType, unique: parentUnique }, documentTypeUnique);
+
+ new UmbWorkspaceIsNewRedirectController(
+ this,
+ this.#workspaceContext!,
+ this.shadowRoot!.querySelector('umb-router-slot')!,
+ );
+ },
+ },
+ {
+ path: 'edit/null',
+ component: this.#rootElement,
+ },
+ {
+ path: 'edit/:unique',
+ component: this.#editorElement,
+ setup: (_component, info) => {
+ const unique = info.match.params.unique;
+ this.#workspaceContext!.load(unique);
+ },
+ },
+ ];
+
+ // TODO: We need to recreate when ID changed?
+ new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'workspaceContext', [this, this.#workspaceContext]);
+ }
+
+ render() {
+ return html` `;
+ }
+
+ static styles = [
+ css`
+ #wrapper {
+ margin: var(--uui-size-layout-1);
+ }
+ `,
+ ];
+}
+
+export default UmbDocumentBlueprintWorkspaceElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-document-blueprint-workspace': UmbDocumentBlueprintWorkspaceElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/index.ts
new file mode 100644
index 0000000000..22a5c8eeab
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/index.ts
@@ -0,0 +1 @@
+export * from './document-blueprint-workspace.context-token.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts
index 9d79e676fe..a93f324175 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts
@@ -8,7 +8,7 @@ const workspace: ManifestWorkspace = {
type: 'workspace',
alias: UMB_DOCUMENT_BLUEPRINT_ROOT_WORKSPACE_ALIAS,
name: 'Document Blueprint Root Workspace',
- element: () => import('./document-blueprint-root-workspace.element.js'),
+ js: () => import('./document-blueprint-workspace.element.js'),
meta: {
entityType: UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
},
From f5287d499702ed48712ee9d2efcc65e20aea9238 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Mon, 18 Mar 2024 11:21:18 +0100
Subject: [PATCH 008/280] comment-out folder repos for now
---
.../entity-actions/manifests.ts | 15 +-
.../menu-item/manifests.ts | 6 +-
.../document-blueprint-folder.repository.ts | 16 +-
...ent-blueprint-folder.server.data-source.ts | 210 +++++++++---------
.../document-blueprints/tree/folder/index.ts | 4 +-
.../tree/folder/manifests.ts | 66 +++---
.../document-blueprints/tree/folder/types.ts | 10 +-
.../document-blueprints/tree/index.ts | 2 +-
.../document-blueprints/tree/manifests.ts | 8 +-
.../document-blueprint-workspace.element.ts | 2 +
10 files changed, 168 insertions(+), 171 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts
index 2580b43adf..c2a0771aa1 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts
@@ -1,12 +1,8 @@
-/*import {
+import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE, UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE } from '../entity.js';
+import {
UMB_DOCUMENT_BLUEPRINT_DETAIL_REPOSITORY_ALIAS,
UMB_DOCUMENT_BLUEPRINT_ITEM_REPOSITORY_ALIAS,
-} from '../repository/index.js';*/
-import {
- UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
- UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
- UMB_DOCUMENT_BLUEPRINT_ITEM_ENTITY_TYPE,
-} from '../entity.js';
+} from '../index.js';
import { UmbCreateEntityAction } from './create/create.action.js';
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
@@ -34,19 +30,18 @@ const entityActions: Array = [
icon: 'icon-add',
label: 'Create',
},
- } /*
+ },
{
type: 'entityAction',
kind: 'delete',
alias: 'Umb.EntityAction.DocumentBlueprintItem.Delete',
name: 'Delete Document Blueprint Item Entity Action',
- forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_ITEM_ENTITY_TYPE],
+ forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE],
meta: {
detailRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_DETAIL_REPOSITORY_ALIAS,
itemRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_ITEM_REPOSITORY_ALIAS,
},
},
- */,
];
export const manifests = [...entityActions];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts
index cbddb145af..18e64cab86 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/menu-item/manifests.ts
@@ -1,4 +1,4 @@
-import { UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE } from '../entity.js';
+import { UMB_DOCUMENT_BLUEPRINT_TREE_ALIAS } from '../tree/manifests.js';
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
const menuItem: ManifestTypes = {
@@ -8,10 +8,8 @@ const menuItem: ManifestTypes = {
name: 'Document Blueprints Menu Item',
weight: 100,
meta: {
- treeAlias: 'Umb.Tree.DocumentBlueprint',
+ treeAlias: UMB_DOCUMENT_BLUEPRINT_TREE_ALIAS,
label: 'Document Blueprints',
- icon: 'icon-blueprint',
- entityType: UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
menus: ['Umb.Menu.Settings'],
},
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.repository.ts
index 4510666a59..1031ebc6ed 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.repository.ts
@@ -1,9 +1,9 @@
-import { UmbDocumentBlueprintFolderServerDataSource } from './document-blueprint-folder.server.data-source.js';
-import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
-import { UmbFolderRepositoryBase } from '@umbraco-cms/backoffice/tree';
+// import { UmbDocumentBlueprintFolderServerDataSource } from './document-blueprint-folder.server.data-source.js';
+// import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+// import { UmbFolderRepositoryBase } from '@umbraco-cms/backoffice/tree';
-export class UmbDocumentBlueprintFolderRepository extends UmbFolderRepositoryBase {
- constructor(host: UmbControllerHost) {
- super(host, UmbDocumentBlueprintFolderServerDataSource);
- }
-}
+// export class UmbDocumentBlueprintFolderRepository extends UmbFolderRepositoryBase {
+// constructor(host: UmbControllerHost) {
+// super(host, UmbDocumentBlueprintFolderServerDataSource);
+// }
+// }
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.server.data-source.ts
index a3dd268887..993af8fcea 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.server.data-source.ts
@@ -1,122 +1,122 @@
-import type { UmbCreateFolderModel, UmbFolderDataSource, UmbUpdateFolderModel } from '@umbraco-cms/backoffice/tree';
-import { DocumentBlueprintResource } from '@umbraco-cms/backoffice/external/backend-api';
-import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
-import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
+// import type { UmbCreateFolderModel, UmbFolderDataSource, UmbUpdateFolderModel } from '@umbraco-cms/backoffice/tree';
+// import { DocumentBlueprintResource } from '@umbraco-cms/backoffice/external/backend-api';
+// import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+// import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
-/**
- * A data source for a Document Blueprint folder that fetches data from the server
- * @export
- * @class UmbDocumentBlueprintFolderServerDataSource
- * @implements {RepositoryDetailDataSource}
- */
-export class UmbDocumentBlueprintFolderServerDataSource implements UmbFolderDataSource {
- #host: UmbControllerHost;
+// /**
+// * A data source for a Document Blueprint folder that fetches data from the server
+// * @export
+// * @class UmbDocumentBlueprintFolderServerDataSource
+// * @implements {RepositoryDetailDataSource}
+// */
+// export class UmbDocumentBlueprintFolderServerDataSource implements UmbFolderDataSource {
+// #host: UmbControllerHost;
- /**
- * Creates an instance of UmbDocumentBlueprintFolderServerDataSource.
- * @param {UmbControllerHost} host
- * @memberof UmbDocumentBlueprintFolderServerDataSource
- */
- constructor(host: UmbControllerHost) {
- this.#host = host;
- }
+// /**
+// * Creates an instance of UmbDocumentBlueprintFolderServerDataSource.
+// * @param {UmbControllerHost} host
+// * @memberof UmbDocumentBlueprintFolderServerDataSource
+// */
+// constructor(host: UmbControllerHost) {
+// this.#host = host;
+// }
- /**
- * Fetches a Document Blueprint folder from the server
- * @param {string} unique
- * @return {*}
- * @memberof UmbDocumentBlueprintFolderServerDataSource
- */
- async read(unique: string) {
- if (!unique) throw new Error('Unique is missing');
+// /**
+// * Fetches a Document Blueprint folder from the server
+// * @param {string} unique
+// * @return {*}
+// * @memberof UmbDocumentBlueprintFolderServerDataSource
+// */
+// async read(unique: string) {
+// if (!unique) throw new Error('Unique is missing');
- const { data, error } = await tryExecuteAndNotify(
- this.#host,
- DocumentBlueprintResource.getDocumentBlueprintFolderById({
- id: unique,
- }),
- );
+// const { data, error } = await tryExecuteAndNotify(
+// this.#host,
+// DocumentBlueprintResource.getDocumentBlueprintFolderById({
+// id: unique,
+// }),
+// );
- if (data) {
- const mappedData = {
- unique: data.id,
- name: data.name,
- };
+// if (data) {
+// const mappedData = {
+// unique: data.id,
+// name: data.name,
+// };
- return { data: mappedData };
- }
+// return { data: mappedData };
+// }
- return { error };
- }
+// return { error };
+// }
- /**
- * Creates a Document Blueprint folder on the server
- * @param {UmbCreateFolderModel} args
- * @return {*}
- * @memberof UmbDocumentBlueprintFolderServerDataSource
- */
- async create(args: UmbCreateFolderModel) {
- if (args.parentUnique === undefined) throw new Error('Parent unique is missing');
- if (!args.name) throw new Error('Name is missing');
+// /**
+// * Creates a Document Blueprint folder on the server
+// * @param {UmbCreateFolderModel} args
+// * @return {*}
+// * @memberof UmbDocumentBlueprintFolderServerDataSource
+// */
+// async create(args: UmbCreateFolderModel) {
+// if (args.parentUnique === undefined) throw new Error('Parent unique is missing');
+// if (!args.name) throw new Error('Name is missing');
- const requestBody = {
- id: args.unique,
- parent: args.parentUnique ? { id: args.parentUnique } : null,
- name: args.name,
- };
+// const requestBody = {
+// id: args.unique,
+// parent: args.parentUnique ? { id: args.parentUnique } : null,
+// name: args.name,
+// };
- const { error } = await tryExecuteAndNotify(
- this.#host,
- DocumentBlueprintResource.postDocumentBlueprintFolder({
- requestBody,
- }),
- );
+// const { error } = await tryExecuteAndNotify(
+// this.#host,
+// DocumentBlueprintResource.postDocumentBlueprintFolder({
+// requestBody,
+// }),
+// );
- if (!error) {
- return this.read(args.unique);
- }
+// if (!error) {
+// return this.read(args.unique);
+// }
- return { error };
- }
+// return { error };
+// }
- /**
- * Updates a Document Blueprint folder on the server
- * @param {UmbUpdateFolderModel} args
- * @return {*}
- * @memberof UmbDocumentBlueprintFolderServerDataSource
- */
- async update(args: UmbUpdateFolderModel) {
- if (!args.unique) throw new Error('Unique is missing');
- if (!args.name) throw new Error('Folder name is missing');
+// /**
+// * Updates a Document Blueprint folder on the server
+// * @param {UmbUpdateFolderModel} args
+// * @return {*}
+// * @memberof UmbDocumentBlueprintFolderServerDataSource
+// */
+// async update(args: UmbUpdateFolderModel) {
+// if (!args.unique) throw new Error('Unique is missing');
+// if (!args.name) throw new Error('Folder name is missing');
- const { error } = await tryExecuteAndNotify(
- this.#host,
- DocumentBlueprintResource.putDocumentBlueprintFolderById({
- id: args.unique,
- requestBody: { name: args.name },
- }),
- );
+// const { error } = await tryExecuteAndNotify(
+// this.#host,
+// DocumentBlueprintResource.putDocumentBlueprintFolderById({
+// id: args.unique,
+// requestBody: { name: args.name },
+// }),
+// );
- if (!error) {
- return this.read(args.unique);
- }
+// if (!error) {
+// return this.read(args.unique);
+// }
- return { error };
- }
+// return { error };
+// }
- /**
- * Deletes a Document Blueprint folder on the server
- * @param {string} unique
- * @return {*}
- * @memberof UmbDocumentBlueprintServerDataSource
- */
- async delete(unique: string) {
- if (!unique) throw new Error('Unique is missing');
- return tryExecuteAndNotify(
- this.#host,
- DocumentBlueprintResource.deleteDocumentBlueprintFolderById({
- id: unique,
- }),
- );
- }
-}
+// /**
+// * Deletes a Document Blueprint folder on the server
+// * @param {string} unique
+// * @return {*}
+// * @memberof UmbDocumentBlueprintServerDataSource
+// */
+// async delete(unique: string) {
+// if (!unique) throw new Error('Unique is missing');
+// return tryExecuteAndNotify(
+// this.#host,
+// DocumentBlueprintResource.deleteDocumentBlueprintFolderById({
+// id: unique,
+// }),
+// );
+// }
+// }
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/index.ts
index 29904de469..c0cde243d3 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/index.ts
@@ -1,2 +1,2 @@
-export { UmbDocumentBlueprintFolderRepository } from './document-blueprint-folder.repository.js';
-export { UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS } from './manifests.js';
+// export { UmbDocumentBlueprintFolderRepository } from './document-blueprint-folder.repository.js';
+// export { UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS } from './manifests.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/manifests.ts
index 9eef583220..90635572ee 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/manifests.ts
@@ -1,37 +1,37 @@
-import { UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../../entity.js';
-import { UmbDocumentBlueprintFolderRepository } from './document-blueprint-folder.repository.js';
-import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
+// import { UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../../entity.js';
+// import { UmbDocumentBlueprintFolderRepository } from './document-blueprint-folder.repository.js';
+// import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
-export const UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS = 'Umb.Repository.DocumentBlueprint.Folder';
+// export const UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS = 'Umb.Repository.DocumentBlueprint.Folder';
-const folderRepository: ManifestRepository = {
- type: 'repository',
- alias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS,
- name: 'Document Blueprint Folder Repository',
- api: UmbDocumentBlueprintFolderRepository,
-};
+// const folderRepository: ManifestRepository = {
+// type: 'repository',
+// alias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS,
+// name: 'Document Blueprint Folder Repository',
+// api: UmbDocumentBlueprintFolderRepository,
+// };
-const entityActions: Array = [
- {
- type: 'entityAction',
- kind: 'folderUpdate',
- alias: 'Umb.EntityAction.DocumentBlueprint.Folder.Rename',
- name: 'Rename Document Blueprint Folder Entity Action',
- forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE],
- meta: {
- folderRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS,
- },
- },
- {
- type: 'entityAction',
- kind: 'folderDelete',
- alias: 'Umb.EntityAction.DocumentBlueprint.Folder.Delete',
- name: 'Delete Document Blueprint Folder Entity Action',
- forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE],
- meta: {
- folderRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS,
- },
- },
-];
+// const entityActions: Array = [
+// {
+// type: 'entityAction',
+// kind: 'folderUpdate',
+// alias: 'Umb.EntityAction.DocumentBlueprint.Folder.Rename',
+// name: 'Rename Document Blueprint Folder Entity Action',
+// forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE],
+// meta: {
+// folderRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS,
+// },
+// },
+// {
+// type: 'entityAction',
+// kind: 'folderDelete',
+// alias: 'Umb.EntityAction.DocumentBlueprint.Folder.Delete',
+// name: 'Delete Document Blueprint Folder Entity Action',
+// forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE],
+// meta: {
+// folderRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS,
+// },
+// },
+// ];
-export const manifests = [folderRepository, ...entityActions];
+// export const manifests = [folderRepository, ...entityActions];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/types.ts
index dd70703d94..e29ea4ff3b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/types.ts
@@ -1,6 +1,6 @@
-import type { UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../../entity.js';
-import type { UmbDocumentBlueprintTreeItemModel } from '../types.js';
+// import type { UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../../entity.js';
+// import type { UmbDocumentBlueprintTreeItemModel } from '../types.js';
-export interface UmbDocumentBlueprintFolderTreeItemModel extends UmbDocumentBlueprintTreeItemModel {
- entityType: typeof UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE;
-}
+// export interface UmbDocumentBlueprintFolderTreeItemModel extends UmbDocumentBlueprintTreeItemModel {
+// entityType: typeof UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE;
+// }
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts
index f098c0956c..9f2a67da2f 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts
@@ -1,2 +1,2 @@
export { UMB_DOCUMENT_BLUEPRINT_TREE_STORE_CONTEXT } from './document-blueprint-tree.store.js';
-export * from './folder/index.js';
+//export * from './folder/index.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/manifests.ts
index f69949127f..6a413d7177 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/manifests.ts
@@ -3,7 +3,7 @@ import {
UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE,
UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
} from '../entity.js';
-import { manifests as folderManifests } from './folder/manifests.js';
+//import { manifests as folderManifests } from './folder/manifests.js';
import { manifests as reloadManifests } from './reload-tree-item-children/manifests.js';
import { UmbDocumentBlueprintTreeRepository } from './document-blueprint-tree.repository.js';
import { UmbDocumentBlueprintTreeStore } from './document-blueprint-tree.store.js';
@@ -16,6 +16,7 @@ import type {
export const UMB_DOCUMENT_BLUEPRINT_TREE_REPOSITORY_ALIAS = 'Umb.Repository.DocumentBlueprint.Tree';
export const UMB_DOCUMENT_BLUEPRINT_TREE_STORE_ALIAS = 'Umb.Store.DocumentBlueprint.Tree';
+export const UMB_DOCUMENT_BLUEPRINT_TREE_ALIAS = 'Umb.Tree.DocumentBlueprint';
const treeRepository: ManifestRepository = {
type: 'repository',
@@ -34,7 +35,7 @@ const treeStore: ManifestTreeStore = {
const tree: ManifestTree = {
type: 'tree',
kind: 'default',
- alias: 'Umb.Tree.DocumentBlueprint',
+ alias: UMB_DOCUMENT_BLUEPRINT_TREE_ALIAS,
name: 'Document Blueprints Tree',
meta: {
repositoryAlias: UMB_DOCUMENT_BLUEPRINT_TREE_REPOSITORY_ALIAS,
@@ -53,4 +54,5 @@ const treeItem: ManifestTreeItem = {
],
};
-export const manifests = [treeRepository, treeStore, tree, treeItem, ...folderManifests, ...reloadManifests];
+export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadManifests];
+//...folderManifests,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.element.ts
index 495489dfe9..ce5f7060a0 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.element.ts
@@ -48,6 +48,7 @@ export class UmbDocumentBlueprintWorkspaceElement extends UmbLitElement {
},
},
{
+ /** TODO: Any way to setup the root without edit/null appearing? */
path: 'edit/null',
component: this.#rootElement,
},
@@ -55,6 +56,7 @@ export class UmbDocumentBlueprintWorkspaceElement extends UmbLitElement {
path: 'edit/:unique',
component: this.#editorElement,
setup: (_component, info) => {
+ console.log('edit unique');
const unique = info.match.params.unique;
this.#workspaceContext!.load(unique);
},
From 8ab192131236dd4c8977bfbf16739ef034abf897 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Mon, 18 Mar 2024 12:26:26 +0100
Subject: [PATCH 009/280] fix tree
---
.../document-blueprint.data.ts | 2 +-
...ument-blueprint-item.server.data-source.ts | 9 ++-
...ument-blueprint-tree.server.data-source.ts | 2 +-
...ment-blueprint-workspace-editor.element.ts | 1 +
.../document-blueprint-workspace.context.ts | 1 -
.../document-blueprint-workspace.element.ts | 75 +++++++------------
.../workspace/manifests.ts | 4 +-
7 files changed, 37 insertions(+), 57 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.data.ts
index 6b362e7995..084f715a9a 100644
--- a/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.data.ts
+++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document-blueprint/document-blueprint.data.ts
@@ -28,7 +28,7 @@ export const data: Array = [
publishDate: '2023-02-06T15:32:24.957009',
culture: 'en-us',
segment: null,
- name: 'The Simplest Document',
+ name: 'The Simplest Document Blueprint',
createDate: '2023-02-06T15:32:05.350038',
updateDate: '2023-02-06T15:32:24.957009',
},
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.server.data-source.ts
index 1e8df1b933..c971e13bcf 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/item/document-blueprint-item.server.data-source.ts
@@ -1,7 +1,7 @@
import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE } from '../../entity.js';
import type { UmbDocumentBlueprintItemModel } from './types.js';
-import type { DocumentItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
-import { DocumentResource } from '@umbraco-cms/backoffice/external/backend-api';
+import type { CancelablePromise, DocumentItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
+import { DocumentBlueprintResource, DocumentResource } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository';
@@ -29,7 +29,10 @@ export class UmbDocumentBlueprintItemServerDataSource extends UmbItemServerDataS
}
/* eslint-disable local-rules/no-direct-api-import */
-const getItems = (uniques: Array) => DocumentResource.getItemDocument({ id: uniques });
+const getItems = (uniques: Array) =>
+ DocumentBlueprintResource.getItemDocumentBlueprint({ id: uniques }) as unknown as CancelablePromise<
+ DocumentItemResponseModel[]
+ >;
const mapper = (item: DocumentItemResponseModel): UmbDocumentBlueprintItemModel => {
return {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts
index d7b30c8318..da3f6f406e 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts
@@ -1,4 +1,4 @@
-import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE, UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../entity.js';
+import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE } from '../entity.js';
import type { UmbDocumentBlueprintTreeItemModel } from './types.js';
import type { UmbTreeChildrenOfRequestArgs, UmbTreeRootItemsRequestArgs } from '@umbraco-cms/backoffice/tree';
import { UmbTreeServerDataSourceBase } from '@umbraco-cms/backoffice/tree';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts
index 7b17e80df5..0b4d12d646 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts
@@ -20,6 +20,7 @@ export class UmbDocumentBlueprintWorkspaceEditorElement extends UmbLitElement {
constructor() {
super();
+ console.log('editor');
this.consumeContext(UMB_DOCUMENT_BLUEPRINT_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts
index a0279b8906..1260990680 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts
@@ -130,7 +130,6 @@ export class UmbDocumentBlueprintWorkspaceContext
}
async load(unique: string) {
- console.log('load');
this.resetState();
this.#getDataPromise = this.repository.requestByUnique(unique);
const { data } = await this.#getDataPromise;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.element.ts
index ce5f7060a0..abf3533d08 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.element.ts
@@ -1,4 +1,4 @@
-import type { UmbDocumentBlueprintWorkspaceContext } from './document-blueprint-workspace.context.js';
+import { UmbDocumentBlueprintWorkspaceContext } from './document-blueprint-workspace.context.js';
import { UmbDocumentBlueprintWorkspaceEditorElement } from './document-blueprint-workspace-editor.element.js';
import { UmbDocumentBlueprintRootWorkspaceElement } from './document-blueprint-root-workspace.element.js';
import { html, customElement, css, state } from '@umbraco-cms/backoffice/external/lit';
@@ -11,61 +11,38 @@ import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/wor
@customElement('umb-document-blueprint-workspace')
export class UmbDocumentBlueprintWorkspaceElement extends UmbLitElement {
- #workspaceContext?: UmbDocumentBlueprintWorkspaceContext;
+ #workspaceContext = new UmbDocumentBlueprintWorkspaceContext(this);
#editorElement = () => new UmbDocumentBlueprintWorkspaceEditorElement();
#rootElement = () => new UmbDocumentBlueprintRootWorkspaceElement();
@state()
- _routes: UmbRoute[] = [];
+ _routes: UmbRoute[] = [
+ {
+ path: 'create/parent/:entityType/:parentUnique/:documentTypeUnique',
+ component: this.#editorElement,
+ setup: (_component, info) => {
+ const parentEntityType = info.match.params.entityType;
+ const parentUnique = info.match.params.parentUnique === 'null' ? null : info.match.params.parentUnique;
+ const documentTypeUnique = info.match.params.documentTypeUnique;
+ this.#workspaceContext.create({ entityType: parentEntityType, unique: parentUnique }, documentTypeUnique);
- public set manifest(manifest: ManifestWorkspace) {
- createExtensionApi(this, manifest).then((context) => {
- if (context) {
- this.#gotWorkspaceContext(context);
- }
- });
- }
-
- #gotWorkspaceContext(context: UmbApi) {
- this.#workspaceContext = context as UmbDocumentBlueprintWorkspaceContext;
-
- this._routes = [
- {
- path: 'create/parent/:entityType/:parentUnique/:documentTypeUnique',
- component: this.#editorElement,
- setup: async (_component, info) => {
- // TODO: Remember the perspective of permissions here, we need to check if the user has access to create a document of this type under this parent?
- const parentEntityType = info.match.params.entityType;
- const parentUnique = info.match.params.parentUnique === 'null' ? null : info.match.params.parentUnique;
- const documentTypeUnique = info.match.params.documentTypeUnique;
- this.#workspaceContext!.create({ entityType: parentEntityType, unique: parentUnique }, documentTypeUnique);
-
- new UmbWorkspaceIsNewRedirectController(
- this,
- this.#workspaceContext!,
- this.shadowRoot!.querySelector('umb-router-slot')!,
- );
- },
+ new UmbWorkspaceIsNewRedirectController(
+ this,
+ this.#workspaceContext,
+ this.shadowRoot!.querySelector('umb-router-slot')!,
+ );
},
- {
- /** TODO: Any way to setup the root without edit/null appearing? */
- path: 'edit/null',
- component: this.#rootElement,
+ },
+ {
+ path: 'edit/:unique',
+ component: this.#editorElement,
+ setup: (_component, info) => {
+ this.removeControllerByAlias('isNewRedirectController');
+ const unique = info.match.params.unique;
+ this.#workspaceContext.load(unique);
},
- {
- path: 'edit/:unique',
- component: this.#editorElement,
- setup: (_component, info) => {
- console.log('edit unique');
- const unique = info.match.params.unique;
- this.#workspaceContext!.load(unique);
- },
- },
- ];
-
- // TODO: We need to recreate when ID changed?
- new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'workspaceContext', [this, this.#workspaceContext]);
- }
+ },
+ ];
render() {
return html` `;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts
index a93f324175..6e9d8a47d5 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts
@@ -1,4 +1,4 @@
-import { UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE } from '../entity.js';
+import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE, UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE } from '../entity.js';
import { UmbSaveWorkspaceAction } from '@umbraco-cms/backoffice/workspace';
import type { ManifestWorkspace, ManifestWorkspaceActions } from '@umbraco-cms/backoffice/extension-registry';
@@ -10,7 +10,7 @@ const workspace: ManifestWorkspace = {
name: 'Document Blueprint Root Workspace',
js: () => import('./document-blueprint-workspace.element.js'),
meta: {
- entityType: UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
+ entityType: UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
},
};
From df9cb2ebaa3830de1d43e9b9a248eb327fe90389 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Tue, 19 Mar 2024 10:34:56 +0100
Subject: [PATCH 010/280] modal create
---
.../entity-actions/create/create.action.ts | 22 ++++-
.../entity-actions/create/manifests.ts | 12 +++
...-blueprint-create-options-modal.element.ts | 80 +++++++++++++++++++
.../entity-actions/create/modal/index.ts | 22 +++++
.../entity-actions/manifests.ts | 3 +-
.../document-blueprint-workspace.context.ts | 6 +-
6 files changed, 138 insertions(+), 7 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/modal/document-blueprint-create-options-modal.element.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/modal/index.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/create.action.ts
index 0b13db78b3..d5034e8d25 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/create.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/create.action.ts
@@ -1,6 +1,9 @@
+import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE } from '../../entity.js';
+import { UMB_DOCUMENT_BLUEPRINT_CREATE_OPTIONS_MODAL } from './modal/index.js';
import type { UmbEntityActionArgs } from '@umbraco-cms/backoffice/entity-action';
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
export class UmbCreateEntityAction extends UmbEntityActionBase {
constructor(host: UmbControllerHost, args: UmbEntityActionArgs) {
@@ -8,10 +11,23 @@ export class UmbCreateEntityAction extends UmbEntityActionBase {
}
async execute() {
- const url = `section/settings/workspace/document-blueprint/create/parent/${this.args.entityType}/${
- this.args.unique || 'null'
+ const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
+ const modalContext = modalManager.open(this, UMB_DOCUMENT_BLUEPRINT_CREATE_OPTIONS_MODAL, {
+ data: {
+ parent: {
+ unique: this.args.unique,
+ entityType: this.args.entityType,
+ },
+ },
+ });
+
+ await modalContext.onSubmit().catch(() => undefined);
+
+ const documentTypeUnique = modalContext.getValue().documentTypeUnique;
+
+ const url = `section/settings/workspace/${UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE}/create/parent/${this.args.entityType}/${
+ documentTypeUnique || 'null'
}`;
- // TODO: how do we handle this with a href?
history.pushState(null, '', url);
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/manifests.ts
new file mode 100644
index 0000000000..1c1c7a408d
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/manifests.ts
@@ -0,0 +1,12 @@
+import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
+
+const entityActions: Array = [
+ {
+ type: 'modal',
+ alias: 'Umb.Modal.DocumentBlueprintCreateOptions',
+ name: 'Document Blueprint Create Options Modal',
+ js: () => import('./modal/document-blueprint-create-options-modal.element.js'),
+ },
+];
+
+export const manifests = [...entityActions];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/modal/document-blueprint-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/modal/document-blueprint-create-options-modal.element.ts
new file mode 100644
index 0000000000..ef7e3ac473
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/modal/document-blueprint-create-options-modal.element.ts
@@ -0,0 +1,80 @@
+import type {
+ UmbDocumentBlueprintCreateOptionsModalData,
+ UmbDocumentBlueprintCreateOptionsModalValue,
+} from './index.js';
+import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
+import { html, customElement, css, state } from '@umbraco-cms/backoffice/external/lit';
+import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
+import type { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
+import { UmbDocumentTypeStructureRepository } from '@umbraco-cms/backoffice/document-type';
+import { type UmbSelectedEvent, UmbSelectionChangeEvent } from '@umbraco-cms/backoffice/event';
+import type { UmbTreeElement } from '@umbraco-cms/backoffice/tree';
+
+@customElement('umb-document-blueprint-create-options-modal')
+export class UmbDocumentBlueprintCreateOptionsModalElement extends UmbModalBaseElement<
+ UmbDocumentBlueprintCreateOptionsModalData,
+ UmbDocumentBlueprintCreateOptionsModalValue
+> {
+ @state()
+ private _documentTypes?: Array;
+
+ #documentTypeRepository = new UmbDocumentTypeStructureRepository(this);
+
+ connectedCallback(): void {
+ super.connectedCallback();
+ }
+
+ async #fetchTypes() {
+ //const something = await this.#documentTypeRepository.
+ }
+
+ #onNavigate() {
+ this._submitModal();
+ }
+
+ #onSelected(event: UmbSelectedEvent) {
+ event.stopPropagation();
+ const element = event.target as UmbTreeElement;
+ this.value = { documentTypeUnique: element.getSelection()[0] };
+ this.modalContext?.dispatchEvent(new UmbSelectionChangeEvent());
+ this.#onNavigate();
+ }
+
+ render() {
+ return html`
+
+
+ Create an item under Content Templates
+
+ Select the Document Type you want to make a content blueprint for
+
+ item.isElement == false,
+ }}
+ @selected=${this.#onSelected}>
+
+
+
+ `;
+ }
+
+ static styles = [
+ UmbTextStyles,
+ css`
+ strong {
+ display: block;
+ }
+ `,
+ ];
+}
+
+export default UmbDocumentBlueprintCreateOptionsModalElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-document-blueprint-create-options-modal': UmbDocumentBlueprintCreateOptionsModalElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/modal/index.ts
new file mode 100644
index 0000000000..98a89164ec
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/modal/index.ts
@@ -0,0 +1,22 @@
+import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
+
+export interface UmbDocumentBlueprintCreateOptionsModalData {
+ parent: {
+ unique: string | null;
+ entityType: string;
+ };
+}
+
+export interface UmbDocumentBlueprintCreateOptionsModalValue {
+ documentTypeUnique: string;
+}
+
+export const UMB_DOCUMENT_BLUEPRINT_CREATE_OPTIONS_MODAL = new UmbModalToken<
+ UmbDocumentBlueprintCreateOptionsModalData,
+ UmbDocumentBlueprintCreateOptionsModalValue
+>('Umb.Modal.DocumentBlueprintCreateOptions', {
+ modal: {
+ type: 'sidebar',
+ size: 'small',
+ },
+});
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts
index c2a0771aa1..192700d16e 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts
@@ -3,6 +3,7 @@ import {
UMB_DOCUMENT_BLUEPRINT_DETAIL_REPOSITORY_ALIAS,
UMB_DOCUMENT_BLUEPRINT_ITEM_REPOSITORY_ALIAS,
} from '../index.js';
+import { manifests as createManifests } from './create/manifests.js';
import { UmbCreateEntityAction } from './create/create.action.js';
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
@@ -44,4 +45,4 @@ const entityActions: Array = [
},
];
-export const manifests = [...entityActions];
+export const manifests = [...entityActions, ...createManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts
index 1260990680..8df0383b97 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts
@@ -8,10 +8,9 @@ import type {
UmbDocumentBlueprintVariantModel,
UmbDocumentBlueprintVariantOptionModel,
} from '../types.js';
-//import { umbPickDocumentVariantModal, type UmbDocumentBlueprintVariantPickerModalType } from '../modals/index.js';
+/* import { umbPickDocumentVariantModal, type UmbDocumentBlueprintVariantPickerModalType } from '../modals/index.js';*/
import { UMB_DOCUMENT_BLUEPRINT_ROOT_WORKSPACE_ALIAS } from './manifests.js';
import { UMB_INVARIANT_CULTURE, UmbVariantId } from '@umbraco-cms/backoffice/variant';
-import { UmbContentTypePropertyStructureManager } from '@umbraco-cms/backoffice/content-type';
import {
UmbEditableWorkspaceContextBase,
UmbWorkspaceSplitViewManager,
@@ -26,10 +25,11 @@ import {
} from '@umbraco-cms/backoffice/observable-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbLanguageCollectionRepository, type UmbLanguageDetailModel } from '@umbraco-cms/backoffice/language';
-import { type Observable, firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs';
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
import { UmbReloadTreeItemChildrenRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree';
import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/event';
+import { UmbContentTypePropertyStructureManager } from '@umbraco-cms/backoffice/content-type';
+import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
type EntityType = UmbDocumentBlueprintDetailModel;
export class UmbDocumentBlueprintWorkspaceContext
From 5439668c8657cbb5b2e29a40db7ace168f2f73ad Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Tue, 19 Mar 2024 10:46:50 +0100
Subject: [PATCH 011/280] structure manager
---
.../workspace/document-blueprint-workspace.context.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts
index 8df0383b97..9017a990fa 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts
@@ -28,7 +28,7 @@ import { UmbLanguageCollectionRepository, type UmbLanguageDetailModel } from '@u
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
import { UmbReloadTreeItemChildrenRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree';
import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/event';
-import { UmbContentTypePropertyStructureManager } from '@umbraco-cms/backoffice/content-type';
+import { UmbContentTypeStructureManager } from '@umbraco-cms/backoffice/content-type';
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
type EntityType = UmbDocumentBlueprintDetailModel;
@@ -65,7 +65,7 @@ export class UmbDocumentBlueprintWorkspaceContext
readonly urls = this.#currentData.asObservablePart((data) => data?.urls || []);
readonly templateId = this.#currentData.asObservablePart((data) => data?.template?.unique || null);
- readonly structure = new UmbContentTypePropertyStructureManager(this, new UmbDocumentTypeDetailRepository(this));
+ readonly structure = new UmbContentTypeStructureManager(this, new UmbDocumentTypeDetailRepository(this));
readonly variesByCulture = this.structure.ownerContentTypePart((x) => x?.variesByCulture);
//#variesByCulture?: boolean;
readonly variesBySegment = this.structure.ownerContentTypePart((x) => x?.variesBySegment);
From b6bc2a531c36a539018d43f21fcc140fd11ba7c4 Mon Sep 17 00:00:00 2001
From: Lone Iversen <108085781+loivsen@users.noreply.github.com>
Date: Tue, 19 Mar 2024 14:05:06 +0100
Subject: [PATCH 012/280] action
---
.../entity-actions/manifests.ts | 20 ++++++-------------
1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts
index 192700d16e..ff487efb7f 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/manifests.ts
@@ -1,4 +1,8 @@
-import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE, UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE } from '../entity.js';
+import {
+ UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE,
+ UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE,
+ UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE,
+} from '../entity.js';
import {
UMB_DOCUMENT_BLUEPRINT_DETAIL_REPOSITORY_ALIAS,
UMB_DOCUMENT_BLUEPRINT_ITEM_REPOSITORY_ALIAS,
@@ -14,19 +18,7 @@ const entityActions: Array = [
alias: 'Umb.EntityAction.DocumentBlueprint.Create',
name: 'Create Document Blueprint Entity Action',
api: UmbCreateEntityAction,
- forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE],
- meta: {
- icon: 'icon-add',
- label: 'Create',
- },
- },
- {
- type: 'entityAction',
- kind: 'default',
- alias: 'Umb.EntityAction.DocumentBlueprintItem.Create',
- name: 'Create Document Blueprint Item Entity Action',
- api: UmbCreateEntityAction,
- forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE],
+ forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_ROOT_ENTITY_TYPE, UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE],
meta: {
icon: 'icon-add',
label: 'Create',
From f9284cf36f66045cbf90cc7a448faf46a225795c Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 14:55:09 +0200
Subject: [PATCH 013/280] remove document delete action
---
.../documents/documents/entity-actions/manifests.ts | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts
index 36d9a0cf3e..7455fc7762 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts
@@ -7,19 +7,6 @@ import { manifests as cultureAndHostnamesManifests } from './culture-and-hostnam
import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry';
const entityActions: Array = [
- {
- type: 'entityAction',
- kind: 'delete',
- alias: 'Umb.EntityAction.Document.Delete',
- name: 'Delete Document Entity Action',
- weight: 1100,
- forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE],
- meta: {
- deleteRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
- itemRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
- pickerModalAlias: UMB_DOCUMENT_PICKER_MODAL,
- },
- },
{
type: 'entityAction',
kind: 'default',
From 69d0bc0618dd116a2c75db3c7ffeb567d079d4b1 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 14:55:21 +0200
Subject: [PATCH 014/280] rename property
---
.../core/extension-registry/models/entity-action.model.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
index c5ddd408fa..ae8066a9ab 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
@@ -63,7 +63,7 @@ export interface ManifestEntityActionTrashKind extends ManifestEntityAction
Date: Tue, 2 Apr 2024 14:55:37 +0200
Subject: [PATCH 015/280] remove user permission condition
---
.../documents/recycle-bin/entity-action/manifests.ts | 6 ------
1 file changed, 6 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
index 2c654126d5..dec1ebb439 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
@@ -12,11 +12,5 @@ export const manifests = [
itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
trashRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
},
- conditions: [
- {
- alias: 'Umb.Condition.UserPermission',
- match: 'Umb.UserPermission.Document.Delete',
- },
- ],
},
];
From ff317d67792279344e7a70bea46e7d266157e470 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 16:03:05 +0200
Subject: [PATCH 016/280] update trash action
---
.../common/trash/trash.action.kind.ts | 6 +-
.../common/trash/trash.action.ts | 59 +++++++++++--------
2 files changed, 38 insertions(+), 27 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.kind.ts
index beb3103a7b..53a7273139 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.kind.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.kind.ts
@@ -11,13 +11,13 @@ export const manifest: UmbBackofficeManifestKind = {
type: 'entityAction',
kind: 'trash',
api: () => import('./trash.action.js'),
- weight: 900,
+ weight: 1100,
forEntityTypes: [],
meta: {
icon: 'icon-trash',
- label: 'Trash',
+ label: 'Trash...',
itemRepositoryAlias: '',
- trashRepositoryAlias: '',
+ recycleBinRepositoryAlias: '',
},
},
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts
index 3c4fc550c3..14ab66edb3 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts
@@ -1,34 +1,45 @@
import { UmbEntityActionBase } from '../../entity-action-base.js';
-import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
-//import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
+import { UmbRequestReloadStructureForEntityEvent } from '../../request-reload-structure-for-entity.event.js';
+import { createExtensionApiByAlias, type MetaEntityActionDeleteKind } from '@umbraco-cms/backoffice/extension-registry';
+import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
+import type { UmbItemRepository } from '@umbraco-cms/backoffice/repository';
+import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
-export class UmbTrashEntityAction extends UmbEntityActionBase {
- constructor(host: UmbControllerHost, args: any) {
- super(host, args);
- }
+export class UmbDeleteEntityAction extends UmbEntityActionBase {
+ // TODO: make base type for item and detail models
async execute() {
- console.log(`execute trash for: ${this.args.unique}`);
- /*
- if (!this.unique) throw new Error('Unique is not available');
- if (!this.repository) return;
+ if (!this.args.unique) throw new Error('Cannot trash an item without a unique identifier.');
- const { data } = await this.repository.requestItems([this.unique]);
+ const itemRepository = await createExtensionApiByAlias>(
+ this,
+ this.args.meta.itemRepositoryAlias,
+ );
- if (data) {
- const item = data[0];
+ const { data } = await itemRepository.requestItems([this.args.unique]);
+ const item = data?.[0];
+ if (!item) throw new Error('Item not found.');
- await umbConfirmModal(this._host, {
- headline: `Trash ${item.name}`,
- content: 'Are you sure you want to move this item to the recycle bin?',
- color: 'danger',
- confirmLabel: 'Trash',
- });
+ // TODO: handle items with variants
+ await umbConfirmModal(this._host, {
+ headline: `Trash`,
+ content: `Are you sure you want to move ${item.name} to the recycle bin?`,
+ color: 'danger',
+ confirmLabel: 'Trash',
+ });
- this.repository?.trash(this.unique);
- }
- */
+ const recycleBinRepository = await createExtensionApiByAlias(this, this.args.meta.recycleBinRepositoryAlias);
+ await recycleBinRepository.trash(this.args.unique);
+
+ const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT);
+ const event = new UmbRequestReloadStructureForEntityEvent({
+ unique: this.args.unique,
+ entityType: this.args.entityType,
+ });
+
+ actionEventContext.dispatchEvent(event);
+
+ // TODO: reload destination
}
}
-
-export default UmbTrashEntityAction;
+export default UmbDeleteEntityAction;
From ddb0b704e4ea1499c7f50eb38aa0517096ba7d2d Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 16:03:30 +0200
Subject: [PATCH 017/280] work in progress repository
---
.../recycle-bin/entity-action/manifests.ts | 5 ++-
.../documents/recycle-bin/manifests.ts | 7 ++--
.../recycle-bin/repository/constants.ts | 1 +
.../document-recycle-bin.repository.ts | 30 ++++++++++++++
...document-recycle-bin.server.data-source.ts | 39 +++++++++++++++++++
.../documents/recycle-bin/repository/index.ts | 1 +
.../recycle-bin/repository/manifests.ts | 11 ++++++
.../documents/recycle-bin/repository/types.ts | 0
8 files changed, 89 insertions(+), 5 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/constants.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/types.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
index dec1ebb439..4c6a590d4c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
@@ -1,5 +1,6 @@
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
-import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
+import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
+import { UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from '../repository/index.js';
export const manifests = [
{
@@ -10,7 +11,7 @@ export const manifests = [
forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE],
meta: {
itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
- trashRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
+ recycleBinRepositoryAlias: UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
},
},
];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts
index 38ee0700be..1277abe4c1 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts
@@ -1,5 +1,6 @@
-import { manifests as treeManifests } from './tree/manifests.js';
-import { manifests as menuItemManifests } from './menu-item/manifests.js';
import { manifests as entityActionManifests } from './entity-action/manifests.js';
+import { manifests as menuItemManifests } from './menu-item/manifests.js';
+import { manifests as repositoryManifests } from './repository/manifests.js';
+import { manifests as treeManifests } from './tree/manifests.js';
-export const manifests = [...treeManifests, ...menuItemManifests, ...entityActionManifests];
+export const manifests = [...treeManifests, ...menuItemManifests, ...entityActionManifests, ...repositoryManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/constants.ts
new file mode 100644
index 0000000000..f350dc5e9d
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/constants.ts
@@ -0,0 +1 @@
+export const UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS = 'Umb.Repository.Document.RecycleBin';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts
new file mode 100644
index 0000000000..44a4f60478
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts
@@ -0,0 +1,30 @@
+import { UmbDocumentRecycleBinServerDataSource } from './document-recycle-bin.server.data-source.js';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository';
+
+export class UmbDocumentRecycleBinRepository extends UmbRepositoryBase {
+ #recycleBinSource: UmbDocumentRecycleBinServerDataSource;
+
+ constructor(host: UmbControllerHost) {
+ super(host);
+ this.#recycleBinSource = new UmbDocumentRecycleBinServerDataSource(this);
+ }
+
+ async requestTrash(args) {
+ return this.#recycleBinSource.trash(args);
+ }
+
+ async requestRestore(args) {
+ return this.#recycleBinSource.restore(args);
+ }
+
+ async requestEmptyBin() {
+ return this.#recycleBinSource.emptyBin();
+ }
+
+ async requestOriginalParent(args) {
+ return this.#recycleBinSource.getOriginalParent(args);
+ }
+}
+
+export { UmbDocumentRecycleBinRepository as api };
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
new file mode 100644
index 0000000000..3a4d74b20d
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
@@ -0,0 +1,39 @@
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
+
+export class UmbDocumentRecycleBinServerDataSource {
+ #host: UmbControllerHost;
+
+ constructor(host: UmbControllerHost) {
+ this.#host = host;
+ }
+
+ trash(args: { unique: string }) {
+ return tryExecuteAndNotify(this.#host, DocumentResource.putDocumentByIdMoveToRecycleBin({ id: args.unique }));
+ }
+
+ async restore(args: { unique: string; target: { unique: string | null } }) {
+ return tryExecuteAndNotify(this.#host, DocumentResource.putRecycleBinDocumentByIdRestore({ id: args.unique }));
+ }
+
+ emptyBin() {
+ return tryExecuteAndNotify(this.#host, DocumentResource);
+ }
+
+ async getOriginalParent(args: { unique: string }) {
+ const { data, error } = await tryExecuteAndNotify(
+ this.#host,
+ DocumentResource.getRecycleBinDocumentByIdOriginalParent({ id: args.unique }),
+ );
+
+ if (data) {
+ const mappedData = {
+ unique: data.id,
+ };
+
+ return { data: mappedData };
+ }
+
+ return { error };
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/index.ts
new file mode 100644
index 0000000000..50bcc134af
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/index.ts
@@ -0,0 +1 @@
+export { UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from './constants.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/manifests.ts
new file mode 100644
index 0000000000..b2b0b2ac63
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/manifests.ts
@@ -0,0 +1,11 @@
+import { UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from './constants.js';
+import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
+
+const queryRepository: ManifestRepository = {
+ type: 'repository',
+ alias: UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
+ name: 'Document Recycle Bin Repository',
+ api: () => import('./document-recycle-bin.repository.js'),
+};
+
+export const manifests = [queryRepository];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/types.ts
new file mode 100644
index 0000000000..e69de29bb2
From 81ee95a7185cabf709af9a9873395087525aba5a Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 16:15:17 +0200
Subject: [PATCH 018/280] use correct method
---
.../repository/document-recycle-bin.server.data-source.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
index 3a4d74b20d..3e00d33711 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
@@ -1,4 +1,5 @@
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { DocumentResource } from '@umbraco-cms/backoffice/external/backend-api';
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
export class UmbDocumentRecycleBinServerDataSource {
@@ -17,7 +18,7 @@ export class UmbDocumentRecycleBinServerDataSource {
}
emptyBin() {
- return tryExecuteAndNotify(this.#host, DocumentResource);
+ return tryExecuteAndNotify(this.#host, DocumentResource.deleteRecycleBinDocument());
}
async getOriginalParent(args: { unique: string }) {
From 0ae27a683380d14a4914154d23778fd35ce276a9 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 16:15:35 +0200
Subject: [PATCH 019/280] move import
---
.../documents/documents/recycle-bin/entity-action/manifests.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
index 4c6a590d4c..d665404052 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
@@ -1,6 +1,6 @@
+import { UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from '../repository/index.js';
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
-import { UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from '../repository/index.js';
export const manifests = [
{
From c722eb48edef7d913a14400c967b5a80f1a4bbe1 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 16:15:56 +0200
Subject: [PATCH 020/280] use correct method name on repo
---
.../core/entity-action/common/trash/trash.action.ts | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts
index 14ab66edb3..94e2da1304 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts
@@ -1,11 +1,12 @@
import { UmbEntityActionBase } from '../../entity-action-base.js';
import { UmbRequestReloadStructureForEntityEvent } from '../../request-reload-structure-for-entity.event.js';
-import { createExtensionApiByAlias, type MetaEntityActionDeleteKind } from '@umbraco-cms/backoffice/extension-registry';
+import type { MetaEntityActionTrashKind } from '@umbraco-cms/backoffice/extension-registry';
+import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
import type { UmbItemRepository } from '@umbraco-cms/backoffice/repository';
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
-export class UmbDeleteEntityAction extends UmbEntityActionBase {
+export class UmbTrashEntityAction extends UmbEntityActionBase {
// TODO: make base type for item and detail models
async execute() {
@@ -28,8 +29,8 @@ export class UmbDeleteEntityAction extends UmbEntityActionBase(this, this.args.meta.recycleBinRepositoryAlias);
+ await recycleBinRepository.requestTrash({ unique: this.args.unique });
const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT);
const event = new UmbRequestReloadStructureForEntityEvent({
@@ -42,4 +43,4 @@ export class UmbDeleteEntityAction extends UmbEntityActionBase
Date: Tue, 2 Apr 2024 16:46:57 +0200
Subject: [PATCH 021/280] register workspace for documents in recycle bin
---
.../documents/recycle-bin/manifests.ts | 9 +++-
.../recycle-bin/workspace/constants.ts | 1 +
...nt-recycle-bin-workspace-editor.element.ts | 45 +++++++++++++++++++
...ent-recycle-bin-workspace.context-token.ts | 12 +++++
.../document-recycle-bin-workspace.context.ts | 34 ++++++++++++++
.../documents/recycle-bin/workspace/index.ts | 1 +
.../recycle-bin/workspace/manifests.ts | 14 ++++++
7 files changed, 115 insertions(+), 1 deletion(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/constants.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace-editor.element.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context-token.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/manifests.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts
index 1277abe4c1..96b9d4b78a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts
@@ -2,5 +2,12 @@ import { manifests as entityActionManifests } from './entity-action/manifests.js
import { manifests as menuItemManifests } from './menu-item/manifests.js';
import { manifests as repositoryManifests } from './repository/manifests.js';
import { manifests as treeManifests } from './tree/manifests.js';
+import { manifests as workspaceManifests } from './workspace/manifests.js';
-export const manifests = [...treeManifests, ...menuItemManifests, ...entityActionManifests, ...repositoryManifests];
+export const manifests = [
+ ...entityActionManifests,
+ ...menuItemManifests,
+ ...repositoryManifests,
+ ...treeManifests,
+ ...workspaceManifests,
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/constants.ts
new file mode 100644
index 0000000000..61e0e19e34
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/constants.ts
@@ -0,0 +1 @@
+export const UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_ALIAS = 'Umb.Workspace.Document.RecycleBin';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace-editor.element.ts
new file mode 100644
index 0000000000..7477cf00d0
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace-editor.element.ts
@@ -0,0 +1,45 @@
+import { UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_CONTEXT } from './document-recycle-bin-workspace.context-token.js';
+import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
+import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
+import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry';
+
+const elementName = 'umb-document-recycle-bin-editor';
+
+@customElement(elementName)
+export class UmbDocumentRecycleBinWorkspaceEditorElement extends UmbLitElement {
+ @property({ attribute: false })
+ manifest?: ManifestWorkspace;
+
+ #workspaceContext?: typeof UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_CONTEXT.TYPE;
+
+ constructor() {
+ super();
+
+ this.consumeContext(UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_CONTEXT, (workspaceContext) => {
+ this.#workspaceContext = workspaceContext;
+ debugger;
+ });
+ }
+
+ render() {
+ return html`Document Recycle Bin
`;
+ }
+
+ static styles = [
+ css`
+ :host {
+ display: block;
+ width: 100%;
+ height: 100%;
+ }
+ `,
+ ];
+}
+
+export { UmbDocumentRecycleBinWorkspaceEditorElement as element };
+
+declare global {
+ interface HTMLElementTagNameMap {
+ [elementName]: UmbDocumentRecycleBinWorkspaceEditorElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context-token.ts
new file mode 100644
index 0000000000..51b8c272eb
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context-token.ts
@@ -0,0 +1,12 @@
+import type { UmbDocumentRecycleBinWorkspaceContext } from './document-recycle-bin-workspace.context.js';
+import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
+import type { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
+
+export const UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_CONTEXT = new UmbContextToken<
+ UmbWorkspaceContext,
+ UmbDocumentRecycleBinWorkspaceContext
+>(
+ 'UmbWorkspaceContext',
+ undefined,
+ (context): context is UmbDocumentRecycleBinWorkspaceContext => context.getEntityType?.() === 'document-recycle-bin',
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context.ts
new file mode 100644
index 0000000000..65163ed83f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context.ts
@@ -0,0 +1,34 @@
+import { UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_ALIAS } from './constants.js';
+import { UmbDocumentRecycleBinWorkspaceEditorElement } from './document-recycle-bin-workspace-editor.element.js';
+import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbRoutableWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
+import { UmbWorkspaceRouteManager } from '@umbraco-cms/backoffice/workspace';
+
+export class UmbDocumentRecycleBinWorkspaceContext extends UmbControllerBase implements UmbRoutableWorkspaceContext {
+ public readonly workspaceAlias = UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_ALIAS;
+ public readonly routes = new UmbWorkspaceRouteManager(this);
+
+ constructor(host: UmbControllerHost) {
+ super(host, 'Umb.Workspace.Document.RecycleBin');
+
+ this.routes.setRoutes([
+ {
+ path: 'edit/:unique',
+ component: UmbDocumentRecycleBinWorkspaceEditorElement,
+ setup: (_component, info) => {
+ const unique = info.match.params.unique;
+ console.log('unique', unique);
+ },
+ },
+ ]);
+ }
+
+ getEntityType() {
+ return 'document-recycle-bin';
+ }
+
+ destroy(): void {}
+}
+
+export { UmbDocumentRecycleBinWorkspaceContext as api };
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/index.ts
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/index.ts
@@ -0,0 +1 @@
+
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/manifests.ts
new file mode 100644
index 0000000000..cd04c18b64
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/manifests.ts
@@ -0,0 +1,14 @@
+import type { ManifestWorkspaces } from '@umbraco-cms/backoffice/extension-registry';
+
+const workspace: ManifestWorkspaces = {
+ type: 'workspace',
+ kind: 'routable',
+ alias: 'Umb.Workspace.Document.RecycleBin',
+ name: 'Document Recycle Bin Workspace',
+ api: () => import('./document-recycle-bin-workspace.context.js'),
+ meta: {
+ entityType: 'document-recycle-bin',
+ },
+};
+
+export const manifests = [workspace];
From d485ac05e94033175dbca5e3c893aee1ef83a54a Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 19:09:27 +0200
Subject: [PATCH 022/280] call delete document end point when deleting a
document
---
.../repository/detail/document-detail.server.data-source.ts | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts
index e8fb1638a3..aa8516e2b5 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts
@@ -199,8 +199,6 @@ export class UmbDocumentServerDataSource implements UmbDetailDataSource
Date: Tue, 2 Apr 2024 19:09:45 +0200
Subject: [PATCH 023/280] add delete entity action for documents in recycle bin
---
.../documents/entity-actions/manifests.ts | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts
index 7455fc7762..b6d153fe5c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts
@@ -1,12 +1,24 @@
-import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS } from '../repository/index.js';
+import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../repository/index.js';
import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js';
import { UMB_DOCUMENT_PICKER_MODAL } from '../modals/index.js';
+import { UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE } from '../recycle-bin/index.js';
import { manifests as createManifests } from './create/manifests.js';
import { manifests as publicAccessManifests } from './public-access/manifests.js';
import { manifests as cultureAndHostnamesManifests } from './culture-and-hostnames/manifests.js';
import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry';
const entityActions: Array = [
+ {
+ type: 'entityAction',
+ kind: 'delete',
+ alias: 'Umb.EntityAction.Document.Delete',
+ name: 'Delete Document Entity Action',
+ forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE],
+ meta: {
+ detailRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
+ itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
+ },
+ },
{
type: 'entityAction',
kind: 'default',
From ad843fb1b2045b562f8d691ff3e51e5187b0e946 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 19:11:54 +0200
Subject: [PATCH 024/280] move registration to recycle bin
---
.../documents/entity-actions/manifests.ts | 14 +-------------
.../recycle-bin/entity-action/manifests.ts | 14 +++++++++++++-
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts
index b6d153fe5c..7455fc7762 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts
@@ -1,24 +1,12 @@
-import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../repository/index.js';
+import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS } from '../repository/index.js';
import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js';
import { UMB_DOCUMENT_PICKER_MODAL } from '../modals/index.js';
-import { UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE } from '../recycle-bin/index.js';
import { manifests as createManifests } from './create/manifests.js';
import { manifests as publicAccessManifests } from './public-access/manifests.js';
import { manifests as cultureAndHostnamesManifests } from './culture-and-hostnames/manifests.js';
import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry';
const entityActions: Array = [
- {
- type: 'entityAction',
- kind: 'delete',
- alias: 'Umb.EntityAction.Document.Delete',
- name: 'Delete Document Entity Action',
- forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE],
- meta: {
- detailRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
- itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
- },
- },
{
type: 'entityAction',
kind: 'default',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
index d665404052..4dad984bbc 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
@@ -1,6 +1,7 @@
import { UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from '../repository/index.js';
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
-import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
+import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
+import { UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE } from '../entity.js';
export const manifests = [
{
@@ -14,4 +15,15 @@ export const manifests = [
recycleBinRepositoryAlias: UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
},
},
+ {
+ type: 'entityAction',
+ kind: 'delete',
+ alias: 'Umb.EntityAction.Document.Delete',
+ name: 'Delete Document Entity Action',
+ forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE],
+ meta: {
+ itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
+ detailRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
+ },
+ },
];
From 19fdafa852a83329e4b93fd3b384574bc458232c Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 19:14:38 +0200
Subject: [PATCH 025/280] explicit naming
---
.../recycle-bin/entity-action/manifests.ts | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
index 4dad984bbc..5ff1a0ed33 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
@@ -7,7 +7,7 @@ export const manifests = [
{
type: 'entityAction',
kind: 'trash',
- alias: 'Umb.EntityAction.Document.Trash',
+ alias: 'Umb.EntityAction.Document.RecycleBin.Trash',
name: 'Trash Document Entity Action',
forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE],
meta: {
@@ -18,8 +18,19 @@ export const manifests = [
{
type: 'entityAction',
kind: 'delete',
- alias: 'Umb.EntityAction.Document.Delete',
- name: 'Delete Document Entity Action',
+ alias: 'Umb.EntityAction.Document.RecycleBin.Delete',
+ name: 'Delete Document From Recycle Bin Entity Action',
+ forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE],
+ meta: {
+ itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
+ detailRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
+ },
+ },
+ {
+ type: 'entityAction',
+ kind: 'restoreFromRecycleBin',
+ alias: 'Umb.EntityAction.Document.RecycleBin.Restore',
+ name: 'Restore Document From Recycle Bin Entity Action',
forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE],
meta: {
itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
From 86462af1145b76837710a006b7942018ade3ee87 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 20:54:28 +0200
Subject: [PATCH 026/280] add type
---
.../documents/documents/recycle-bin/entity-action/manifests.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
index 5ff1a0ed33..03ba4b98dc 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
@@ -2,8 +2,9 @@ import { UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from '../repository/index.j
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
import { UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE } from '../entity.js';
+import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
-export const manifests = [
+export const manifests: Array = [
{
type: 'entityAction',
kind: 'trash',
From 7b7c3e2d2e417675601489088ddddc76114e5aa4 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 21:03:57 +0200
Subject: [PATCH 027/280] register restore from recycle bin kind
---
.../restore-from-recycle-bin/manifests.ts | 3 +++
.../restore-from-recycle-bin.action.kind.ts | 21 +++++++++++++++++++
.../restore-from-recycle-bin.action.ts | 11 ++++++++++
.../packages/core/entity-action/manifests.ts | 2 ++
.../models/entity-action.model.ts | 13 ++++++++++++
.../core/extension-registry/models/index.ts | 14 +++++++------
6 files changed, 58 insertions(+), 6 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/manifests.ts
new file mode 100644
index 0000000000..6a25de540f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/manifests.ts
@@ -0,0 +1,3 @@
+import { manifest as restoreFromRecycleBinKindManifest } from './restore-from-recycle-bin.action.kind.js';
+
+export const manifests = [restoreFromRecycleBinKindManifest];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts
new file mode 100644
index 0000000000..2ac61e4679
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts
@@ -0,0 +1,21 @@
+import { UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST } from '../../default/default.action.kind.js';
+import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifest: UmbBackofficeManifestKind = {
+ type: 'kind',
+ alias: 'Umb.Kind.EntityAction.RecycleBin.Restore',
+ matchKind: 'restoreFromRecycleBin',
+ matchType: 'entityAction',
+ manifest: {
+ ...UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST.manifest,
+ type: 'entityAction',
+ kind: 'restoreFromRecycleBin',
+ api: () => import('./restore-from-recycle-bin.action.js'),
+ weight: 100,
+ forEntityTypes: [],
+ meta: {
+ icon: 'icon-undo',
+ label: 'Restore...',
+ },
+ },
+};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
new file mode 100644
index 0000000000..5c791ea562
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
@@ -0,0 +1,11 @@
+import { UmbEntityActionBase } from '../../entity-action-base.js';
+import type { MetaEntityActionRestoreFromRecycleBinKind } from '@umbraco-cms/backoffice/extension-registry';
+
+export class UmbRestoreFromRecycleBinEntityAction extends UmbEntityActionBase {
+ async execute() {
+ debugger;
+ console.log(`execute sort for: ${this.args.unique}`);
+ }
+}
+
+export { UmbRestoreFromRecycleBinEntityAction as api };
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts
index dcdfb2d4b3..8d36e21f1a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts
@@ -4,6 +4,7 @@ import { manifests as duplicateEntityActionManifests } from './common/duplicate/
import { manifests as moveEntityActionManifests } from './common/move/manifests.js';
import { manifests as trashEntityActionManifests } from './common/trash/manifests.js';
import { manifests as sortChildrenOfEntityActionManifests } from './common/sort-children-of/manifests.js';
+import { manifests as restoreFromRecycleBinEntityActionManifests } from './common/restore-from-recycle-bin/manifests.js';
export const manifests = [
...defaultEntityActionManifests,
@@ -12,4 +13,5 @@ export const manifests = [
...moveEntityActionManifests,
...trashEntityActionManifests,
...sortChildrenOfEntityActionManifests,
+ ...restoreFromRecycleBinEntityActionManifests,
];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
index ae8066a9ab..7930417432 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
@@ -67,6 +67,19 @@ export interface MetaEntityActionTrashKind extends MetaEntityActionDefaultKind {
itemRepositoryAlias: string;
}
+// RESTORE FROM RECYCLE BIN
+
+export interface ManifestEntityActionRestoreFromRecycleBinKind
+ extends ManifestEntityAction {
+ type: 'entityAction';
+ kind: 'restoreFromRecycleBin';
+}
+
+export interface MetaEntityActionRestoreFromRecycleBinKind extends MetaEntityActionDefaultKind {
+ recycleBinRepositoryAlias: string;
+ itemRepositoryAlias: string;
+}
+
// RENAME
export interface ManifestEntityActionRenameServerFileKind
extends ManifestEntityAction {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts
index df4635f601..2c31df1873 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts
@@ -15,6 +15,7 @@ import type {
ManifestEntityActionDeleteFolderKind,
ManifestEntityActionDefaultKind,
ManifestEntityActionTrashKind,
+ ManifestEntityActionRestoreFromRecycleBinKind,
} from './entity-action.model.js';
import type { ManifestDynamicRootOrigin, ManifestDynamicRootQueryStep } from './dynamic-root.model.js';
import type { ManifestEntityBulkAction } from './entity-bulk-action.model.js';
@@ -105,16 +106,17 @@ export type * from './workspace.model.js';
export type ManifestEntityActions =
| ManifestEntityAction
+ | ManifestEntityActionCreateFolderKind
| ManifestEntityActionDefaultKind
+ | ManifestEntityActionDeleteFolderKind
| ManifestEntityActionDeleteKind
- | ManifestEntityActionRenameServerFileKind
- | ManifestEntityActionReloadTreeItemChildrenKind
| ManifestEntityActionDuplicateKind
| ManifestEntityActionMoveKind
- | ManifestEntityActionCreateFolderKind
- | ManifestEntityActionUpdateFolderKind
- | ManifestEntityActionDeleteFolderKind
- | ManifestEntityActionTrashKind;
+ | ManifestEntityActionReloadTreeItemChildrenKind
+ | ManifestEntityActionRenameServerFileKind
+ | ManifestEntityActionRestoreFromRecycleBinKind
+ | ManifestEntityActionTrashKind
+ | ManifestEntityActionUpdateFolderKind;
export type ManifestWorkspaceFooterApps =
| ManifestWorkspaceFooterApp
From eef66e29148920277efbbdd7c5aae622a4763121 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 21:25:17 +0200
Subject: [PATCH 028/280] register entity action for empty recycle bin
---
.../empty-recycle-bin.action.kind.ts | 21 +++++++++++++++++++
.../empty-recycle-bin.action.ts | 11 ++++++++++
.../common/empty-recycle-bin/manifests.ts | 3 +++
.../core/entity-action/common/index.ts | 3 +++
.../packages/core/entity-action/manifests.ts | 2 ++
.../models/entity-action.model.ts | 11 ++++++++++
.../core/extension-registry/models/index.ts | 2 ++
.../recycle-bin/entity-action/manifests.ts | 16 +++++++++++---
8 files changed, 66 insertions(+), 3 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.kind.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/manifests.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.kind.ts
new file mode 100644
index 0000000000..afa76d64e2
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.kind.ts
@@ -0,0 +1,21 @@
+import { UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST } from '../../default/default.action.kind.js';
+import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifest: UmbBackofficeManifestKind = {
+ type: 'kind',
+ alias: 'Umb.Kind.EntityAction.RecycleBin.Empty',
+ matchKind: 'emptyRecycleBin',
+ matchType: 'entityAction',
+ manifest: {
+ ...UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST.manifest,
+ type: 'entityAction',
+ kind: 'emptyRecycleBin',
+ api: () => import('./empty-recycle-bin.action.js'),
+ weight: 100,
+ forEntityTypes: [],
+ meta: {
+ icon: 'icon-trash',
+ label: 'Empty...',
+ },
+ },
+};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.ts
new file mode 100644
index 0000000000..7e711e2cfc
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.ts
@@ -0,0 +1,11 @@
+import { UmbEntityActionBase } from '../../entity-action-base.js';
+import type { MetaEntityActionEmptyRecycleBinKind } from '@umbraco-cms/backoffice/extension-registry';
+
+export class UmbEmptyRecycleBinEntityAction extends UmbEntityActionBase {
+ async execute() {
+ debugger;
+ console.log(`execute empty for: ${this.args.unique}`);
+ }
+}
+
+export { UmbEmptyRecycleBinEntityAction as api };
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/manifests.ts
new file mode 100644
index 0000000000..89241384bb
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/manifests.ts
@@ -0,0 +1,3 @@
+import { manifest as emptyRecycleBinKindManifest } from './empty-recycle-bin.action.kind.js';
+
+export const manifests = [emptyRecycleBinKindManifest];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts
index b597275cdd..7a060051a3 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts
@@ -3,3 +3,6 @@ export * from './delete/delete.action.js';
export * from './move/move.action.js';
export * from './sort-children-of/sort-children-of.action.js';
export * from './trash/trash.action.js';
+
+export { UmbRestoreFromRecycleBinEntityAction } from './restore-from-recycle-bin/restore-from-recycle-bin.action.js';
+export { UmbEmptyRecycleBinEntityAction } from './empty-recycle-bin/empty-recycle-bin.action.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts
index 8d36e21f1a..1d4111b74e 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts
@@ -5,6 +5,7 @@ import { manifests as moveEntityActionManifests } from './common/move/manifests.
import { manifests as trashEntityActionManifests } from './common/trash/manifests.js';
import { manifests as sortChildrenOfEntityActionManifests } from './common/sort-children-of/manifests.js';
import { manifests as restoreFromRecycleBinEntityActionManifests } from './common/restore-from-recycle-bin/manifests.js';
+import { manifests as emptyRecycleBinEntityActionManifests } from './common/empty-recycle-bin/manifests.js';
export const manifests = [
...defaultEntityActionManifests,
@@ -14,4 +15,5 @@ export const manifests = [
...trashEntityActionManifests,
...sortChildrenOfEntityActionManifests,
...restoreFromRecycleBinEntityActionManifests,
+ ...emptyRecycleBinEntityActionManifests,
];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
index 7930417432..6a17e1e326 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
@@ -80,6 +80,17 @@ export interface MetaEntityActionRestoreFromRecycleBinKind extends MetaEntityAct
itemRepositoryAlias: string;
}
+// EMPTY RECYCLE BIN
+export interface ManifestEntityActionEmptyRecycleBinKind
+ extends ManifestEntityAction {
+ type: 'entityAction';
+ kind: 'emptyRecycleBin';
+}
+
+export interface MetaEntityActionEmptyRecycleBinKind extends MetaEntityActionDefaultKind {
+ recycleBinRepositoryAlias: string;
+}
+
// RENAME
export interface ManifestEntityActionRenameServerFileKind
extends ManifestEntityAction {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts
index 2c31df1873..2517521319 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts
@@ -16,6 +16,7 @@ import type {
ManifestEntityActionDefaultKind,
ManifestEntityActionTrashKind,
ManifestEntityActionRestoreFromRecycleBinKind,
+ ManifestEntityActionEmptyRecycleBinKind,
} from './entity-action.model.js';
import type { ManifestDynamicRootOrigin, ManifestDynamicRootQueryStep } from './dynamic-root.model.js';
import type { ManifestEntityBulkAction } from './entity-bulk-action.model.js';
@@ -111,6 +112,7 @@ export type ManifestEntityActions =
| ManifestEntityActionDeleteFolderKind
| ManifestEntityActionDeleteKind
| ManifestEntityActionDuplicateKind
+ | ManifestEntityActionEmptyRecycleBinKind
| ManifestEntityActionMoveKind
| ManifestEntityActionReloadTreeItemChildrenKind
| ManifestEntityActionRenameServerFileKind
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
index 03ba4b98dc..e5da085471 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
@@ -1,7 +1,7 @@
import { UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from '../repository/index.js';
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
-import { UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE } from '../entity.js';
+import { UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE, UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../entity.js';
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
export const manifests: Array = [
@@ -24,7 +24,7 @@ export const manifests: Array = [
forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE],
meta: {
itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
- detailRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
+ recycleBinRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
},
},
{
@@ -35,7 +35,17 @@ export const manifests: Array = [
forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE],
meta: {
itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
- detailRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
+ recycleBinRepositoryAlias: UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
+ },
+ },
+ {
+ type: 'entityAction',
+ kind: 'emptyRecycleBin',
+ alias: 'Umb.EntityAction.Document.RecycleBin.Empty',
+ name: 'Empty Document Recycle Bin Entity Action',
+ forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE],
+ meta: {
+ recycleBinRepositoryAlias: UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
},
},
];
From 02140ce0c650d1033ad617172227418bc787f3ee Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 21:34:47 +0200
Subject: [PATCH 029/280] simplify method names
---
.../empty-recycle-bin.action.kind.ts | 2 +-
.../empty-recycle-bin.action.ts | 27 ++++++++++++++++---
.../document-recycle-bin.repository.ts | 10 +++----
...document-recycle-bin.server.data-source.ts | 4 +--
4 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.kind.ts
index afa76d64e2..bfba1de2a0 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.kind.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.kind.ts
@@ -15,7 +15,7 @@ export const manifest: UmbBackofficeManifestKind = {
forEntityTypes: [],
meta: {
icon: 'icon-trash',
- label: 'Empty...',
+ label: 'Empty Recycle Bin...',
},
},
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.ts
index 7e711e2cfc..f095c0fbe8 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.ts
@@ -1,10 +1,31 @@
import { UmbEntityActionBase } from '../../entity-action-base.js';
-import type { MetaEntityActionEmptyRecycleBinKind } from '@umbraco-cms/backoffice/extension-registry';
+import { UmbRequestReloadStructureForEntityEvent } from '../../request-reload-structure-for-entity.event.js';
+import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
+import {
+ createExtensionApiByAlias,
+ type MetaEntityActionEmptyRecycleBinKind,
+} from '@umbraco-cms/backoffice/extension-registry';
+import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
export class UmbEmptyRecycleBinEntityAction extends UmbEntityActionBase {
async execute() {
- debugger;
- console.log(`execute empty for: ${this.args.unique}`);
+ await umbConfirmModal(this._host, {
+ headline: `Empty Recycle Bin`,
+ content: `When items are deleted from the recycle bin, they will be gone forever.`,
+ color: 'danger',
+ confirmLabel: 'Empty Recycle Bin',
+ });
+
+ const recycleBinRepository = await createExtensionApiByAlias(this, this.args.meta.recycleBinRepositoryAlias);
+ await recycleBinRepository.requestEmpty();
+
+ const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT);
+ const event = new UmbRequestReloadStructureForEntityEvent({
+ unique: this.args.unique,
+ entityType: this.args.entityType,
+ });
+
+ actionEventContext.dispatchEvent(event);
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts
index 44a4f60478..44759d1e75 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts
@@ -10,19 +10,19 @@ export class UmbDocumentRecycleBinRepository extends UmbRepositoryBase {
this.#recycleBinSource = new UmbDocumentRecycleBinServerDataSource(this);
}
- async requestTrash(args) {
+ async requestTrash(args: any) {
return this.#recycleBinSource.trash(args);
}
- async requestRestore(args) {
+ async requestRestore(args: any) {
return this.#recycleBinSource.restore(args);
}
- async requestEmptyBin() {
- return this.#recycleBinSource.emptyBin();
+ async requestEmpty() {
+ return this.#recycleBinSource.empty();
}
- async requestOriginalParent(args) {
+ async requestOriginalParent(args: any) {
return this.#recycleBinSource.getOriginalParent(args);
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
index 3e00d33711..2b67253d6c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
@@ -13,11 +13,11 @@ export class UmbDocumentRecycleBinServerDataSource {
return tryExecuteAndNotify(this.#host, DocumentResource.putDocumentByIdMoveToRecycleBin({ id: args.unique }));
}
- async restore(args: { unique: string; target: { unique: string | null } }) {
+ restore(args: { unique: string; target: { unique: string | null } }) {
return tryExecuteAndNotify(this.#host, DocumentResource.putRecycleBinDocumentByIdRestore({ id: args.unique }));
}
- emptyBin() {
+ empty() {
return tryExecuteAndNotify(this.#host, DocumentResource.deleteRecycleBinDocument());
}
From 755028866bd876b6a3b88cb4304efbd4e3fe405c Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Tue, 2 Apr 2024 21:42:22 +0200
Subject: [PATCH 030/280] export repository response types
---
src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts
index 0002dac5a9..7557680428 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts
@@ -7,4 +7,4 @@ export * from './detail/index.js';
export type { UmbDataSourceResponse, UmbDataSourceErrorResponse } from './data-source-response.interface.js';
export type { UmbMoveDataSource, UmbMoveRepository } from './move/index.js';
export type { UmbDuplicateDataSource, UmbDuplicateRepository } from './duplicate/index.js';
-export type { UmbPagedModel } from './types.js';
+export type { UmbPagedModel, UmbRepositoryResponse, UmbRepositoryErrorResponse } from './types.js';
From 89c8bf7a5a053d38c063a6748f26e7aa001b7480 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 08:53:39 +0200
Subject: [PATCH 031/280] add recycle bin core module
---
src/Umbraco.Web.UI.Client/package.json | 1 +
src/Umbraco.Web.UI.Client/tsconfig.json | 1 +
2 files changed, 2 insertions(+)
diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json
index b8c968c82c..ce6aa21b9a 100644
--- a/src/Umbraco.Web.UI.Client/package.json
+++ b/src/Umbraco.Web.UI.Client/package.json
@@ -61,6 +61,7 @@
"./property-action": "./dist-cms/packages/core/property-action/index.js",
"./property-editor": "./dist-cms/packages/core/property-editor/index.js",
"./property": "./dist-cms/packages/core/property/index.js",
+ "./recycle-bin": "./dist-cms/packages/core/recycle-bin/index.js",
"./relation-type": "./dist-cms/packages/relations/relation-types/index.js",
"./relations": "./dist-cms/packages/relations/relations/index.js",
"./repository": "./dist-cms/packages/core/repository/index.js",
diff --git a/src/Umbraco.Web.UI.Client/tsconfig.json b/src/Umbraco.Web.UI.Client/tsconfig.json
index 33bf53145e..1ef7e39c5b 100644
--- a/src/Umbraco.Web.UI.Client/tsconfig.json
+++ b/src/Umbraco.Web.UI.Client/tsconfig.json
@@ -79,6 +79,7 @@
"@umbraco-cms/backoffice/property-action": ["./src/packages/core/property-action/index.ts"],
"@umbraco-cms/backoffice/property-editor": ["./src/packages/core/property-editor/index.ts"],
"@umbraco-cms/backoffice/property": ["./src/packages/core/property/index.ts"],
+ "@umbraco-cms/backoffice/recycle-bin": ["./src/packages/core/recycle-bin/index.ts"],
"@umbraco-cms/backoffice/relation-type": ["./src/packages/relations/relation-types/index.ts"],
"@umbraco-cms/backoffice/relations": ["./src/packages/relations/relations/index.ts"],
"@umbraco-cms/backoffice/repository": ["./src/packages/core/repository/index.ts"],
From 95bd7beedfdcbc2ad023b8a5fc25b5e4b5962861 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 08:54:00 +0200
Subject: [PATCH 032/280] add interface + repo base
---
.../src/packages/core/recycle-bin/index.ts | 4 ++
.../recycle-bin-data-source.interface.ts | 12 +++++
.../recycle-bin-repository-base.ts | 53 +++++++++++++++++++
.../recycle-bin-repository.interface.ts | 9 ++++
4 files changed, 78 insertions(+)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-data-source.interface.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository-base.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository.interface.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/index.ts
new file mode 100644
index 0000000000..bae80c5872
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/index.ts
@@ -0,0 +1,4 @@
+export { UmbRecycleBinRepositoryBase } from './recycle-bin-repository-base.js';
+
+export type { UmbRecycleBinDataSource } from './recycle-bin-data-source.interface.js';
+export type { UmbRecycleBinRepository } from './recycle-bin-repository.interface.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-data-source.interface.ts
new file mode 100644
index 0000000000..1781308748
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-data-source.interface.ts
@@ -0,0 +1,12 @@
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';
+
+export interface UmbRecycleBinDataSourceConstructor {
+ new (host: UmbControllerHost): UmbRecycleBinDataSource;
+}
+
+export interface UmbRecycleBinDataSource {
+ trash(args: any): Promise;
+ restore(args: any): Promise;
+ empty(): Promise;
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository-base.ts
new file mode 100644
index 0000000000..01483486e9
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository-base.ts
@@ -0,0 +1,53 @@
+import type { UmbRecycleBinRepository } from './recycle-bin-repository.interface.js';
+import type {
+ UmbRecycleBinDataSource,
+ UmbRecycleBinDataSourceConstructor,
+} from './recycle-bin-data-source.interface.js';
+import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository';
+
+export abstract class UmbRecycleBinRepositoryBase extends UmbRepositoryBase implements UmbRecycleBinRepository {
+ #recycleBinSource: UmbRecycleBinDataSource;
+
+ constructor(host: UmbControllerHost, recycleBinSource: UmbRecycleBinDataSourceConstructor) {
+ super(host);
+ this.#recycleBinSource = new recycleBinSource(this);
+ }
+
+ async requestTrash(args: any) {
+ const { error } = await this.#recycleBinSource.trash(args);
+
+ if (!error) {
+ const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT);
+ const notification = { data: { message: `Trashed` } };
+ notificationContext.peek('positive', notification);
+ }
+
+ return { error };
+ }
+
+ async requestRestore(args: any) {
+ const { error } = await this.#recycleBinSource.restore(args);
+
+ if (!error) {
+ const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT);
+ const notification = { data: { message: `Restored` } };
+ notificationContext.peek('positive', notification);
+ }
+
+ return { error };
+ }
+
+ async requestEmpty() {
+ const { error } = await this.#recycleBinSource.empty();
+
+ if (!error) {
+ const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT);
+ const notification = { data: { message: `Recycle Bin Emptied` } };
+ notificationContext.peek('positive', notification);
+ }
+
+ return this.#recycleBinSource.empty();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository.interface.ts
new file mode 100644
index 0000000000..bda95673f6
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository.interface.ts
@@ -0,0 +1,9 @@
+import type { UmbRepositoryBase } from '../repository/repository-base.js';
+import type { UmbRepositoryErrorResponse } from '@umbraco-cms/backoffice/repository';
+import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
+
+export interface UmbRecycleBinRepository extends UmbRepositoryBase, UmbApi {
+ requestTrash(args: any): Promise;
+ requestRestore(args: any): Promise;
+ requestEmpty(): Promise;
+}
From d8e10b055b38b9156e8a53e66b5aaf4f68ecb101 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 08:55:21 +0200
Subject: [PATCH 033/280] extend recycle bin repo base
---
.../document-recycle-bin.repository.ts | 25 +++----------------
1 file changed, 3 insertions(+), 22 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts
index 44759d1e75..2a33cafed8 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts
@@ -1,29 +1,10 @@
+import { UmbRecycleBinRepositoryBase } from '@umbraco-cms/backoffice/recycle-bin';
import { UmbDocumentRecycleBinServerDataSource } from './document-recycle-bin.server.data-source.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
-import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository';
-
-export class UmbDocumentRecycleBinRepository extends UmbRepositoryBase {
- #recycleBinSource: UmbDocumentRecycleBinServerDataSource;
+export class UmbDocumentRecycleBinRepository extends UmbRecycleBinRepositoryBase {
constructor(host: UmbControllerHost) {
- super(host);
- this.#recycleBinSource = new UmbDocumentRecycleBinServerDataSource(this);
- }
-
- async requestTrash(args: any) {
- return this.#recycleBinSource.trash(args);
- }
-
- async requestRestore(args: any) {
- return this.#recycleBinSource.restore(args);
- }
-
- async requestEmpty() {
- return this.#recycleBinSource.empty();
- }
-
- async requestOriginalParent(args: any) {
- return this.#recycleBinSource.getOriginalParent(args);
+ super(host, UmbDocumentRecycleBinServerDataSource);
}
}
From 66bb43438b562c77259cb19508d35473ab58d248 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 08:55:47 +0200
Subject: [PATCH 034/280] remove method from source
---
...document-recycle-bin.server.data-source.ts | 20 ++-----------------
1 file changed, 2 insertions(+), 18 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
index 2b67253d6c..2b4585adff 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
@@ -1,8 +1,9 @@
+import type { UmbRecycleBinDataSource } from '@umbraco-cms/backoffice/recycle-bin';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { DocumentResource } from '@umbraco-cms/backoffice/external/backend-api';
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
-export class UmbDocumentRecycleBinServerDataSource {
+export class UmbDocumentRecycleBinServerDataSource implements UmbRecycleBinDataSource {
#host: UmbControllerHost;
constructor(host: UmbControllerHost) {
@@ -20,21 +21,4 @@ export class UmbDocumentRecycleBinServerDataSource {
empty() {
return tryExecuteAndNotify(this.#host, DocumentResource.deleteRecycleBinDocument());
}
-
- async getOriginalParent(args: { unique: string }) {
- const { data, error } = await tryExecuteAndNotify(
- this.#host,
- DocumentResource.getRecycleBinDocumentByIdOriginalParent({ id: args.unique }),
- );
-
- if (data) {
- const mappedData = {
- unique: data.id,
- };
-
- return { data: mappedData };
- }
-
- return { error };
- }
}
From 38883fd18009b12ee781a24705f605f6f443fcec Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Wed, 3 Apr 2024 09:16:21 +0200
Subject: [PATCH 035/280] init
---
.../core/modal/component/modal.element.ts | 1 +
.../core/modal/context/modal.context.ts | 4 +
.../documents/documents/modals/manifests.ts | 7 ++
.../documents/modals/rollback/index.ts | 1 +
.../modals/rollback/rollback-modal.element.ts | 86 +++++++++++++++++++
.../modals/rollback/rollback-modal.token.ts | 15 ++++
...ent-workspace-view-info-history.element.ts | 22 ++++-
7 files changed, 135 insertions(+), 1 deletion(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.token.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/component/modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/component/modal.element.ts
index b5a431d7cc..296061dbee 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/component/modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/component/modal.element.ts
@@ -102,6 +102,7 @@ export class UmbModalElement extends UmbLitElement {
}
#createContainerElement() {
+ console.log('Creating modal element', this.#modalContext);
return this.#modalContext!.type === 'sidebar' ? this.#createSidebarElement() : this.#createDialogElement();
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts
index a22c2dd674..386cfb7a77 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts
@@ -48,9 +48,13 @@ export class UmbModalContext = [
+ {
+ type: 'modal',
+ alias: UMB_ROLLBACK_MODAL_ALIAS,
+ name: 'Rollback Modal',
+ js: () => import('./rollback/rollback-modal.element.js'),
+ },
{
type: 'modal',
alias: UMB_DOCUMENT_SAVE_MODAL_ALIAS,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/index.ts
new file mode 100644
index 0000000000..fd0f63b2c3
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/index.ts
@@ -0,0 +1 @@
+export * from './rollback-modal.token.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
new file mode 100644
index 0000000000..9f707a7fb4
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
@@ -0,0 +1,86 @@
+import type { UmbRollbackModalData, UmbRollbackModalValue } from './rollback-modal.token.js';
+import { css, customElement, html, state } from '@umbraco-cms/backoffice/external/lit';
+import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
+import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
+
+import '../shared/document-variant-language-picker.element.js';
+
+@customElement('umb-rollback-modal')
+export class UmbRollbackModalElement extends UmbModalBaseElement {
+ #onRollback() {
+ console.log('Rollback');
+ return;
+ this.modalContext?.submit();
+ }
+
+ #onCancel() {
+ this.modalContext?.reject();
+ }
+
+ #renderRollbackItem() {
+ return html`
+
+
+
+
April 2, 2024 6:05 PM
+
Jesper
+
Current published version
+
+ Prevent cleanup
+
+
+ `;
+ }
+
+ render() {
+ return html`
+
+
+ ${this.#renderRollbackItem()}
+
+
+
+ `;
+ }
+
+ static styles = [
+ UmbTextStyles,
+ css`
+ .rollback-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: var(--uui-size-space-5);
+ }
+ .rollback-item p {
+ margin: 0;
+ opacity: 0.5;
+ }
+ .rollback-item-date {
+ opacity: 1;
+ }
+ #main {
+ display: flex;
+ gap: var(--uui-size-space-4);
+ width: 100%;
+ }
+
+ #box-left {
+ max-width: 500px;
+ flex: 1;
+ }
+
+ #box-right {
+ flex: 1;
+ }
+ `,
+ ];
+}
+
+export default UmbRollbackModalElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-rollback-modal': UmbRollbackModalElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.token.ts
new file mode 100644
index 0000000000..a6174f17e7
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.token.ts
@@ -0,0 +1,15 @@
+import { UMB_ROLLBACK_MODAL_ALIAS } from '../manifests.js';
+import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
+
+export interface UmbRollbackModalData {}
+export interface UmbRollbackModalValue {}
+
+export const UMB_ROLLBACK_MODAL = new UmbModalToken(
+ UMB_ROLLBACK_MODAL_ALIAS,
+ {
+ modal: {
+ type: 'sidebar',
+ size: 'full',
+ },
+ },
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts
index 600d06260f..99adb3e5f6 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts
@@ -15,11 +15,15 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import type { AuditLogWithUsernameResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { DirectionModel } from '@umbraco-cms/backoffice/external/backend-api';
+import { UMB_MODAL_MANAGER_CONTEXT, type UmbModalManagerContext } from '@umbraco-cms/backoffice/modal';
+import { UMB_ROLLBACK_MODAL_ALIAS } from '../../../modals/manifests.js';
+import { UMB_ROLLBACK_MODAL } from '../../../modals/rollback/index.js';
@customElement('umb-document-workspace-view-info-history')
export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement {
#logRepository: UmbAuditLogRepository;
#itemsPerPage = 10;
+ #modalContext?: UmbModalManagerContext;
@property()
documentUnique = '';
@@ -36,10 +40,16 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement {
constructor() {
super();
this.#logRepository = new UmbAuditLogRepository(this);
+ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => {
+ this.#modalContext = instance;
+ });
}
protected firstUpdated(): void {
this.#getLogs();
+
+ //TODO: REMOVE THIS
+ this.#onRollbackModalOpen();
}
async #getLogs() {
@@ -88,6 +98,16 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement {
this.#getLogs();
}
+ #onRollbackModalOpen = () => {
+ const modalContext = this.#modalContext?.open(this, UMB_ROLLBACK_MODAL, {});
+
+ if (!modalContext) return;
+
+ modalContext.onSubmit().then(() => {
+ console.log('Rollback modal submitted');
+ });
+ };
+
render() {
return html`
@@ -96,7 +116,7 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement {
label=${this.localize.term('actions_rollback')}
look="secondary"
slot="actions"
- @click=${() => alert('TODO: Rollback Modal')}>
+ @click=${this.#onRollbackModalOpen}>
From 6a2aa103fa530e62de30673c80ca13b1ec404a85 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 11:03:39 +0200
Subject: [PATCH 036/280] use document entity type for recycle bin items
---
.../documents/entity-actions/manifests.ts | 13 +++++-
.../recycle-bin/entity-action/manifests.ts | 15 +------
.../documents/documents/recycle-bin/entity.ts | 1 -
.../documents/recycle-bin/manifests.ts | 9 +---
.../recycle-bin/menu-item/manifests.ts | 5 ++-
.../documents/recycle-bin/tree/constants.ts | 3 ++
...ent-recycle-bin-tree.server.data-source.ts | 21 ++++++++-
.../documents/recycle-bin/tree/index.ts | 2 +-
.../documents/recycle-bin/tree/manifests.ts | 17 +++----
.../reload-tree-item-children/manifests.ts | 4 +-
.../documents/recycle-bin/tree/types.ts | 5 ++-
.../recycle-bin/workspace/constants.ts | 1 -
...nt-recycle-bin-workspace-editor.element.ts | 45 -------------------
...ent-recycle-bin-workspace.context-token.ts | 12 -----
.../document-recycle-bin-workspace.context.ts | 34 --------------
.../documents/recycle-bin/workspace/index.ts | 1 -
.../recycle-bin/workspace/manifests.ts | 14 ------
17 files changed, 55 insertions(+), 147 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/constants.ts
delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/constants.ts
delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace-editor.element.ts
delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context-token.ts
delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context.ts
delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/index.ts
delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/manifests.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts
index 7455fc7762..a2f1beea81 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts
@@ -1,4 +1,4 @@
-import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS } from '../repository/index.js';
+import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../repository/index.js';
import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js';
import { UMB_DOCUMENT_PICKER_MODAL } from '../modals/index.js';
import { manifests as createManifests } from './create/manifests.js';
@@ -7,6 +7,17 @@ import { manifests as cultureAndHostnamesManifests } from './culture-and-hostnam
import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry';
const entityActions: Array = [
+ {
+ type: 'entityAction',
+ kind: 'delete',
+ alias: 'Umb.EntityAction.Document.Delete',
+ name: 'Delete Document Entity Action',
+ forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE],
+ meta: {
+ itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
+ detailRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
+ },
+ },
{
type: 'entityAction',
kind: 'default',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
index e5da085471..41af2a423c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
@@ -1,7 +1,7 @@
import { UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from '../repository/index.js';
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
-import { UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE, UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../entity.js';
+import { UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../entity.js';
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
export const manifests: Array = [
@@ -16,23 +16,12 @@ export const manifests: Array = [
recycleBinRepositoryAlias: UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
},
},
- {
- type: 'entityAction',
- kind: 'delete',
- alias: 'Umb.EntityAction.Document.RecycleBin.Delete',
- name: 'Delete Document From Recycle Bin Entity Action',
- forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE],
- meta: {
- itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
- recycleBinRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
- },
- },
{
type: 'entityAction',
kind: 'restoreFromRecycleBin',
alias: 'Umb.EntityAction.Document.RecycleBin.Restore',
name: 'Restore Document From Recycle Bin Entity Action',
- forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE],
+ forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE],
meta: {
itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
recycleBinRepositoryAlias: UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity.ts
index 5751458ba0..1e39a86afa 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity.ts
@@ -1,2 +1 @@
export const UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE = 'document-recycle-bin-root';
-export const UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE = 'document-recycle-bin';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts
index 96b9d4b78a..423a1afcc2 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts
@@ -2,12 +2,5 @@ import { manifests as entityActionManifests } from './entity-action/manifests.js
import { manifests as menuItemManifests } from './menu-item/manifests.js';
import { manifests as repositoryManifests } from './repository/manifests.js';
import { manifests as treeManifests } from './tree/manifests.js';
-import { manifests as workspaceManifests } from './workspace/manifests.js';
-export const manifests = [
- ...entityActionManifests,
- ...menuItemManifests,
- ...repositoryManifests,
- ...treeManifests,
- ...workspaceManifests,
-];
+export const manifests = [...entityActionManifests, ...menuItemManifests, ...repositoryManifests, ...treeManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu-item/manifests.ts
index 60699a97fa..418ed9c109 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu-item/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu-item/manifests.ts
@@ -1,14 +1,15 @@
import { UMB_CONTENT_MENU_ALIAS } from '../../menu/manifests.js';
+import { UMB_DOCUMENT_RECYCLE_BIN_TREE_ALIAS } from '../tree/index.js';
import type { ManifestMenuItemTreeKind } from '@umbraco-cms/backoffice/extension-registry';
const menuItem: ManifestMenuItemTreeKind = {
type: 'menuItem',
kind: 'tree',
- alias: 'Umb.MenuItem.DocumentRecycleBin',
+ alias: 'Umb.MenuItem.Document.RecycleBin',
name: 'Document Recycle Bin Menu Item',
weight: 100,
meta: {
- treeAlias: 'Umb.Tree.DocumentRecycleBin',
+ treeAlias: UMB_DOCUMENT_RECYCLE_BIN_TREE_ALIAS,
label: 'Recycle Bin',
icon: 'icon-trash',
menus: [UMB_CONTENT_MENU_ALIAS],
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/constants.ts
new file mode 100644
index 0000000000..492e6f36ed
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/constants.ts
@@ -0,0 +1,3 @@
+export const UMB_DOCUMENT_RECYCLE_BIN_TREE_REPOSITORY_ALIAS = 'Umb.Repository.Document.RecycleBin.Tree';
+export const UMB_DOCUMENT_RECYCLE_BIN_TREE_STORE_ALIAS = 'Umb.Store.Document.RecycleBin.Tree';
+export const UMB_DOCUMENT_RECYCLE_BIN_TREE_ALIAS = 'Umb.Tree.Document.RecycleBin';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/document-recycle-bin-tree.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/document-recycle-bin-tree.server.data-source.ts
index d5a1ee2f36..4fa19adbd0 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/document-recycle-bin-tree.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/document-recycle-bin-tree.server.data-source.ts
@@ -1,3 +1,4 @@
+import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
import type { UmbDocumentRecycleBinTreeItemModel } from './types.js';
import type { DocumentRecycleBinItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import { DocumentResource } from '@umbraco-cms/backoffice/external/backend-api';
@@ -61,9 +62,25 @@ const mapper = (item: DocumentRecycleBinItemResponseModel): UmbDocumentRecycleBi
return {
unique: item.id,
parentUnique: item.parent ? item.parent.id : null,
- entityType: 'document-recycle-bin',
+ entityType: UMB_DOCUMENT_ENTITY_TYPE,
+ noAccess: false,
+ isTrashed: true,
hasChildren: item.hasChildren,
- isFolder: false,
+ isProtected: false,
+ documentType: {
+ unique: item.documentType.id,
+ icon: item.documentType.icon,
+ collection: item.documentType.collection ? { unique: item.documentType.collection.id } : null,
+ },
+ variants: item.variants.map((variant) => {
+ return {
+ name: variant.name,
+ culture: variant.culture || null,
+ segment: null, // TODO: add segment to the backend API?
+ state: variant.state,
+ };
+ }),
name: item.variants[0]?.name, // TODO: this is not correct. We need to get it from the variants. This is a temp solution.
+ isFolder: false,
};
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/index.ts
index 995f0b5ebf..1c6d9bc43c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/index.ts
@@ -3,7 +3,7 @@ export {
UMB_DOCUMENT_RECYCLE_BIN_TREE_REPOSITORY_ALIAS,
UMB_DOCUMENT_RECYCLE_BIN_TREE_STORE_ALIAS,
UMB_DOCUMENT_RECYCLE_BIN_TREE_ALIAS,
-} from './manifests.js';
+} from './constants.js';
export { UMB_DOCUMENT_RECYCLE_BIN_TREE_STORE_CONTEXT } from './document-recycle-bin-tree.store.js';
export { type UmbDocumentRecycleBinTreeStore } from './document-recycle-bin-tree.store.js';
export * from './types.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/manifests.ts
index 0b7795f149..69c76b9235 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/manifests.ts
@@ -1,4 +1,9 @@
-import { UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE, UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../entity.js';
+import { UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../entity.js';
+import {
+ UMB_DOCUMENT_RECYCLE_BIN_TREE_ALIAS,
+ UMB_DOCUMENT_RECYCLE_BIN_TREE_REPOSITORY_ALIAS,
+ UMB_DOCUMENT_RECYCLE_BIN_TREE_STORE_ALIAS,
+} from './constants.js';
import { UmbDocumentRecycleBinTreeRepository } from './document-recycle-bin-tree.repository.js';
import { UmbDocumentRecycleBinTreeStore } from './document-recycle-bin-tree.store.js';
import { manifests as reloadTreeItemChildrenManifests } from './reload-tree-item-children/manifests.js';
@@ -9,10 +14,6 @@ import type {
ManifestTreeStore,
} from '@umbraco-cms/backoffice/extension-registry';
-export const UMB_DOCUMENT_RECYCLE_BIN_TREE_REPOSITORY_ALIAS = 'Umb.Repository.DocumentRecycleBin.Tree';
-export const UMB_DOCUMENT_RECYCLE_BIN_TREE_STORE_ALIAS = 'Umb.Store.DocumentRecycleBin.Tree';
-export const UMB_DOCUMENT_RECYCLE_BIN_TREE_ALIAS = 'Umb.Tree.DocumentRecycleBin';
-
const treeRepository: ManifestRepository = {
type: 'repository',
alias: UMB_DOCUMENT_RECYCLE_BIN_TREE_REPOSITORY_ALIAS,
@@ -40,9 +41,9 @@ const tree: ManifestTree = {
const treeItem: ManifestTreeItem = {
type: 'treeItem',
kind: 'default',
- alias: 'Umb.TreeItem.DocumentRecycleBin',
- name: 'DocumentRecycleBin Tree Item',
- forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE, UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE],
+ alias: 'Umb.TreeItem.Document.RecycleBin',
+ name: 'Document Recycle Bin Tree Item',
+ forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE],
};
export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadTreeItemChildrenManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/reload-tree-item-children/manifests.ts
index 9b90625f81..35463faee4 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/reload-tree-item-children/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/reload-tree-item-children/manifests.ts
@@ -1,4 +1,4 @@
-import { UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE, UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../../entity.js';
+import { UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../../entity.js';
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
export const manifests: Array = [
@@ -7,6 +7,6 @@ export const manifests: Array = [
kind: 'reloadTreeItemChildren',
alias: 'Umb.EntityAction.DocumentRecycleBin.Tree.ReloadChildrenOf',
name: 'Reload Document Recycle Bin Tree Item Children Entity Action',
- forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE, UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE],
+ forEntityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE],
},
];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/types.ts
index 5c67491e8e..d84c7821f1 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/types.ts
@@ -1,5 +1,6 @@
-import type { UmbUniqueTreeItemModel, UmbUniqueTreeRootModel } from '@umbraco-cms/backoffice/tree';
+import type { UmbDocumentTreeItemModel } from '../../tree/index.js';
+import type { UmbUniqueTreeRootModel } from '@umbraco-cms/backoffice/tree';
-export interface UmbDocumentRecycleBinTreeItemModel extends UmbUniqueTreeItemModel {}
+export interface UmbDocumentRecycleBinTreeItemModel extends UmbDocumentTreeItemModel {}
export interface UmbDocumentRecycleBinTreeRootModel extends UmbUniqueTreeRootModel {}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/constants.ts
deleted file mode 100644
index 61e0e19e34..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/constants.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_ALIAS = 'Umb.Workspace.Document.RecycleBin';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace-editor.element.ts
deleted file mode 100644
index 7477cf00d0..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace-editor.element.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_CONTEXT } from './document-recycle-bin-workspace.context-token.js';
-import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
-import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
-import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry';
-
-const elementName = 'umb-document-recycle-bin-editor';
-
-@customElement(elementName)
-export class UmbDocumentRecycleBinWorkspaceEditorElement extends UmbLitElement {
- @property({ attribute: false })
- manifest?: ManifestWorkspace;
-
- #workspaceContext?: typeof UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_CONTEXT.TYPE;
-
- constructor() {
- super();
-
- this.consumeContext(UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_CONTEXT, (workspaceContext) => {
- this.#workspaceContext = workspaceContext;
- debugger;
- });
- }
-
- render() {
- return html`Document Recycle Bin
`;
- }
-
- static styles = [
- css`
- :host {
- display: block;
- width: 100%;
- height: 100%;
- }
- `,
- ];
-}
-
-export { UmbDocumentRecycleBinWorkspaceEditorElement as element };
-
-declare global {
- interface HTMLElementTagNameMap {
- [elementName]: UmbDocumentRecycleBinWorkspaceEditorElement;
- }
-}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context-token.ts
deleted file mode 100644
index 51b8c272eb..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context-token.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { UmbDocumentRecycleBinWorkspaceContext } from './document-recycle-bin-workspace.context.js';
-import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
-import type { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
-
-export const UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_CONTEXT = new UmbContextToken<
- UmbWorkspaceContext,
- UmbDocumentRecycleBinWorkspaceContext
->(
- 'UmbWorkspaceContext',
- undefined,
- (context): context is UmbDocumentRecycleBinWorkspaceContext => context.getEntityType?.() === 'document-recycle-bin',
-);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context.ts
deleted file mode 100644
index 65163ed83f..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/document-recycle-bin-workspace.context.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_ALIAS } from './constants.js';
-import { UmbDocumentRecycleBinWorkspaceEditorElement } from './document-recycle-bin-workspace-editor.element.js';
-import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
-import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
-import type { UmbRoutableWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
-import { UmbWorkspaceRouteManager } from '@umbraco-cms/backoffice/workspace';
-
-export class UmbDocumentRecycleBinWorkspaceContext extends UmbControllerBase implements UmbRoutableWorkspaceContext {
- public readonly workspaceAlias = UMB_DOCUMENT_RECYCLE_BIN_WORKSPACE_ALIAS;
- public readonly routes = new UmbWorkspaceRouteManager(this);
-
- constructor(host: UmbControllerHost) {
- super(host, 'Umb.Workspace.Document.RecycleBin');
-
- this.routes.setRoutes([
- {
- path: 'edit/:unique',
- component: UmbDocumentRecycleBinWorkspaceEditorElement,
- setup: (_component, info) => {
- const unique = info.match.params.unique;
- console.log('unique', unique);
- },
- },
- ]);
- }
-
- getEntityType() {
- return 'document-recycle-bin';
- }
-
- destroy(): void {}
-}
-
-export { UmbDocumentRecycleBinWorkspaceContext as api };
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/index.ts
deleted file mode 100644
index 8b13789179..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/manifests.ts
deleted file mode 100644
index cd04c18b64..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/workspace/manifests.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import type { ManifestWorkspaces } from '@umbraco-cms/backoffice/extension-registry';
-
-const workspace: ManifestWorkspaces = {
- type: 'workspace',
- kind: 'routable',
- alias: 'Umb.Workspace.Document.RecycleBin',
- name: 'Document Recycle Bin Workspace',
- api: () => import('./document-recycle-bin-workspace.context.js'),
- meta: {
- entityType: 'document-recycle-bin',
- },
-};
-
-export const manifests = [workspace];
From fcad6f6cb1bc7ee0a5ac2145c62ceb012d96c19b Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 11:05:43 +0200
Subject: [PATCH 037/280] align delete and trash weights
---
.../core/entity-action/common/delete/delete.action.kind.ts | 2 +-
.../core/entity-action/common/trash/trash.action.kind.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/delete.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/delete.action.kind.ts
index bf2f0136f6..12e5b0c6c1 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/delete.action.kind.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/delete.action.kind.ts
@@ -11,7 +11,7 @@ export const manifest: UmbBackofficeManifestKind = {
type: 'entityAction',
kind: 'delete',
api: () => import('./delete.action.js'),
- weight: 900,
+ weight: 1100,
forEntityTypes: [],
meta: {
icon: 'icon-trash',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.kind.ts
index 53a7273139..317632b65b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.kind.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.kind.ts
@@ -11,7 +11,7 @@ export const manifest: UmbBackofficeManifestKind = {
type: 'entityAction',
kind: 'trash',
api: () => import('./trash.action.js'),
- weight: 1100,
+ weight: 1050,
forEntityTypes: [],
meta: {
icon: 'icon-trash',
From 1cf7b495eb81a9f1fa901cd6908d8490f4db644e Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 12:09:36 +0200
Subject: [PATCH 038/280] move entity actions to recycle bin module
---
.../src/packages/core/entity-action/common/index.ts | 4 ----
.../src/packages/core/entity-action/manifests.ts | 6 ------
.../empty-recycle-bin/empty-recycle-bin.action.kind.ts | 2 +-
.../empty-recycle-bin/empty-recycle-bin.action.ts | 4 ++--
.../entity-action}/empty-recycle-bin/manifests.ts | 0
.../src/packages/core/recycle-bin/entity-action/index.ts | 3 +++
.../entity-action}/restore-from-recycle-bin/manifests.ts | 0
.../restore-from-recycle-bin.action.kind.ts | 2 +-
.../restore-from-recycle-bin.action.ts | 2 +-
.../entity-action}/trash/manifests.ts | 0
.../entity-action}/trash/trash.action.kind.ts | 2 +-
.../entity-action}/trash/trash.action.ts | 4 ++--
.../src/packages/core/recycle-bin/index.ts | 5 +++++
.../src/packages/core/recycle-bin/manifests.ts | 9 +++++++++
14 files changed, 25 insertions(+), 18 deletions(-)
rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common => recycle-bin/entity-action}/empty-recycle-bin/empty-recycle-bin.action.kind.ts (83%)
rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common => recycle-bin/entity-action}/empty-recycle-bin/empty-recycle-bin.action.ts (83%)
rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common => recycle-bin/entity-action}/empty-recycle-bin/manifests.ts (100%)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/index.ts
rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common => recycle-bin/entity-action}/restore-from-recycle-bin/manifests.ts (100%)
rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common => recycle-bin/entity-action}/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts (83%)
rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common => recycle-bin/entity-action}/restore-from-recycle-bin/restore-from-recycle-bin.action.ts (81%)
rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common => recycle-bin/entity-action}/trash/manifests.ts (100%)
rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common => recycle-bin/entity-action}/trash/trash.action.kind.ts (83%)
rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common => recycle-bin/entity-action}/trash/trash.action.ts (88%)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/manifests.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts
index 7a060051a3..005791ff7b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts
@@ -2,7 +2,3 @@ export * from './duplicate/duplicate.action.js';
export * from './delete/delete.action.js';
export * from './move/move.action.js';
export * from './sort-children-of/sort-children-of.action.js';
-export * from './trash/trash.action.js';
-
-export { UmbRestoreFromRecycleBinEntityAction } from './restore-from-recycle-bin/restore-from-recycle-bin.action.js';
-export { UmbEmptyRecycleBinEntityAction } from './empty-recycle-bin/empty-recycle-bin.action.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts
index 1d4111b74e..bbe018524f 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts
@@ -2,18 +2,12 @@ import { manifests as defaultEntityActionManifests } from './default/manifests.j
import { manifests as deleteEntityActionManifests } from './common/delete/manifests.js';
import { manifests as duplicateEntityActionManifests } from './common/duplicate/manifests.js';
import { manifests as moveEntityActionManifests } from './common/move/manifests.js';
-import { manifests as trashEntityActionManifests } from './common/trash/manifests.js';
import { manifests as sortChildrenOfEntityActionManifests } from './common/sort-children-of/manifests.js';
-import { manifests as restoreFromRecycleBinEntityActionManifests } from './common/restore-from-recycle-bin/manifests.js';
-import { manifests as emptyRecycleBinEntityActionManifests } from './common/empty-recycle-bin/manifests.js';
export const manifests = [
...defaultEntityActionManifests,
...deleteEntityActionManifests,
...duplicateEntityActionManifests,
...moveEntityActionManifests,
- ...trashEntityActionManifests,
...sortChildrenOfEntityActionManifests,
- ...restoreFromRecycleBinEntityActionManifests,
- ...emptyRecycleBinEntityActionManifests,
];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.kind.ts
similarity index 83%
rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.kind.ts
rename to src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.kind.ts
index bfba1de2a0..de15a8826a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.kind.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.kind.ts
@@ -1,4 +1,4 @@
-import { UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST } from '../../default/default.action.kind.js';
+import { UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST } from '../../../entity-action/default/default.action.kind.js';
import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry';
export const manifest: UmbBackofficeManifestKind = {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts
similarity index 83%
rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.ts
rename to src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts
index f095c0fbe8..c718739f1b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/empty-recycle-bin.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts
@@ -1,5 +1,5 @@
-import { UmbEntityActionBase } from '../../entity-action-base.js';
-import { UmbRequestReloadStructureForEntityEvent } from '../../request-reload-structure-for-entity.event.js';
+import { UmbEntityActionBase } from '../../../entity-action/entity-action-base.js';
+import { UmbRequestReloadStructureForEntityEvent } from '../../../entity-action/request-reload-structure-for-entity.event.js';
import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
import {
createExtensionApiByAlias,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/manifests.ts
similarity index 100%
rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/empty-recycle-bin/manifests.ts
rename to src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/manifests.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/index.ts
new file mode 100644
index 0000000000..df73603f45
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/index.ts
@@ -0,0 +1,3 @@
+export { UmbTrashEntityAction } from './trash/trash.action.js';
+export { UmbRestoreFromRecycleBinEntityAction } from './restore-from-recycle-bin/restore-from-recycle-bin.action.js';
+export { UmbEmptyRecycleBinEntityAction } from './empty-recycle-bin/empty-recycle-bin.action.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/manifests.ts
similarity index 100%
rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/manifests.ts
rename to src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/manifests.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts
similarity index 83%
rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts
rename to src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts
index 2ac61e4679..3be8eeefcc 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts
@@ -1,4 +1,4 @@
-import { UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST } from '../../default/default.action.kind.js';
+import { UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST } from '../../../entity-action/default/default.action.kind.js';
import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry';
export const manifest: UmbBackofficeManifestKind = {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
similarity index 81%
rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
rename to src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
index 5c791ea562..c15e204383 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
@@ -1,4 +1,4 @@
-import { UmbEntityActionBase } from '../../entity-action-base.js';
+import { UmbEntityActionBase } from '../../../entity-action/entity-action-base.js';
import type { MetaEntityActionRestoreFromRecycleBinKind } from '@umbraco-cms/backoffice/extension-registry';
export class UmbRestoreFromRecycleBinEntityAction extends UmbEntityActionBase {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/manifests.ts
similarity index 100%
rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/manifests.ts
rename to src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/manifests.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.kind.ts
similarity index 83%
rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.kind.ts
rename to src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.kind.ts
index 317632b65b..fa78c1185b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.kind.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.kind.ts
@@ -1,4 +1,4 @@
-import { UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST } from '../../default/default.action.kind.js';
+import { UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST } from '../../../entity-action/default/default.action.kind.js';
import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry';
export const manifest: UmbBackofficeManifestKind = {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts
similarity index 88%
rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts
rename to src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts
index 94e2da1304..09d8f6c08a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts
@@ -1,5 +1,5 @@
-import { UmbEntityActionBase } from '../../entity-action-base.js';
-import { UmbRequestReloadStructureForEntityEvent } from '../../request-reload-structure-for-entity.event.js';
+import { UmbEntityActionBase } from '../../../entity-action/entity-action-base.js';
+import { UmbRequestReloadStructureForEntityEvent } from '../../../entity-action/request-reload-structure-for-entity.event.js';
import type { MetaEntityActionTrashKind } from '@umbraco-cms/backoffice/extension-registry';
import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/index.ts
index bae80c5872..49cec0d017 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/index.ts
@@ -1,4 +1,9 @@
export { UmbRecycleBinRepositoryBase } from './recycle-bin-repository-base.js';
+export {
+ UmbTrashEntityAction,
+ UmbRestoreFromRecycleBinEntityAction,
+ UmbEmptyRecycleBinEntityAction,
+} from './entity-action/index.js';
export type { UmbRecycleBinDataSource } from './recycle-bin-data-source.interface.js';
export type { UmbRecycleBinRepository } from './recycle-bin-repository.interface.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/manifests.ts
new file mode 100644
index 0000000000..49e2d1fd73
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/manifests.ts
@@ -0,0 +1,9 @@
+import { manifests as trashEntityActionManifests } from '../recycle-bin/entity-action/trash/manifests.js';
+import { manifests as restoreFromRecycleBinEntityActionManifests } from '../recycle-bin/entity-action/restore-from-recycle-bin/manifests.js';
+import { manifests as emptyRecycleBinEntityActionManifests } from '../recycle-bin/entity-action/empty-recycle-bin/manifests.js';
+
+export const manifests = [
+ ...trashEntityActionManifests,
+ ...restoreFromRecycleBinEntityActionManifests,
+ ...emptyRecycleBinEntityActionManifests,
+];
From ec2befe77b3db8a9e55ff6e850e8fdd8d622509f Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 12:11:58 +0200
Subject: [PATCH 039/280] register recycle bin manifests
---
src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts
index 66d11f9961..620b0e6c1c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts
@@ -8,6 +8,7 @@ import { manifests as localizationManifests } from './localization/manifests.js'
import { manifests as modalManifests } from './modal/common/manifests.js';
import { manifests as propertyActionManifests } from './property-action/manifests.js';
import { manifests as propertyEditorManifests } from './property-editor/manifests.js';
+import { manifests as recycleBinManifests } from './recycle-bin/manifests.js';
import { manifests as sectionManifests } from './section/manifests.js';
import { manifests as serverFileSystemManifests } from './server-file-system/manifests.js';
import { manifests as settingsManifests } from './settings/manifests.js';
@@ -28,6 +29,7 @@ export const manifests: Array = [
...modalManifests,
...propertyActionManifests,
...propertyEditorManifests,
+ ...recycleBinManifests,
...sectionManifests,
...serverFileSystemManifests,
...settingsManifests,
From 43f91defd7eac67be9293bfef784ca9801c1af6c Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 12:24:36 +0200
Subject: [PATCH 040/280] reload children when recycle bin is emptied
---
.../empty-recycle-bin/empty-recycle-bin.action.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts
index c718739f1b..9c1868b53e 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts
@@ -6,6 +6,7 @@ import {
type MetaEntityActionEmptyRecycleBinKind,
} from '@umbraco-cms/backoffice/extension-registry';
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
+import { UmbReloadTreeItemChildrenRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree';
export class UmbEmptyRecycleBinEntityAction extends UmbEntityActionBase {
async execute() {
@@ -20,7 +21,7 @@ export class UmbEmptyRecycleBinEntityAction extends UmbEntityActionBase
Date: Wed, 3 Apr 2024 12:27:30 +0200
Subject: [PATCH 041/280] set children flag based on server result
---
.../core/tree/tree-item/tree-item-base/tree-item-context-base.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts
index 05ff0d5a58..ac71003504 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts
@@ -171,6 +171,7 @@ export abstract class UmbTreeItemContextBase 0);
this.pagination.setTotalItems(data.total);
}
From c9b117665e355bb715734b3bdb02b14ee89b4460 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 12:28:01 +0200
Subject: [PATCH 042/280] don't observe store for children
---
.../tree-item-base/tree-item-context-base.ts | 27 -------------------
1 file changed, 27 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts
index ac71003504..09e8ce9c90 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts
@@ -41,7 +41,6 @@ export abstract class UmbTreeItemContextBase {
@@ -300,28 +295,6 @@ export abstract class UmbTreeItemContextBase children.length > 0),
- );
-
- // observe if any children will be added runtime to a tree item. Nested items/folders etc.
- this.observe(hasChildrenObservable, (hasChildren) => {
- /* we need to skip the first value, because it will also return false until a child is in the store
- we therefor rely on the value from the tree item itself */
- if (this.#hasChildrenInitValueFlag === true) {
- this.#hasChildren.setValue(hasChildren);
- }
- this.#hasChildrenInitValueFlag = true;
- });
- }
-
#onReloadRequest = (event: UmbEntityActionEvent) => {
if (event.getUnique() !== this.unique) return;
if (event.getEntityType() !== this.entityType) return;
From bdf591ac9c660fd372df10f9d22f3d17e5c5682f Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 12:43:14 +0200
Subject: [PATCH 043/280] remove unused
---
.../documents/documents/recycle-bin/entity-action/manifests.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
index 41af2a423c..1fc4073ffd 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
@@ -1,6 +1,6 @@
import { UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from '../repository/index.js';
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
-import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
+import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
import { UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../entity.js';
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
From 55168364291d7cff654426dda100aefaee7d6227 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 15:29:46 +0200
Subject: [PATCH 044/280] register tree item for document root
---
.../packages/documents/documents/tree/manifests.ts | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/manifests.ts
index 281c0d85a7..5b964c6b94 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/manifests.ts
@@ -42,7 +42,15 @@ const treeItem: ManifestTreeItem = {
name: 'Document Tree Item',
element: () => import('./tree-item/document-tree-item.element.js'),
api: UmbDocumentTreeItemContext,
- forEntityTypes: [UMB_DOCUMENT_ROOT_ENTITY_TYPE, UMB_DOCUMENT_ENTITY_TYPE],
+ forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE],
};
-export const manifests = [...reloadTreeItemChildrenManifests, tree, treeItem, treeRepository, treeStore];
+const rootTreeItem: ManifestTreeItem = {
+ type: 'treeItem',
+ kind: 'default',
+ alias: 'Umb.TreeItem.Document.Root',
+ name: 'Document Tree Item',
+ forEntityTypes: [UMB_DOCUMENT_ROOT_ENTITY_TYPE],
+};
+
+export const manifests = [...reloadTreeItemChildrenManifests, tree, treeItem, rootTreeItem, treeRepository, treeStore];
From 83d7e55ce779d46e600f22a964964d26762219e0 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 16:12:30 +0200
Subject: [PATCH 045/280] add method to get original parent to repo + data
source
---
.../recycle-bin-data-source.interface.ts | 1 +
.../recycle-bin/recycle-bin-repository-base.ts | 4 ++++
.../recycle-bin-repository.interface.ts | 3 ++-
.../document-recycle-bin.server.data-source.ts | 17 +++++++++++++++++
4 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-data-source.interface.ts
index 1781308748..b0de7b0ab9 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-data-source.interface.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-data-source.interface.ts
@@ -9,4 +9,5 @@ export interface UmbRecycleBinDataSource {
trash(args: any): Promise;
restore(args: any): Promise;
empty(): Promise;
+ getOriginalParent(args: any): Promise;
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository-base.ts
index 01483486e9..ac12e66d1c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository-base.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository-base.ts
@@ -50,4 +50,8 @@ export abstract class UmbRecycleBinRepositoryBase extends UmbRepositoryBase impl
return this.#recycleBinSource.empty();
}
+
+ async requestOriginalParent(args: any) {
+ return this.#recycleBinSource.getOriginalParent(args);
+ }
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository.interface.ts
index bda95673f6..cda0a2448a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository.interface.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository.interface.ts
@@ -1,9 +1,10 @@
import type { UmbRepositoryBase } from '../repository/repository-base.js';
-import type { UmbRepositoryErrorResponse } from '@umbraco-cms/backoffice/repository';
+import type { UmbRepositoryErrorResponse, UmbRepositoryResponse } from '@umbraco-cms/backoffice/repository';
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
export interface UmbRecycleBinRepository extends UmbRepositoryBase, UmbApi {
requestTrash(args: any): Promise;
requestRestore(args: any): Promise;
requestEmpty(): Promise;
+ requestOriginalParent(args: any): Promise>;
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
index 2b4585adff..7d59389943 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
@@ -21,4 +21,21 @@ export class UmbDocumentRecycleBinServerDataSource implements UmbRecycleBinDataS
empty() {
return tryExecuteAndNotify(this.#host, DocumentResource.deleteRecycleBinDocument());
}
+
+ async getOriginalParent(args: { unique: string }) {
+ const { data, error } = await tryExecuteAndNotify(
+ this.#host,
+ DocumentResource.getRecycleBinDocumentByIdOriginalParent({ id: args.unique }),
+ );
+
+ if (data) {
+ const mappedData = {
+ unique: data.id,
+ };
+
+ return { data: mappedData };
+ }
+
+ return { error };
+ }
}
From 63dcfa5955482429eb2c3b8f5fcbd3eda9a6f7e3 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 16:12:55 +0200
Subject: [PATCH 046/280] wip restore modal
---
.../models/entity-action.model.ts | 1 +
.../empty-recycle-bin.action.ts | 6 +-
.../restore-from-recycle-bin/manifests.ts | 12 +-
.../restore-from-recycle-bin/modal/index.ts | 2 +
.../restore-from-recycle-bin-modal.element.ts | 123 ++++++++++++++++++
.../restore-from-recycle-bin-modal.token.ts | 25 ++++
.../restore-from-recycle-bin.action.kind.ts | 1 +
.../restore-from-recycle-bin.action.ts | 29 ++++-
.../entity-action/trash/trash.action.ts | 5 +-
.../recycle-bin/entity-action/manifests.ts | 2 +
10 files changed, 200 insertions(+), 6 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
index 6a17e1e326..3be5173679 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
@@ -78,6 +78,7 @@ export interface ManifestEntityActionRestoreFromRecycleBinKind
export interface MetaEntityActionRestoreFromRecycleBinKind extends MetaEntityActionDefaultKind {
recycleBinRepositoryAlias: string;
itemRepositoryAlias: string;
+ pickerModal: UmbModalToken | string;
}
// EMPTY RECYCLE BIN
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts
index 9c1868b53e..d2059161be 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts
@@ -1,5 +1,6 @@
import { UmbEntityActionBase } from '../../../entity-action/entity-action-base.js';
import { UmbRequestReloadStructureForEntityEvent } from '../../../entity-action/request-reload-structure-for-entity.event.js';
+import type { UmbRecycleBinRepository } from '../../recycle-bin-repository.interface.js';
import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
import {
createExtensionApiByAlias,
@@ -17,7 +18,10 @@ export class UmbEmptyRecycleBinEntityAction extends UmbEntityActionBase(this, this.args.meta.recycleBinRepositoryAlias);
+ const recycleBinRepository = await createExtensionApiByAlias(
+ this,
+ this.args.meta.recycleBinRepositoryAlias,
+ );
await recycleBinRepository.requestEmpty();
const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/manifests.ts
index 6a25de540f..09766fef9c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/manifests.ts
@@ -1,3 +1,11 @@
-import { manifest as restoreFromRecycleBinKindManifest } from './restore-from-recycle-bin.action.kind.js';
+import { manifest as kindManifest } from './restore-from-recycle-bin.action.kind.js';
-export const manifests = [restoreFromRecycleBinKindManifest];
+export const manifests = [
+ kindManifest,
+ {
+ type: 'modal',
+ alias: 'Umb.Modal.RecycleBin.Restore',
+ name: 'Restore From Recycle Bin Modal',
+ js: () => import('./modal/restore-from-recycle-bin-modal.element.js'),
+ },
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/index.ts
new file mode 100644
index 0000000000..b4d1511566
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/index.ts
@@ -0,0 +1,2 @@
+export * from './restore-from-recycle-bin-modal.token.js';
+export * from './restore-from-recycle-bin-modal.element.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
new file mode 100644
index 0000000000..85d45dee42
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
@@ -0,0 +1,123 @@
+import type { UmbRecycleBinRepository } from '../../../recycle-bin-repository.interface.js';
+import type {
+ UmbRestoreFromRecycleBinModalData,
+ UmbRestoreFromRecycleBinModalValue,
+} from './restore-from-recycle-bin-modal.token.js';
+import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
+import { html, customElement, state, nothing, css } from '@umbraco-cms/backoffice/external/lit';
+import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
+import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
+import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
+import { UMB_DOCUMENT_PICKER_MODAL } from '@umbraco-cms/backoffice/document';
+import type { UmbItemRepository } from '@umbraco-cms/backoffice/repository';
+
+const elementName = 'umb-restore-from-recycle-bin-modal';
+
+@customElement(elementName)
+export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
+ UmbRestoreFromRecycleBinModalData,
+ UmbRestoreFromRecycleBinModalValue
+> {
+ @state()
+ _customSelectDestination = false;
+
+ @state()
+ _destinationItem: any;
+
+ constructor() {
+ super();
+ }
+
+ protected async firstUpdated(_changedProperties: PropertyValueMap | Map): Promise {
+ super.firstUpdated(_changedProperties);
+
+ const restoreDestination = await this.#requestRestoreDestination();
+
+ if (!restoreDestination) {
+ this._customSelectDestination = true;
+ this.requestUpdate();
+ return;
+ }
+ }
+
+ async #requestRestoreDestination(): Promise {
+ if (!this.data?.unique) throw new Error('Cannot restore an item without a unique identifier.');
+ if (!this.data?.recycleBinRepositoryAlias)
+ throw new Error('Cannot restore an item without a recycle bin repository alias.');
+
+ const recycleBinRepository = await createExtensionApiByAlias(
+ this,
+ this.data.recycleBinRepositoryAlias,
+ );
+
+ const { data } = await recycleBinRepository.requestOriginalParent({
+ unique: this.data.unique,
+ });
+
+ // The original parent is still available. We will restore to that
+ if (data) {
+ return data.unique;
+ }
+
+ return undefined;
+ }
+
+ async #onSelectCustomDestination() {
+ const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
+ const modal = modalManager.open(this, UMB_DOCUMENT_PICKER_MODAL, {
+ data: {
+ multiple: false,
+ },
+ });
+
+ const { selection } = await modal.onSubmit();
+
+ if (selection.length > 0) {
+ const destinationUnique = selection[0];
+
+ console.log(data);
+ debugger;
+ }
+ }
+
+ async requestDestinationItem(unique: string | null) {
+ if (!this.data?.itemRepositoryAlias) throw new Error('Cannot restore an item without an item repository alias.');
+
+ const itemRepository = await createExtensionApiByAlias>(this, this.data.itemRepositoryAlias);
+ const { data } = await itemRepository.requestItems([unique]);
+ }
+
+ render() {
+ return html`
+
+
+ ${this._customSelectDestination
+ ? html`
+ Cannot automatically restore this item.
+
+ There is no location where this item can be automatically restored. You can select a new location
+ below.
+
+
+ Select location
+ `
+ : nothing}
+
+
+ `;
+ }
+
+ #renderDestination() {}
+
+ #renderCustomSelection() {}
+
+ static styles = [UmbTextStyles, css``];
+}
+
+export default UmbRestoreFromRecycleBinModalElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ [elementName]: UmbRestoreFromRecycleBinModalElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
new file mode 100644
index 0000000000..0ef015f444
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
@@ -0,0 +1,25 @@
+import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
+
+export interface UmbRestoreFromRecycleBinModalData {
+ unique: string;
+ entityType: string;
+ recycleBinRepositoryAlias: string;
+ itemRepositoryAlias: string;
+}
+
+export interface UmbRestoreFromRecycleBinModalValue {
+ destination: {
+ unique: string;
+ entityType: string;
+ };
+}
+
+export const UMB_RESTORE_FROM_RECYCLE_BIN_MODAL = new UmbModalToken<
+ UmbRestoreFromRecycleBinModalData,
+ UmbRestoreFromRecycleBinModalValue
+>('Umb.Modal.RecycleBin.Restore', {
+ modal: {
+ type: 'sidebar',
+ size: 'small',
+ },
+});
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts
index 3be8eeefcc..18edd68da0 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.kind.ts
@@ -16,6 +16,7 @@ export const manifest: UmbBackofficeManifestKind = {
meta: {
icon: 'icon-undo',
label: 'Restore...',
+ pickerModal: '',
},
},
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
index c15e204383..2aac69acc9 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
@@ -1,10 +1,35 @@
import { UmbEntityActionBase } from '../../../entity-action/entity-action-base.js';
+import { UMB_RESTORE_FROM_RECYCLE_BIN_MODAL } from './modal/restore-from-recycle-bin-modal.token.js';
+import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
+import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/entity-action';
+import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
import type { MetaEntityActionRestoreFromRecycleBinKind } from '@umbraco-cms/backoffice/extension-registry';
export class UmbRestoreFromRecycleBinEntityAction extends UmbEntityActionBase {
async execute() {
- debugger;
- console.log(`execute sort for: ${this.args.unique}`);
+ if (!this.args.unique) throw new Error('Cannot restore an item without a unique identifier.');
+
+ const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
+ const modal = modalManager.open(this, UMB_RESTORE_FROM_RECYCLE_BIN_MODAL, {
+ data: {
+ unique: this.args.unique,
+ entityType: this.args.entityType,
+ recycleBinRepositoryAlias: this.args.meta.recycleBinRepositoryAlias,
+ },
+ });
+
+ const { destination } = await modal.onSubmit();
+
+ const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT);
+ const event = new UmbRequestReloadStructureForEntityEvent({
+ unique: this.args.unique,
+ entityType: this.args.entityType,
+ });
+
+ actionEventContext.dispatchEvent(event);
+
+ // TODO: reload destination
+ console.log(destination.unique, destination.entityType);
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts
index 09d8f6c08a..7983bb697f 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts
@@ -29,7 +29,10 @@ export class UmbTrashEntityAction extends UmbEntityActionBase(this, this.args.meta.recycleBinRepositoryAlias);
+ const recycleBinRepository = await createExtensionApiByAlias(
+ this,
+ this.args.meta.recycleBinRepositoryAlias,
+ );
await recycleBinRepository.requestTrash({ unique: this.args.unique });
const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
index 1fc4073ffd..0ac0cd09be 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts
@@ -2,6 +2,7 @@ import { UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from '../repository/index.j
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
import { UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../entity.js';
+import { UMB_DOCUMENT_PICKER_MODAL } from '../../modals/document-picker-modal.token.js';
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
export const manifests: Array = [
@@ -25,6 +26,7 @@ export const manifests: Array = [
meta: {
itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
recycleBinRepositoryAlias: UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
+ pickerModal: UMB_DOCUMENT_PICKER_MODAL,
},
},
{
From 2cbb6aad955e0e5f2b6c9192ee3e101d65e37daa Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 19:33:24 +0200
Subject: [PATCH 047/280] pass item repo to modal
---
.../restore-from-recycle-bin/restore-from-recycle-bin.action.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
index 2aac69acc9..71f04de803 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
@@ -15,6 +15,7 @@ export class UmbRestoreFromRecycleBinEntityAction extends UmbEntityActionBase
Date: Wed, 3 Apr 2024 20:06:45 +0200
Subject: [PATCH 048/280] add arg types
---
.../recycle-bin-data-source.interface.ts | 11 ++++++++---
.../recycle-bin-repository.interface.ts | 11 ++++++++---
.../src/packages/core/recycle-bin/types.ts | 14 ++++++++++++++
3 files changed, 30 insertions(+), 6 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/types.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-data-source.interface.ts
index b0de7b0ab9..8d381a83c9 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-data-source.interface.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-data-source.interface.ts
@@ -1,3 +1,8 @@
+import type {
+ UmbRecycleBinOriginalParentRequestArgs,
+ UmbRecycleBinRestoreRequestArgs,
+ UmbRecycleBinTrashRequestArgs,
+} from './types.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';
@@ -6,8 +11,8 @@ export interface UmbRecycleBinDataSourceConstructor {
}
export interface UmbRecycleBinDataSource {
- trash(args: any): Promise;
- restore(args: any): Promise;
+ trash(args: UmbRecycleBinTrashRequestArgs): Promise;
+ restore(args: UmbRecycleBinRestoreRequestArgs): Promise;
empty(): Promise;
- getOriginalParent(args: any): Promise;
+ getOriginalParent(args: UmbRecycleBinOriginalParentRequestArgs): Promise;
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository.interface.ts
index cda0a2448a..92a6d2ba9a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository.interface.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository.interface.ts
@@ -1,10 +1,15 @@
import type { UmbRepositoryBase } from '../repository/repository-base.js';
+import type {
+ UmbRecycleBinOriginalParentRequestArgs,
+ UmbRecycleBinRestoreRequestArgs,
+ UmbRecycleBinTrashRequestArgs,
+} from './types.js';
import type { UmbRepositoryErrorResponse, UmbRepositoryResponse } from '@umbraco-cms/backoffice/repository';
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
export interface UmbRecycleBinRepository extends UmbRepositoryBase, UmbApi {
- requestTrash(args: any): Promise;
- requestRestore(args: any): Promise;
+ requestTrash(args: UmbRecycleBinTrashRequestArgs): Promise;
+ requestRestore(args: UmbRecycleBinRestoreRequestArgs): Promise;
requestEmpty(): Promise;
- requestOriginalParent(args: any): Promise>;
+ requestOriginalParent(args: UmbRecycleBinOriginalParentRequestArgs): Promise>;
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/types.ts
new file mode 100644
index 0000000000..3a74c7c86f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/types.ts
@@ -0,0 +1,14 @@
+export interface UmbRecycleBinRestoreRequestArgs {
+ unique: string;
+ destination: {
+ unique: string | null;
+ };
+}
+
+export interface UmbRecycleBinTrashRequestArgs {
+ unique: string;
+}
+
+export interface UmbRecycleBinOriginalParentRequestArgs {
+ unique: string;
+}
From 8c287e8757a77695fb7ae62709b1865a93387b89 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 21:04:36 +0200
Subject: [PATCH 049/280] export types
---
.../src/packages/core/recycle-bin/index.ts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/index.ts
index 49cec0d017..4cb027b622 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/index.ts
@@ -7,3 +7,8 @@ export {
export type { UmbRecycleBinDataSource } from './recycle-bin-data-source.interface.js';
export type { UmbRecycleBinRepository } from './recycle-bin-repository.interface.js';
+export type {
+ UmbRecycleBinRestoreRequestArgs,
+ UmbRecycleBinTrashRequestArgs,
+ UmbRecycleBinOriginalParentRequestArgs,
+} from './types.js';
From cedeede9cd6036895562a2c4da416488597fbdcb Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 21:04:49 +0200
Subject: [PATCH 050/280] Update document-recycle-bin.repository.ts
---
.../recycle-bin/repository/document-recycle-bin.repository.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts
index 2a33cafed8..89422926fc 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.repository.ts
@@ -1,5 +1,5 @@
-import { UmbRecycleBinRepositoryBase } from '@umbraco-cms/backoffice/recycle-bin';
import { UmbDocumentRecycleBinServerDataSource } from './document-recycle-bin.server.data-source.js';
+import { UmbRecycleBinRepositoryBase } from '@umbraco-cms/backoffice/recycle-bin';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
export class UmbDocumentRecycleBinRepository extends UmbRecycleBinRepositoryBase {
From d2d6043ad1f9681eb065d41de9023a4474dbb613 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 21:05:00 +0200
Subject: [PATCH 051/280] value can be undefined
---
.../modal/restore-from-recycle-bin-modal.token.ts | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
index 0ef015f444..c3af787444 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
@@ -8,10 +8,12 @@ export interface UmbRestoreFromRecycleBinModalData {
}
export interface UmbRestoreFromRecycleBinModalValue {
- destination: {
- unique: string;
- entityType: string;
- };
+ destination:
+ | {
+ unique: string;
+ entityType: string;
+ }
+ | undefined;
}
export const UMB_RESTORE_FROM_RECYCLE_BIN_MODAL = new UmbModalToken<
From 4ba5ab19d5c8ca1563cbfc895bbf01d84cb01aad Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 21:05:23 +0200
Subject: [PATCH 052/280] automatic restore + custom selection
---
.../restore-from-recycle-bin-modal.element.ts | 116 +++++++++++++-----
1 file changed, 87 insertions(+), 29 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
index 85d45dee42..4922c183ab 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
@@ -18,25 +18,32 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
UmbRestoreFromRecycleBinModalData,
UmbRestoreFromRecycleBinModalValue
> {
+ @state()
+ _isAutomaticRestore = false;
+
@state()
_customSelectDestination = false;
@state()
- _destinationItem: any;
+ _destinationItem?: any;
- constructor() {
- super();
- }
+ #recycleBinRepository?: UmbRecycleBinRepository;
protected async firstUpdated(_changedProperties: PropertyValueMap | Map): Promise {
super.firstUpdated(_changedProperties);
- const restoreDestination = await this.#requestRestoreDestination();
+ const restoreDestinationUnique = await this.#requestRestoreDestination();
- if (!restoreDestination) {
- this._customSelectDestination = true;
- this.requestUpdate();
- return;
+ if (restoreDestinationUnique) {
+ this._destinationItem = await this.#requestDestinationItem(restoreDestinationUnique);
+ if (!this._destinationItem) throw new Error('Cant find destination item.');
+
+ this.#setDestinationValue({
+ unique: this._destinationItem.unique,
+ entityType: this._destinationItem.entityType,
+ });
+
+ this._isAutomaticRestore = true;
}
}
@@ -45,16 +52,15 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
if (!this.data?.recycleBinRepositoryAlias)
throw new Error('Cannot restore an item without a recycle bin repository alias.');
- const recycleBinRepository = await createExtensionApiByAlias(
+ this.#recycleBinRepository = await createExtensionApiByAlias(
this,
this.data.recycleBinRepositoryAlias,
);
- const { data } = await recycleBinRepository.requestOriginalParent({
+ const { data } = await this.#recycleBinRepository.requestOriginalParent({
unique: this.data.unique,
});
- // The original parent is still available. We will restore to that
if (data) {
return data.unique;
}
@@ -74,44 +80,96 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
if (selection.length > 0) {
const destinationUnique = selection[0];
+ this._destinationItem = await this.#requestDestinationItem(destinationUnique);
+ if (!this._destinationItem) throw new Error('Cant find destination item.');
- console.log(data);
- debugger;
+ this.#setDestinationValue({
+ unique: this._destinationItem.unique,
+ entityType: this._destinationItem.entityType,
+ });
}
}
- async requestDestinationItem(unique: string | null) {
+ async #requestDestinationItem(unique: string | null) {
+ if (unique === null) {
+ console.log('ROOT IS SELECTED, HANDLE THIS CASE');
+ return;
+ }
+
if (!this.data?.itemRepositoryAlias) throw new Error('Cannot restore an item without an item repository alias.');
const itemRepository = await createExtensionApiByAlias>(this, this.data.itemRepositoryAlias);
const { data } = await itemRepository.requestItems([unique]);
+
+ return data?.[0];
+ }
+
+ async #onSubmit() {
+ if (!this.value.destination) throw new Error('Cannot restore an item without a destination.');
+ if (!this.#recycleBinRepository) throw new Error('Cannot restore an item without a destination.');
+ if (!this.data?.unique) throw new Error('Cannot restore an item without a unique identifier.');
+
+ const { error } = await this.#recycleBinRepository.requestRestore({
+ unique: this.data.unique,
+ destination: { unique: this.value.destination.unique },
+ });
+
+ if (!error) {
+ this._submitModal();
+ }
+ }
+
+ #setDestinationValue(destination: { unique: string; entityType: string }) {
+ this.updateValue({ destination });
}
render() {
return html`
- ${this._customSelectDestination
- ? html`
- Cannot automatically restore this item.
-
- There is no location where this item can be automatically restored. You can select a new location
- below.
-
-
- Select location
- `
- : nothing}
+ ${this._isAutomaticRestore
+ ? html` Restore (ITEM NAME HERE) to ${this._destinationItem.name}`
+ : this.#renderCustomSelectDestination()}
+ ${this.#renderActions()}
`;
}
- #renderDestination() {}
+ #renderCustomSelectDestination() {
+ return html`
+ Cannot automatically restore this item.
+ There is no location where this item can be automatically restored. You can select a new location below.
- #renderCustomSelection() {}
+ ${this._destinationItem
+ ? html`
+
+ (this._destinationItem = undefined)} label="Remove"
+ >${this.localize.term('general_remove')}
+
+ `
+ : html` Select location `}
+ `;
+ }
- static styles = [UmbTextStyles, css``];
+ #renderActions() {
+ return html`
+
+
+ `;
+ }
+
+ static styles = [
+ UmbTextStyles,
+ css`
+ #placeholder {
+ width: 100%;
+ }
+ `,
+ ];
}
export default UmbRestoreFromRecycleBinModalElement;
From a206a8ae06461e72cabe48002b6f06681ceb38f2 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 21:05:43 +0200
Subject: [PATCH 053/280] throw error if there is no destination returned
---
.../restore-from-recycle-bin/restore-from-recycle-bin.action.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
index 71f04de803..acc07f4adb 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
@@ -20,6 +20,7 @@ export class UmbRestoreFromRecycleBinEntityAction extends UmbEntityActionBase
Date: Wed, 3 Apr 2024 21:06:28 +0200
Subject: [PATCH 054/280] add types
---
...document-recycle-bin.server.data-source.ts | 23 +++++++++++++++----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
index 7d59389943..85b33ab073 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
@@ -1,4 +1,9 @@
-import type { UmbRecycleBinDataSource } from '@umbraco-cms/backoffice/recycle-bin';
+import type {
+ UmbRecycleBinDataSource,
+ UmbRecycleBinRestoreRequestArgs,
+ UmbRecycleBinTrashRequestArgs,
+ UmbRecycleBinOriginalParentRequestArgs,
+} from '@umbraco-cms/backoffice/recycle-bin';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { DocumentResource } from '@umbraco-cms/backoffice/external/backend-api';
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
@@ -10,19 +15,27 @@ export class UmbDocumentRecycleBinServerDataSource implements UmbRecycleBinDataS
this.#host = host;
}
- trash(args: { unique: string }) {
+ trash(args: UmbRecycleBinTrashRequestArgs) {
return tryExecuteAndNotify(this.#host, DocumentResource.putDocumentByIdMoveToRecycleBin({ id: args.unique }));
}
- restore(args: { unique: string; target: { unique: string | null } }) {
- return tryExecuteAndNotify(this.#host, DocumentResource.putRecycleBinDocumentByIdRestore({ id: args.unique }));
+ restore(args: UmbRecycleBinRestoreRequestArgs) {
+ return tryExecuteAndNotify(
+ this.#host,
+ DocumentResource.putRecycleBinDocumentByIdRestore({
+ id: args.unique,
+ requestBody: {
+ target: args.destination.unique ? { id: args.destination.unique } : null,
+ },
+ }),
+ );
}
empty() {
return tryExecuteAndNotify(this.#host, DocumentResource.deleteRecycleBinDocument());
}
- async getOriginalParent(args: { unique: string }) {
+ async getOriginalParent(args: UmbRecycleBinOriginalParentRequestArgs) {
const { data, error } = await tryExecuteAndNotify(
this.#host,
DocumentResource.getRecycleBinDocumentByIdOriginalParent({ id: args.unique }),
From db54fdb75517b54fce2588b76a9cad8ac963e778 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 3 Apr 2024 21:07:36 +0200
Subject: [PATCH 055/280] import type
---
.../core/recycle-bin/entity-action/trash/trash.action.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts
index 7983bb697f..f1c9bbee35 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts
@@ -1,5 +1,6 @@
import { UmbEntityActionBase } from '../../../entity-action/entity-action-base.js';
import { UmbRequestReloadStructureForEntityEvent } from '../../../entity-action/request-reload-structure-for-entity.event.js';
+import type { UmbRecycleBinRepository } from '../../recycle-bin-repository.interface.js';
import type { MetaEntityActionTrashKind } from '@umbraco-cms/backoffice/extension-registry';
import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
From 5fce1f8c005afe5af522d4ba49d39b319780056d Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Wed, 3 Apr 2024 23:46:24 +0200
Subject: [PATCH 056/280] add repo
---
.../modals/rollback/repository/index.ts | 2 +
.../modals/rollback/repository/manifests.ts | 12 ++++++
.../repository/rollback.repository.ts | 26 ++++++++++++
.../repository/rollback.server.data-source.ts | 40 +++++++++++++++++++
4 files changed, 80 insertions(+)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.repository.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.server.data-source.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/index.ts
new file mode 100644
index 0000000000..ead77c2bd7
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/index.ts
@@ -0,0 +1,2 @@
+export { UmbMemberDetailRepository } from './rollback.repository.js';
+export { UMB_ROLLBACK_REPOSITORY_ALIAS } from './manifests.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/manifests.ts
new file mode 100644
index 0000000000..1e0c52fc4f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/manifests.ts
@@ -0,0 +1,12 @@
+import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
+
+export const UMB_ROLLBACK_REPOSITORY_ALIAS = 'Umb.Repository.Rollback';
+
+const repository: ManifestRepository = {
+ type: 'repository',
+ alias: UMB_ROLLBACK_REPOSITORY_ALIAS,
+ name: 'Rollback Repository',
+ api: () => import('./rollback.repository.js'),
+};
+
+export const manifests = [repository];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.repository.ts
new file mode 100644
index 0000000000..1e46aec1fc
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.repository.ts
@@ -0,0 +1,26 @@
+import { UmbRollbackServerDataSource } from './rollback.server.data-source.js';
+import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
+
+export class UmbRollbackRepository extends UmbControllerBase implements UmbApi {
+ #dataSource: UmbRollbackServerDataSource;
+
+ constructor(host: UmbControllerHost) {
+ super(host);
+
+ this.#dataSource = new UmbRollbackServerDataSource(this);
+ }
+
+ async requestVersionsByDocumentId(id: string, culture: string) {
+ const { data, error } = await this.#dataSource.getVersionsByDocumentId(id, culture);
+ return { data, error };
+ }
+
+ async requestVersionById(id: string) {
+ const { data, error } = await this.#dataSource.getVersionById(id);
+ return { data, error };
+ }
+}
+
+export default UmbRollbackRepository;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.server.data-source.ts
new file mode 100644
index 0000000000..be767ffd45
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.server.data-source.ts
@@ -0,0 +1,40 @@
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { DocumentVersionResource } from '@umbraco-cms/backoffice/external/backend-api';
+import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
+
+/**
+ * A data source for the Rollback that fetches data from the server
+ * @export
+ * @class UmbRollbackServerDataSource
+ * @implements {RepositoryDetailDataSource}
+ */
+export class UmbRollbackServerDataSource {
+ #host: UmbControllerHost;
+
+ /**
+ * Creates an instance of UmbRollbackServerDataSource.
+ * @param {UmbControllerHost} host
+ * @memberof UmbRollbackServerDataSource
+ */
+ constructor(host: UmbControllerHost) {
+ this.#host = host;
+ }
+
+ /**
+ * Get a list of versions for a document
+ * @return {*}
+ * @memberof UmbRollbackServerDataSource
+ */
+ getVersionsByDocumentId(id: string, culture: string) {
+ return tryExecuteAndNotify(this.#host, DocumentVersionResource.getDocumentVersion({ documentId: id, culture }));
+ }
+
+ /**
+ * Get a specific version by id
+ * @return {*}
+ * @memberof UmbRollbackServerDataSource
+ */
+ getVersionById(id: string) {
+ return tryExecuteAndNotify(this.#host, DocumentVersionResource.getDocumentVersionById({ id }));
+ }
+}
From f018c6d1a78866a27e0ef673e2f631a3f067e138 Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Wed, 3 Apr 2024 23:46:33 +0200
Subject: [PATCH 057/280] load data
---
.../modals/rollback/rollback-modal.element.ts | 149 ++++++++++++++++--
1 file changed, 137 insertions(+), 12 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
index 9f707a7fb4..adf0088166 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
@@ -1,12 +1,88 @@
import type { UmbRollbackModalData, UmbRollbackModalValue } from './rollback-modal.token.js';
-import { css, customElement, html, state } from '@umbraco-cms/backoffice/external/lit';
+import { css, customElement, html, repeat, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import '../shared/document-variant-language-picker.element.js';
+import UmbRollbackRepository from './repository/rollback.repository.js';
+import { UmbUserRepository } from '@umbraco-cms/backoffice/user';
+import { UmbLocalizeDateElement } from 'src/packages/core/localization/localize-date.element.js';
@customElement('umb-rollback-modal')
export class UmbRollbackModalElement extends UmbModalBaseElement {
+ @state()
+ versions: { date: string; user: string; isCurrentlyPublishedVersion: boolean; id: string }[] = [];
+
+ @state()
+ currentVersion?: {
+ date: string;
+ name: string;
+ user: string;
+ id: string;
+ properties: {
+ alias: string;
+ value: string;
+ }[];
+ };
+
+ #rollbackRepository = new UmbRollbackRepository(this);
+
+ #userRepository = new UmbUserRepository(this);
+
+ constructor() {
+ super();
+
+ this.#requestVersions();
+ }
+
+ async #requestVersions() {
+ const { data } = await this.#rollbackRepository.requestVersionsByDocumentId(
+ 'bf327b58-9036-498b-9904-9b01b697b830',
+ 'en-us',
+ );
+
+ const tempItems: { date: string; user: string; isCurrentlyPublishedVersion: boolean; id: string }[] = [];
+
+ data?.items.forEach((item: any) => {
+ tempItems.push({
+ date: item.versionDate,
+ user: item.user.id,
+ isCurrentlyPublishedVersion: item.isCurrentPublishedVersion,
+ id: item.id,
+ });
+ });
+
+ this.versions = tempItems;
+ const id = tempItems.find((item) => item.isCurrentlyPublishedVersion)?.id;
+
+ if (id) {
+ this.#setCurrentVersion(id);
+ }
+ }
+
+ async #setCurrentVersion(id: string) {
+ const version = this.versions.find((item) => item.id === id);
+ if (!version) return;
+
+ const { data } = await this.#rollbackRepository.requestVersionById(id);
+ if (!data) return;
+
+ console.log('data', data);
+
+ this.currentVersion = {
+ date: version.date || '',
+ user: version.user,
+ name: data.variants[0].name,
+ id: data.id,
+ properties: data.values.map((value: any) => {
+ return {
+ alias: value.alias,
+ value: value.value,
+ };
+ }),
+ };
+ }
+
#onRollback() {
console.log('Rollback');
return;
@@ -17,27 +93,68 @@ export class UmbRollbackModalElement extends UmbModalBaseElement item.id,
+ (item) => {
+ return html`
+ this.#onVersionClicked(item.id)}
+ @keydown=${() => {}}
+ class="rollback-item ${this.currentVersion?.id === item.id ? 'active' : ''}">
+
+
+
+
+
${item.user}
+
${item.isCurrentlyPublishedVersion ? 'Current published version' : ''}
+
+
Prevent cleanup
+
+ `;
+ },
+ );
+ }
+
+ #renderCurrentVersion() {
+ if (!this.currentVersion) return;
+
return html`
-
-
-
April 2, 2024 6:05 PM
-
Jesper
-
Current published version
-
- Prevent cleanup
-
+
${this.currentVersion.name}
+ ${repeat(
+ this.currentVersion.properties,
+ (item) => item.alias,
+ (item) => {
+ return html`
${item.alias}: ${JSON.stringify(item.value)}
`;
+ },
+ )}
`;
}
+ get currentVersionHeader() {
+ return this.localize.date(this.currentVersion?.date || '') + ' - ' + this.currentVersion?.user;
+ }
+
render() {
return html`
-
${this.#renderRollbackItem()}
-
+
+ ${this.#renderVersions()}
+
+
${this.#renderCurrentVersion()}
`;
@@ -46,7 +163,11 @@ export class UmbRollbackModalElement extends UmbModalBaseElement
Date: Wed, 3 Apr 2024 23:59:25 +0200
Subject: [PATCH 058/280] add actions
---
.../modals/rollback/rollback-modal.element.ts | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
index adf0088166..1678d10893 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
@@ -1,12 +1,11 @@
import type { UmbRollbackModalData, UmbRollbackModalValue } from './rollback-modal.token.js';
+import { UmbRollbackRepository } from './repository/rollback.repository.js';
import { css, customElement, html, repeat, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import '../shared/document-variant-language-picker.element.js';
-import UmbRollbackRepository from './repository/rollback.repository.js';
import { UmbUserRepository } from '@umbraco-cms/backoffice/user';
-import { UmbLocalizeDateElement } from 'src/packages/core/localization/localize-date.element.js';
@customElement('umb-rollback-modal')
export class UmbRollbackModalElement extends UmbModalBaseElement {
@@ -131,7 +130,7 @@ export class UmbRollbackModalElement extends UmbModalBaseElement
- ${this.currentVersion.name}
+ name: ${this.currentVersion.name}
${repeat(
this.currentVersion.properties,
(item) => item.alias,
@@ -156,6 +155,10 @@ export class UmbRollbackModalElement extends UmbModalBaseElement
${this.#renderCurrentVersion()}
+
+ Cancel
+ Rollback
+
`;
}
@@ -187,16 +190,21 @@ export class UmbRollbackModalElement extends UmbModalBaseElement
Date: Thu, 4 Apr 2024 09:41:44 +0200
Subject: [PATCH 059/280] add rollback
---
.../repository/rollback.repository.ts | 10 +++++++
.../repository/rollback.server.data-source.ts | 18 ++++++++++--
.../modals/rollback/rollback-modal.element.ts | 29 +++++++++++++------
3 files changed, 46 insertions(+), 11 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.repository.ts
index 1e46aec1fc..26d4a01b74 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.repository.ts
@@ -21,6 +21,16 @@ export class UmbRollbackRepository extends UmbControllerBase implements UmbApi {
const { data, error } = await this.#dataSource.getVersionById(id);
return { data, error };
}
+
+ async setPreventCleanup(versionId: string, preventCleanup: boolean) {
+ const { error } = await this.#dataSource.setPreventCleanup(versionId, preventCleanup);
+ return { error };
+ }
+
+ async rollback(versionId: string, culture?: string) {
+ const { error } = await this.#dataSource.rollback(versionId, culture);
+ return { error };
+ }
}
export default UmbRollbackRepository;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.server.data-source.ts
index be767ffd45..9dccdb8466 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.server.data-source.ts
@@ -34,7 +34,21 @@ export class UmbRollbackServerDataSource {
* @return {*}
* @memberof UmbRollbackServerDataSource
*/
- getVersionById(id: string) {
- return tryExecuteAndNotify(this.#host, DocumentVersionResource.getDocumentVersionById({ id }));
+ getVersionById(versionId: string) {
+ return tryExecuteAndNotify(this.#host, DocumentVersionResource.getDocumentVersionById({ id: versionId }));
+ }
+
+ setPreventCleanup(versionId: string, preventCleanup: boolean) {
+ return tryExecuteAndNotify(
+ this.#host,
+ DocumentVersionResource.putDocumentVersionByIdPreventCleanup({ id: versionId, preventCleanup }),
+ );
+ }
+
+ rollback(versionId: string, culture?: string) {
+ return tryExecuteAndNotify(
+ this.#host,
+ DocumentVersionResource.postDocumentVersionByIdRollback({ id: versionId, culture }),
+ );
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
index 1678d10893..9ba0f98fbf 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
@@ -66,8 +66,6 @@ export class UmbRollbackModalElement extends UmbModalBaseElement
Date: Thu, 4 Apr 2024 09:45:00 +0200
Subject: [PATCH 060/280] temp solution to restore to root
---
.../restore-from-recycle-bin-modal.element.ts | 24 +++++++++++++++----
.../restore-from-recycle-bin-modal.token.ts | 2 +-
...document-recycle-bin.server.data-source.ts | 8 +++----
3 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
index 4922c183ab..2aad24f339 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
@@ -34,6 +34,21 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
const restoreDestinationUnique = await this.#requestRestoreDestination();
+ // TODO: handle ROOT lookup. Currently, we can't look up the root in the item repository.
+ // This is a temp solution to show something in the UI.
+ if (restoreDestinationUnique === null) {
+ this._destinationItem = {
+ name: 'ROOT',
+ };
+
+ this.#setDestinationValue({
+ unique: null,
+ entityType: 'unknown',
+ });
+
+ this._isAutomaticRestore = true;
+ }
+
if (restoreDestinationUnique) {
this._destinationItem = await this.#requestDestinationItem(restoreDestinationUnique);
if (!this._destinationItem) throw new Error('Cant find destination item.');
@@ -47,7 +62,7 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
}
}
- async #requestRestoreDestination(): Promise {
+ async #requestRestoreDestination(): Promise {
if (!this.data?.unique) throw new Error('Cannot restore an item without a unique identifier.');
if (!this.data?.recycleBinRepositoryAlias)
throw new Error('Cannot restore an item without a recycle bin repository alias.');
@@ -61,8 +76,9 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
unique: this.data.unique,
});
- if (data) {
- return data.unique;
+ // only check for undefined because data can be null if the parent is the root
+ if (data !== undefined) {
+ return data ? data.unique : null;
}
return undefined;
@@ -119,7 +135,7 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
}
}
- #setDestinationValue(destination: { unique: string; entityType: string }) {
+ #setDestinationValue(destination: UmbRestoreFromRecycleBinModalValue['destination']) {
this.updateValue({ destination });
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
index c3af787444..ed2befadee 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
@@ -10,7 +10,7 @@ export interface UmbRestoreFromRecycleBinModalData {
export interface UmbRestoreFromRecycleBinModalValue {
destination:
| {
- unique: string;
+ unique: string | null;
entityType: string;
}
| undefined;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
index 85b33ab073..7c8dda0721 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts
@@ -41,11 +41,9 @@ export class UmbDocumentRecycleBinServerDataSource implements UmbRecycleBinDataS
DocumentResource.getRecycleBinDocumentByIdOriginalParent({ id: args.unique }),
);
- if (data) {
- const mappedData = {
- unique: data.id,
- };
-
+ // only check for undefined because data can be null if the parent is the root
+ if (data !== undefined) {
+ const mappedData = data ? { unique: data.id } : null;
return { data: mappedData };
}
From 6ab18169dda77635db0ad1f84eb74c548a0e7a8d Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Thu, 4 Apr 2024 09:53:30 +0200
Subject: [PATCH 061/280] get user name
---
.../modals/rollback/rollback-modal.element.ts | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
index 9ba0f98fbf..b34ddda614 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
@@ -5,7 +5,7 @@ import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import '../shared/document-variant-language-picker.element.js';
-import { UmbUserRepository } from '@umbraco-cms/backoffice/user';
+import { UmbUserItemRepository, UmbUserRepository } from '@umbraco-cms/backoffice/user';
@customElement('umb-rollback-modal')
export class UmbRollbackModalElement extends UmbModalBaseElement {
@@ -26,7 +26,7 @@ export class UmbRollbackModalElement extends UmbModalBaseElement item.user.id))];
+
+ const { data: userItems } = await this.#userItemRepository.requestItems(uniqueUserIds);
+
data?.items.forEach((item: any) => {
tempItems.push({
date: item.versionDate,
- user: item.user.id,
+ user: userItems?.find((user) => user.unique === item.user.id)?.name || '',
isCurrentlyPublishedVersion: item.isCurrentPublishedVersion,
id: item.id,
});
@@ -85,19 +89,16 @@ export class UmbRollbackModalElement extends UmbModalBaseElement
Date: Thu, 4 Apr 2024 10:02:43 +0200
Subject: [PATCH 062/280] prevent cleanup
---
.../modals/rollback/repository/index.ts | 2 +-
.../modals/rollback/rollback-modal.element.ts | 34 ++++++++++++++++---
2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/index.ts
index ead77c2bd7..ccf1fc6c85 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/index.ts
@@ -1,2 +1,2 @@
-export { UmbMemberDetailRepository } from './rollback.repository.js';
+export { UmbRollbackRepository } from './rollback.repository.js';
export { UMB_ROLLBACK_REPOSITORY_ALIAS } from './manifests.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
index b34ddda614..65d4c53877 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
@@ -5,12 +5,20 @@ import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import '../shared/document-variant-language-picker.element.js';
-import { UmbUserItemRepository, UmbUserRepository } from '@umbraco-cms/backoffice/user';
+import { UmbUserItemRepository } from '@umbraco-cms/backoffice/user';
+
+type DocumentVersion = {
+ id: string;
+ date: string;
+ user: string;
+ isCurrentlyPublishedVersion: boolean;
+ preventCleanup: boolean;
+};
@customElement('umb-rollback-modal')
export class UmbRollbackModalElement extends UmbModalBaseElement {
@state()
- versions: { date: string; user: string; isCurrentlyPublishedVersion: boolean; id: string }[] = [];
+ versions: DocumentVersion[] = [];
@state()
currentVersion?: {
@@ -40,7 +48,7 @@ export class UmbRollbackModalElement extends UmbModalBaseElement item.user.id))];
@@ -52,6 +60,7 @@ export class UmbRollbackModalElement extends UmbModalBaseElement user.unique === item.user.id)?.name || '',
isCurrentlyPublishedVersion: item.isCurrentPublishedVersion,
id: item.id,
+ preventCleanup: item.preventCleanup,
});
});
@@ -101,6 +110,18 @@ export class UmbRollbackModalElement extends UmbModalBaseElement item.id === id);
+ if (!version) return;
+
+ version.preventCleanup = preventCleanup;
+ this.requestUpdate('versions');
+ }
+
#renderVersions() {
return repeat(
this.versions,
@@ -118,7 +139,11 @@ export class UmbRollbackModalElement extends UmbModalBaseElement${item.user}
${item.isCurrentlyPublishedVersion ? 'Current published version' : ''}
- Prevent cleanup
+ this.#onPreventCleanup(event, item.id, !item.preventCleanup)}>
+ ${item.preventCleanup ? 'Enable cleanup' : 'Prevent cleanup'}
+
`;
},
@@ -180,6 +205,7 @@ export class UmbRollbackModalElement extends UmbModalBaseElement
Date: Thu, 4 Apr 2024 10:07:37 +0200
Subject: [PATCH 063/280] cleanup
---
.../views/info/document-workspace-view-info-history.element.ts | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts
index 99adb3e5f6..0c73f5cf84 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts
@@ -47,9 +47,6 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement {
protected firstUpdated(): void {
this.#getLogs();
-
- //TODO: REMOVE THIS
- this.#onRollbackModalOpen();
}
async #getLogs() {
From c1ab82c5170d91cd21eda45257e5d153bb8358c0 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 10:11:47 +0200
Subject: [PATCH 064/280] clean up
---
.../restore-from-recycle-bin-modal.element.ts | 43 +++++++------------
1 file changed, 16 insertions(+), 27 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
index 2aad24f339..60f7bc070c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
@@ -21,9 +21,6 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
@state()
_isAutomaticRestore = false;
- @state()
- _customSelectDestination = false;
-
@state()
_destinationItem?: any;
@@ -32,11 +29,18 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
protected async firstUpdated(_changedProperties: PropertyValueMap | Map): Promise {
super.firstUpdated(_changedProperties);
- const restoreDestinationUnique = await this.#requestRestoreDestination();
+ const unique = await this.#requestAutomaticRestoreDestination();
+ if (unique !== undefined) {
+ this._isAutomaticRestore = true;
+ this.something(unique);
+ }
+ }
+
+ async something(unique: string | null) {
// TODO: handle ROOT lookup. Currently, we can't look up the root in the item repository.
// This is a temp solution to show something in the UI.
- if (restoreDestinationUnique === null) {
+ if (unique === null) {
this._destinationItem = {
name: 'ROOT',
};
@@ -45,24 +49,20 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
unique: null,
entityType: 'unknown',
});
-
- this._isAutomaticRestore = true;
}
- if (restoreDestinationUnique) {
- this._destinationItem = await this.#requestDestinationItem(restoreDestinationUnique);
+ if (unique) {
+ this._destinationItem = await this.#requestItem(unique);
if (!this._destinationItem) throw new Error('Cant find destination item.');
this.#setDestinationValue({
unique: this._destinationItem.unique,
entityType: this._destinationItem.entityType,
});
-
- this._isAutomaticRestore = true;
}
}
- async #requestRestoreDestination(): Promise {
+ async #requestAutomaticRestoreDestination(): Promise {
if (!this.data?.unique) throw new Error('Cannot restore an item without a unique identifier.');
if (!this.data?.recycleBinRepositoryAlias)
throw new Error('Cannot restore an item without a recycle bin repository alias.');
@@ -95,23 +95,12 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
const { selection } = await modal.onSubmit();
if (selection.length > 0) {
- const destinationUnique = selection[0];
- this._destinationItem = await this.#requestDestinationItem(destinationUnique);
- if (!this._destinationItem) throw new Error('Cant find destination item.');
-
- this.#setDestinationValue({
- unique: this._destinationItem.unique,
- entityType: this._destinationItem.entityType,
- });
+ const unique = selection[0];
+ this.something(unique);
}
}
- async #requestDestinationItem(unique: string | null) {
- if (unique === null) {
- console.log('ROOT IS SELECTED, HANDLE THIS CASE');
- return;
- }
-
+ async #requestItem(unique: string) {
if (!this.data?.itemRepositoryAlias) throw new Error('Cannot restore an item without an item repository alias.');
const itemRepository = await createExtensionApiByAlias>(this, this.data.itemRepositoryAlias);
@@ -156,7 +145,7 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
return html`
Cannot automatically restore this item.
There is no location where this item can be automatically restored. You can select a new location below.
-
+ Restore to:
${this._destinationItem
? html`
From 5ae79a75e80b0767076c114e32501452cc442d70 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 10:14:20 +0200
Subject: [PATCH 065/280] rename method to something useful
---
.../modal/restore-from-recycle-bin-modal.element.ts | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
index 60f7bc070c..8d11163c50 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
@@ -33,11 +33,11 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
if (unique !== undefined) {
this._isAutomaticRestore = true;
- this.something(unique);
+ this.setDestination(unique);
}
}
- async something(unique: string | null) {
+ async setDestination(unique: string | null) {
// TODO: handle ROOT lookup. Currently, we can't look up the root in the item repository.
// This is a temp solution to show something in the UI.
if (unique === null) {
@@ -96,7 +96,7 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
if (selection.length > 0) {
const unique = selection[0];
- this.something(unique);
+ this.setDestination(unique);
}
}
From 9cf2c4b5e08c8c5d1decf924520cd1ec60203b93 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 10:21:32 +0200
Subject: [PATCH 066/280] get the name of the restore item
---
.../restore-from-recycle-bin-modal.element.ts | 27 +++++++++++--------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
index 8d11163c50..4efab40b7a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
@@ -21,6 +21,9 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
@state()
_isAutomaticRestore = false;
+ @state()
+ _restoreItem?: any;
+
@state()
_destinationItem?: any;
@@ -28,12 +31,14 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
protected async firstUpdated(_changedProperties: PropertyValueMap | Map): Promise {
super.firstUpdated(_changedProperties);
+ if (!this.data?.unique) throw new Error('Cannot restore an item without a unique identifier.');
+ this._restoreItem = await this.#requestItem(this.data.unique);
const unique = await this.#requestAutomaticRestoreDestination();
if (unique !== undefined) {
- this._isAutomaticRestore = true;
this.setDestination(unique);
+ this._isAutomaticRestore = true;
}
}
@@ -84,6 +89,15 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
return undefined;
}
+ async #requestItem(unique: string) {
+ if (!this.data?.itemRepositoryAlias) throw new Error('Cannot restore an item without an item repository alias.');
+
+ const itemRepository = await createExtensionApiByAlias>(this, this.data.itemRepositoryAlias);
+ const { data } = await itemRepository.requestItems([unique]);
+
+ return data?.[0];
+ }
+
async #onSelectCustomDestination() {
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
const modal = modalManager.open(this, UMB_DOCUMENT_PICKER_MODAL, {
@@ -100,15 +114,6 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
}
}
- async #requestItem(unique: string) {
- if (!this.data?.itemRepositoryAlias) throw new Error('Cannot restore an item without an item repository alias.');
-
- const itemRepository = await createExtensionApiByAlias>(this, this.data.itemRepositoryAlias);
- const { data } = await itemRepository.requestItems([unique]);
-
- return data?.[0];
- }
-
async #onSubmit() {
if (!this.value.destination) throw new Error('Cannot restore an item without a destination.');
if (!this.#recycleBinRepository) throw new Error('Cannot restore an item without a destination.');
@@ -133,7 +138,7 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
${this._isAutomaticRestore
- ? html` Restore (ITEM NAME HERE) to ${this._destinationItem.name}`
+ ? html` Restore ${this._restoreItem?.name} to ${this._destinationItem?.name}`
: this.#renderCustomSelectDestination()}
${this.#renderActions()}
From 8465bb1dafe60b06bc6b6266d4ebc4f23d9b7b98 Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Thu, 4 Apr 2024 10:43:27 +0200
Subject: [PATCH 067/280] cleanup
---
.../src/packages/core/modal/component/modal.element.ts | 1 -
.../src/packages/core/modal/context/modal.context.ts | 4 ----
2 files changed, 5 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/component/modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/component/modal.element.ts
index 296061dbee..b5a431d7cc 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/component/modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/component/modal.element.ts
@@ -102,7 +102,6 @@ export class UmbModalElement extends UmbLitElement {
}
#createContainerElement() {
- console.log('Creating modal element', this.#modalContext);
return this.#modalContext!.type === 'sidebar' ? this.#createSidebarElement() : this.#createDialogElement();
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts
index 386cfb7a77..a22c2dd674 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts
@@ -48,13 +48,9 @@ export class UmbModalContext
Date: Thu, 4 Apr 2024 10:43:40 +0200
Subject: [PATCH 068/280] correct name
---
.../document-property-dataset-context.token.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-dataset-context/document-property-dataset-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-dataset-context/document-property-dataset-context.token.ts
index 62cd946c83..96efd8d3e6 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-dataset-context/document-property-dataset-context.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-dataset-context/document-property-dataset-context.token.ts
@@ -10,4 +10,4 @@ export const IsDocumentPropertyDatasetContext = (
export const UMB_DOCUMENT_PROPERTY_DATASET_CONTEXT = new UmbContextToken<
UmbPropertyDatasetContext,
UmbDocumentPropertyDataContext
->('UmbVariantContext', undefined, IsDocumentPropertyDatasetContext);
+>('UmbPropertyDatasetContext', undefined, IsDocumentPropertyDatasetContext);
From 92c8873de7efd11081e0b43ebdfd23c76224f1c4 Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Thu, 4 Apr 2024 10:43:51 +0200
Subject: [PATCH 069/280] get id and culture
---
.../repository/rollback.repository.ts | 2 +-
.../repository/rollback.server.data-source.ts | 2 +-
.../modals/rollback/rollback-modal.element.ts | 26 ++++++++++++++-----
3 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.repository.ts
index 26d4a01b74..e4ba53c696 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.repository.ts
@@ -12,7 +12,7 @@ export class UmbRollbackRepository extends UmbControllerBase implements UmbApi {
this.#dataSource = new UmbRollbackServerDataSource(this);
}
- async requestVersionsByDocumentId(id: string, culture: string) {
+ async requestVersionsByDocumentId(id: string, culture?: string) {
const { data, error } = await this.#dataSource.getVersionsByDocumentId(id, culture);
return { data, error };
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.server.data-source.ts
index 9dccdb8466..2344bdf802 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/repository/rollback.server.data-source.ts
@@ -25,7 +25,7 @@ export class UmbRollbackServerDataSource {
* @return {*}
* @memberof UmbRollbackServerDataSource
*/
- getVersionsByDocumentId(id: string, culture: string) {
+ getVersionsByDocumentId(id: string, culture?: string) {
return tryExecuteAndNotify(this.#host, DocumentVersionResource.getDocumentVersion({ documentId: id, culture }));
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
index 65d4c53877..2d6684cf5d 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
@@ -6,6 +6,9 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import '../shared/document-variant-language-picker.element.js';
import { UmbUserItemRepository } from '@umbraco-cms/backoffice/user';
+import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../workspace/index.js';
+import { UMB_DOCUMENT_PROPERTY_DATASET_CONTEXT } from '../../property-dataset-context/document-property-dataset-context.token.js';
+import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property';
type DocumentVersion = {
id: string;
@@ -33,20 +36,31 @@ export class UmbRollbackModalElement extends UmbModalBaseElement {
+ this.#propertyDatasetContext = instance;
+ this.#requestVersions();
+ });
}
async #requestVersions() {
- const { data } = await this.#rollbackRepository.requestVersionsByDocumentId(
- 'bf327b58-9036-498b-9904-9b01b697b830',
- 'en-us',
- );
+ if (!this.#propertyDatasetContext) return;
+
+ const documentId = this.#propertyDatasetContext.getUnique();
+ const documentCulture = this.#propertyDatasetContext.getVariantId().culture;
+
+ if (!documentId || !documentCulture) return;
+
+ const { data } = await this.#rollbackRepository.requestVersionsByDocumentId(documentId, documentCulture);
const tempItems: DocumentVersion[] = [];
From e737fcab579d80c71e45d3ed76f5170376517ec1 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 10:59:42 +0200
Subject: [PATCH 070/280] make source protected instead of private
---
.../packages/core/tree/data/tree-repository-base.ts | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts
index 2409617d42..7e2ca2ccdb 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts
@@ -28,7 +28,7 @@ export abstract class UmbTreeRepositoryBase<
{
protected _init: Promise;
protected _treeStore?: UmbTreeStore;
- #treeSource: UmbTreeDataSource;
+ protected _treeSource: UmbTreeDataSource;
/**
* Creates an instance of UmbTreeRepositoryBase.
@@ -43,7 +43,7 @@ export abstract class UmbTreeRepositoryBase<
treeStoreContextAlias: string | UmbContextToken,
) {
super(host);
- this.#treeSource = new treeSourceConstructor(this);
+ this._treeSource = new treeSourceConstructor(this);
this._init = this.consumeContext(treeStoreContextAlias, (instance) => {
this._treeStore = instance;
@@ -65,7 +65,7 @@ export abstract class UmbTreeRepositoryBase<
async requestRootTreeItems(args: any) {
await this._init;
- const { data, error } = await this.#treeSource.getRootItems(args);
+ const { data, error } = await this._treeSource.getRootItems(args);
if (data) {
this._treeStore!.appendItems(data.items);
@@ -84,7 +84,7 @@ export abstract class UmbTreeRepositoryBase<
if (args.parentUnique === undefined) throw new Error('Parent unique is missing');
await this._init;
- const { data, error } = await this.#treeSource.getChildrenOf(args);
+ const { data, error } = await this._treeSource.getChildrenOf(args);
if (data) {
this._treeStore!.appendItems(data.items);
@@ -103,7 +103,7 @@ export abstract class UmbTreeRepositoryBase<
if (args.descendantUnique === undefined) throw new Error('Descendant unique is missing');
await this._init;
- const { data, error } = await this.#treeSource.getAncestorsOf(args);
+ const { data, error } = await this._treeSource.getAncestorsOf(args);
// TODO: implement observable for ancestor items in the store
return { data, error };
From 435ef26cbc3b4e3aa5a433d6c49b7cb931d24f93 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 11:00:22 +0200
Subject: [PATCH 071/280] check if recycle bin has children on load
---
.../recycle-bin/tree/document-recycle-bin-tree.repository.ts | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/document-recycle-bin-tree.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/document-recycle-bin-tree.repository.ts
index 37ff658fb9..23ed6a2004 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/document-recycle-bin-tree.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/document-recycle-bin-tree.repository.ts
@@ -15,12 +15,15 @@ export class UmbDocumentRecycleBinTreeRepository
}
async requestTreeRoot() {
+ const { data: treeRootData } = await this._treeSource.getRootItems({ skip: 0, take: 1 });
+ const hasChildren = treeRootData?.total > 0;
+
const data = {
unique: null,
entityType: UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE,
name: 'Recycle Bin',
icon: 'icon-trash',
- hasChildren: true,
+ hasChildren,
isContainer: false,
isFolder: true,
};
From 9ca24c3c22f1483f719013f36882eaf5a8955e66 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 11:30:52 +0200
Subject: [PATCH 072/280] add manifest model for external auth provider
---
.../models/auth-provider.model.ts | 64 +++++++++++++++++++
.../core/extension-registry/models/index.ts | 5 +-
2 files changed, 68 insertions(+), 1 deletion(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/auth-provider.model.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/auth-provider.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/auth-provider.model.ts
new file mode 100644
index 0000000000..e212a5208e
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/auth-provider.model.ts
@@ -0,0 +1,64 @@
+import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
+import type { UUIInterfaceColor, UUIInterfaceLook } from '@umbraco-cms/backoffice/external/uui';
+
+/**
+ * Represents an authentication provider that can be used to authenticate users.
+ * The provider needs to be registered in the API that the authorization request is sent to in order to be used.
+ *
+ * @see {forProviderName} for the provider name that this provider is for.
+ */
+export interface ManifestAuthProvider extends ManifestElement {
+ type: 'authProvider';
+
+ /**
+ * The provider name that this provider is for.
+ * @examples 'Umbraco.Github'
+ */
+ forProviderName: string;
+
+ meta?: MetaAuthProvider;
+}
+
+export interface MetaAuthProvider {
+ /**
+ * The label of the provider that is shown to the user.
+ */
+ label?: string;
+
+ /**
+ * The default view of the provider that is shown to the user.
+ * If no element is provided, then the button will be rendered as a @see {UUIButtonElement} using these options.
+ */
+ defaultView: {
+ /**
+ * The icon of the provider that is shown to the user.
+ * @examples ['icon-cloud', 'icon-github', 'icon-google', 'icon-facebook', 'icon-twitter', 'icon-x', 'icon-microsoft']
+ * @default 'icon-cloud'
+ */
+ icon?: string;
+
+ /**
+ * The color of the provider that is shown to the user.
+ * @default 'secondary'
+ */
+ color?: UUIInterfaceLook;
+
+ /**
+ * The look of the provider that is shown to the user.
+ * @default 'default'
+ */
+ look?: UUIInterfaceColor;
+ };
+
+ /**
+ * If true, the Umbraco backoffice login will be disabled.
+ * @default false
+ */
+ denyLocalLogin?: boolean;
+
+ /**
+ * If true, the user will be redirected to the provider's login page immediately.
+ * @default false
+ */
+ autoRedirect?: boolean;
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts
index bd329b9276..c6d951bd27 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts
@@ -1,3 +1,4 @@
+import type { ManifestAuthProvider } from './auth-provider.model.js';
import type { ManifestBlockEditorCustomView } from './block-editor-custom-view.model.js';
import type { ManifestCollection } from './collection.models.js';
import type { ManifestCollectionView } from './collection-view.model.js';
@@ -64,6 +65,7 @@ import type {
ManifestEntryPoint,
} from '@umbraco-cms/backoffice/extension-api';
+export type * from './auth-provider.model.js';
export type * from './block-editor-custom-view.model.js';
export type * from './collection.models.js';
export type * from './collection-action.model.js';
@@ -131,12 +133,13 @@ export type ManifestWorkspaces = ManifestWorkspace | ManifestWorkspaceRoutableKi
export type ManifestWorkspaceViews = ManifestWorkspaceView | ManifestWorkspaceViewContentTypeDesignEditorKind;
export type ManifestTypes =
+ | ManifestAuthProvider
| ManifestBundle
- | ManifestCondition
| ManifestBlockEditorCustomView
| ManifestCollection
| ManifestCollectionView
| ManifestCollectionAction
+ | ManifestCondition
| ManifestDashboard
| ManifestDashboardCollection
| ManifestDynamicRootOrigin
From 090247d79078e290159f5c89372288c2722e5e91 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 11:45:06 +0200
Subject: [PATCH 073/280] add authProvider's to test it out
---
.../src/mocks/handlers/manifests.handlers.ts | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts
index e84f191d7f..3a37e7aec5 100644
--- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts
+++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts
@@ -90,6 +90,32 @@ export const manifestDevelopmentHandler = rest.get(umbracoPath('/package/manifes
},
],
},
+ {
+ name: 'My Auth Package',
+ extensions: [
+ {
+ type: 'authProvider',
+ alias: 'My.AuthProvider.Google',
+ name: 'My Custom Auth Provider',
+ forProviderName: 'Umbraco.Google',
+ meta: {
+ label: 'Sign in with Google',
+ },
+ },
+ {
+ type: 'authProvider',
+ alias: 'My.AUthProvider.Github',
+ name: 'My Github Auth Provider',
+ forProviderName: 'Umbraco.Github',
+ meta: {
+ label: 'Use Github!',
+ look: 'primary',
+ icon: 'icon-github',
+ color: 'success',
+ },
+ },
+ ],
+ },
]),
);
});
From 22e7742d47d500be5cc5f4a08cfc5dcc20761175 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 11:55:03 +0200
Subject: [PATCH 074/280] add support to supply an identity provider to the
authorization request
---
.../src/packages/core/auth/auth-flow.ts | 18 +++++++++++++-----
.../src/packages/core/auth/auth.context.ts | 6 ++++--
2 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth-flow.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth-flow.ts
index 4ced20b66d..01b20582f9 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth-flow.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth-flow.ts
@@ -187,15 +187,23 @@ export class UmbAuthFlow {
}
/**
- * This method will make an authorization request to the server.
+ * Make an authorization request to the server using the specified identity provider.
+ * This method will redirect the user to the authorization endpoint of the server.
*
- * @param username The username to use for the authorization request. It will be provided to the OpenID server as a hint.
+ * @param identityProvider The identity provider to use for the authorization request.
+ * @param usernameHint (Optional) The username to use for the authorization request. It will be provided to the OpenID server as a hint.
*/
- makeAuthorizationRequest(username?: string): void {
+ makeAuthorizationRequest(identityProvider: string, usernameHint?: string): void {
const extras: StringMap = { prompt: 'consent', access_type: 'offline' };
- if (username) {
- extras['login_hint'] = username;
+ // If the identity provider is not 'Umbraco', we will add it to the extras.
+ if (identityProvider !== 'Umbraco') {
+ extras['identity_provider'] = identityProvider;
+ }
+
+ // If there is a username hint, we will add it to the extras.
+ if (usernameHint) {
+ extras['login_hint'] = usernameHint;
}
// create a request
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts
index f457655b18..f5a64ff438 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts
@@ -26,9 +26,11 @@ export class UmbAuthContext extends UmbContextBase {
/**
* Initiates the login flow.
+ * @param identityProvider The provider to use for login. Default is 'Umbraco'.
+ * @param usernameHint The username hint to use for login.
*/
- makeAuthorizationRequest() {
- return this.#authFlow.makeAuthorizationRequest();
+ makeAuthorizationRequest(identityProvider = 'Umbraco', usernameHint?: string) {
+ return this.#authFlow.makeAuthorizationRequest(identityProvider, usernameHint);
}
/**
From 762368c3a6a5f5c62ba44569eb976b9009ad18c1 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 12:03:15 +0200
Subject: [PATCH 075/280] move auth request logic to an auth controller to
split up the logic
---
.../src/apps/app/app-auth.controller.ts | 9 +++++++++
src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts | 6 ++++--
2 files changed, 13 insertions(+), 2 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
new file mode 100644
index 0000000000..fdc4c6cb35
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
@@ -0,0 +1,9 @@
+import { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth';
+import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
+
+export class UmbAppAuthController extends UmbControllerBase {
+ async makeAuthorizationRequest() {
+ const authContext = await this.getContext(UMB_AUTH_CONTEXT);
+ return authContext.makeAuthorizationRequest();
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
index d104ccab6c..89ab404a0f 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
@@ -1,6 +1,7 @@
import type { UmbAppErrorElement } from './app-error.element.js';
import { UmbAppContext } from './app.context.js';
import { UmbServerConnection } from './server-connection.js';
+import { UmbAppAuthController } from './app-auth.controller.js';
import type { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth';
import { UMB_STORAGE_REDIRECT_URL, UmbAuthContext } from '@umbraco-cms/backoffice/auth';
import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
@@ -59,6 +60,7 @@ export class UmbAppElement extends UmbLitElement {
#umbIconRegistry = new UmbIconRegistry();
#uuiIconRegistry = new UUIIconRegistryEssential();
#serverConnection?: UmbServerConnection;
+ #authController = new UmbAppAuthController(this);
constructor() {
super();
@@ -184,7 +186,7 @@ export class UmbAppElement extends UmbLitElement {
}
#isAuthorizedGuard(): Guard {
- return () => {
+ return async () => {
if (!this.#authContext) {
throw new Error('[Fatal] AuthContext requested before it was initialized');
}
@@ -197,7 +199,7 @@ export class UmbAppElement extends UmbLitElement {
window.sessionStorage.setItem(UMB_STORAGE_REDIRECT_URL, location.href);
// Make a request to the auth server to start the auth flow
- this.#authContext.makeAuthorizationRequest();
+ await this.#authController.makeAuthorizationRequest();
// Return false to prevent the route from being rendered
return false;
From 600cc1192fd25dadf2b4e73576bdcaf9ec0fdce6 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 12:22:10 +0200
Subject: [PATCH 076/280] add recycle bin for media
---
.../src/packages/media/media/manifests.ts | 2 +
.../recycle-bin/entity-action/manifests.ts | 42 ++++++++++
.../media/media/recycle-bin/entity.ts | 1 +
.../packages/media/media/recycle-bin/index.ts | 2 +
.../media/media/recycle-bin/manifests.ts | 6 ++
.../media/recycle-bin/menu-item/manifests.ts | 19 +++++
.../media/recycle-bin/repository/constants.ts | 1 +
.../media/recycle-bin/repository/index.ts | 1 +
.../media/recycle-bin/repository/manifests.ts | 11 +++
.../media-recycle-bin.repository.ts | 11 +++
.../media-recycle-bin.server.data-source.ts | 52 ++++++++++++
.../media/media/recycle-bin/tree/constants.ts | 3 +
.../media/media/recycle-bin/tree/index.ts | 9 ++
.../media/media/recycle-bin/tree/manifests.ts | 49 +++++++++++
.../tree/media-recycle-bin-tree.repository.ts | 33 ++++++++
...dia-recycle-bin-tree.server.data-source.ts | 84 +++++++++++++++++++
.../tree/media-recycle-bin-tree.store.ts | 24 ++++++
.../reload-tree-item-children/manifests.ts | 12 +++
.../media/media/recycle-bin/tree/types.ts | 6 ++
19 files changed, 368 insertions(+)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/entity-action/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/entity.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu-item/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/constants.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/media-recycle-bin.repository.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/media-recycle-bin.server.data-source.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/constants.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/media-recycle-bin-tree.repository.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/media-recycle-bin-tree.server.data-source.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/media-recycle-bin-tree.store.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/reload-tree-item-children/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/types.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/manifests.ts
index dba85d8ce2..cbdd5167a5 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/manifests.ts
@@ -3,6 +3,7 @@ import { manifests as entityActionsManifests } from './entity-actions/manifests.
import { manifests as entityBulkActionsManifests } from './entity-bulk-actions/manifests.js';
import { manifests as menuManifests } from './menu/manifests.js';
import { manifests as propertyEditorsManifests } from './property-editors/manifests.js';
+import { manifests as recycleBinManifests } from './recycle-bin/manifests.js';
import { manifests as repositoryManifests } from './repository/manifests.js';
import { manifests as sectionViewManifests } from './section-view/manifests.js';
import { manifests as treeManifests } from './tree/manifests.js';
@@ -14,6 +15,7 @@ export const manifests = [
...entityBulkActionsManifests,
...menuManifests,
...propertyEditorsManifests,
+ ...recycleBinManifests,
...repositoryManifests,
...sectionViewManifests,
...treeManifests,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/entity-action/manifests.ts
new file mode 100644
index 0000000000..d3631a29c6
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/entity-action/manifests.ts
@@ -0,0 +1,42 @@
+import { UMB_MEDIA_RECYCLE_BIN_REPOSITORY_ALIAS } from '../repository/index.js';
+import { UMB_MEDIA_ENTITY_TYPE } from '../../entity.js';
+import { UMB_MEDIA_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
+import { UMB_MEDIA_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../entity.js';
+import { UMB_MEDIA_TREE_PICKER_MODAL } from '@umbraco-cms/backoffice/modal';
+import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifests: Array = [
+ {
+ type: 'entityAction',
+ kind: 'trash',
+ alias: 'Umb.EntityAction.Media.RecycleBin.Trash',
+ name: 'Trash Media Entity Action',
+ forEntityTypes: [UMB_MEDIA_ENTITY_TYPE],
+ meta: {
+ itemRepositoryAlias: UMB_MEDIA_ITEM_REPOSITORY_ALIAS,
+ recycleBinRepositoryAlias: UMB_MEDIA_RECYCLE_BIN_REPOSITORY_ALIAS,
+ },
+ },
+ {
+ type: 'entityAction',
+ kind: 'restoreFromRecycleBin',
+ alias: 'Umb.EntityAction.Media.RecycleBin.Restore',
+ name: 'Restore Media From Recycle Bin Entity Action',
+ forEntityTypes: [UMB_MEDIA_ENTITY_TYPE],
+ meta: {
+ itemRepositoryAlias: UMB_MEDIA_ITEM_REPOSITORY_ALIAS,
+ recycleBinRepositoryAlias: UMB_MEDIA_RECYCLE_BIN_REPOSITORY_ALIAS,
+ pickerModal: UMB_MEDIA_TREE_PICKER_MODAL,
+ },
+ },
+ {
+ type: 'entityAction',
+ kind: 'emptyRecycleBin',
+ alias: 'Umb.EntityAction.Media.RecycleBin.Empty',
+ name: 'Empty Media Recycle Bin Entity Action',
+ forEntityTypes: [UMB_MEDIA_RECYCLE_BIN_ROOT_ENTITY_TYPE],
+ meta: {
+ recycleBinRepositoryAlias: UMB_MEDIA_RECYCLE_BIN_REPOSITORY_ALIAS,
+ },
+ },
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/entity.ts
new file mode 100644
index 0000000000..6237cb94c2
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/entity.ts
@@ -0,0 +1 @@
+export const UMB_MEDIA_RECYCLE_BIN_ROOT_ENTITY_TYPE = 'media-recycle-bin-root';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/index.ts
new file mode 100644
index 0000000000..f04892ceea
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/index.ts
@@ -0,0 +1,2 @@
+export * from './tree/index.js';
+export * from './entity.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/manifests.ts
new file mode 100644
index 0000000000..423a1afcc2
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/manifests.ts
@@ -0,0 +1,6 @@
+import { manifests as entityActionManifests } from './entity-action/manifests.js';
+import { manifests as menuItemManifests } from './menu-item/manifests.js';
+import { manifests as repositoryManifests } from './repository/manifests.js';
+import { manifests as treeManifests } from './tree/manifests.js';
+
+export const manifests = [...entityActionManifests, ...menuItemManifests, ...repositoryManifests, ...treeManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu-item/manifests.ts
new file mode 100644
index 0000000000..3c6b76f1eb
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu-item/manifests.ts
@@ -0,0 +1,19 @@
+import { UMB_MEDIA_MENU_ALIAS } from '../../menu/manifests.js';
+import { UMB_MEDIA_RECYCLE_BIN_TREE_ALIAS } from '../tree/index.js';
+import type { ManifestMenuItemTreeKind } from '@umbraco-cms/backoffice/extension-registry';
+
+const menuItem: ManifestMenuItemTreeKind = {
+ type: 'menuItem',
+ kind: 'tree',
+ alias: 'Umb.MenuItem.Media.RecycleBin',
+ name: 'Media Recycle Bin Menu Item',
+ weight: 100,
+ meta: {
+ treeAlias: UMB_MEDIA_RECYCLE_BIN_TREE_ALIAS,
+ label: 'Recycle Bin',
+ icon: 'icon-trash',
+ menus: [UMB_MEDIA_MENU_ALIAS],
+ },
+};
+
+export const manifests = [menuItem];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/constants.ts
new file mode 100644
index 0000000000..e71d4eb514
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/constants.ts
@@ -0,0 +1 @@
+export const UMB_MEDIA_RECYCLE_BIN_REPOSITORY_ALIAS = 'Umb.Repository.Media.RecycleBin';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/index.ts
new file mode 100644
index 0000000000..b62f9e3b1d
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/index.ts
@@ -0,0 +1 @@
+export { UMB_MEDIA_RECYCLE_BIN_REPOSITORY_ALIAS } from './constants.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/manifests.ts
new file mode 100644
index 0000000000..d645ed6c0e
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/manifests.ts
@@ -0,0 +1,11 @@
+import { UMB_MEDIA_RECYCLE_BIN_REPOSITORY_ALIAS } from './constants.js';
+import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
+
+const repository: ManifestRepository = {
+ type: 'repository',
+ alias: UMB_MEDIA_RECYCLE_BIN_REPOSITORY_ALIAS,
+ name: 'Media Recycle Bin Repository',
+ api: () => import('./media-recycle-bin.repository.js'),
+};
+
+export const manifests = [repository];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/media-recycle-bin.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/media-recycle-bin.repository.ts
new file mode 100644
index 0000000000..867693f2c9
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/media-recycle-bin.repository.ts
@@ -0,0 +1,11 @@
+import { UmbMediaRecycleBinServerDataSource } from './media-recycle-bin.server.data-source.js';
+import { UmbRecycleBinRepositoryBase } from '@umbraco-cms/backoffice/recycle-bin';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+
+export class UmbMediaRecycleBinRepository extends UmbRecycleBinRepositoryBase {
+ constructor(host: UmbControllerHost) {
+ super(host, UmbMediaRecycleBinServerDataSource);
+ }
+}
+
+export { UmbMediaRecycleBinRepository as api };
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/media-recycle-bin.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/media-recycle-bin.server.data-source.ts
new file mode 100644
index 0000000000..91eedae21f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/media-recycle-bin.server.data-source.ts
@@ -0,0 +1,52 @@
+import type {
+ UmbRecycleBinDataSource,
+ UmbRecycleBinRestoreRequestArgs,
+ UmbRecycleBinTrashRequestArgs,
+ UmbRecycleBinOriginalParentRequestArgs,
+} from '@umbraco-cms/backoffice/recycle-bin';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { MediaResource } from '@umbraco-cms/backoffice/external/backend-api';
+import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
+
+export class UmbMediaRecycleBinServerDataSource implements UmbRecycleBinDataSource {
+ #host: UmbControllerHost;
+
+ constructor(host: UmbControllerHost) {
+ this.#host = host;
+ }
+
+ trash(args: UmbRecycleBinTrashRequestArgs) {
+ return tryExecuteAndNotify(this.#host, MediaResource.putMediaByIdMoveToRecycleBin({ id: args.unique }));
+ }
+
+ restore(args: UmbRecycleBinRestoreRequestArgs) {
+ return tryExecuteAndNotify(
+ this.#host,
+ MediaResource.putRecycleBinMediaByIdRestore({
+ id: args.unique,
+ requestBody: {
+ target: args.destination.unique ? { id: args.destination.unique } : null,
+ },
+ }),
+ );
+ }
+
+ empty() {
+ return tryExecuteAndNotify(this.#host, MediaResource.deleteRecycleBinMedia());
+ }
+
+ async getOriginalParent(args: UmbRecycleBinOriginalParentRequestArgs) {
+ const { data, error } = await tryExecuteAndNotify(
+ this.#host,
+ MediaResource.getRecycleBinMediaByIdOriginalParent({ id: args.unique }),
+ );
+
+ // only check for undefined because data can be null if the parent is the root
+ if (data !== undefined) {
+ const mappedData = data ? { unique: data.id } : null;
+ return { data: mappedData };
+ }
+
+ return { error };
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/constants.ts
new file mode 100644
index 0000000000..161a713575
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/constants.ts
@@ -0,0 +1,3 @@
+export const UMB_MEDIA_RECYCLE_BIN_TREE_REPOSITORY_ALIAS = 'Umb.Repository.Media.RecycleBin.Tree';
+export const UMB_MEDIA_RECYCLE_BIN_TREE_STORE_ALIAS = 'Umb.Store.Media.RecycleBin.Tree';
+export const UMB_MEDIA_RECYCLE_BIN_TREE_ALIAS = 'Umb.Tree.Media.RecycleBin';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/index.ts
new file mode 100644
index 0000000000..2a6044c805
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/index.ts
@@ -0,0 +1,9 @@
+export { UmbMediaRecycleBinTreeRepository } from './media-recycle-bin-tree.repository.js';
+export {
+ UMB_MEDIA_RECYCLE_BIN_TREE_REPOSITORY_ALIAS,
+ UMB_MEDIA_RECYCLE_BIN_TREE_STORE_ALIAS,
+ UMB_MEDIA_RECYCLE_BIN_TREE_ALIAS,
+} from './constants.js';
+export { UMB_MEDIA_RECYCLE_BIN_TREE_STORE_CONTEXT } from './media-recycle-bin-tree.store.js';
+export { type UmbMediaRecycleBinTreeStore } from './media-recycle-bin-tree.store.js';
+export * from './types.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/manifests.ts
new file mode 100644
index 0000000000..d3557a6293
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/manifests.ts
@@ -0,0 +1,49 @@
+import { UMB_MEDIA_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../entity.js';
+import {
+ UMB_MEDIA_RECYCLE_BIN_TREE_ALIAS,
+ UMB_MEDIA_RECYCLE_BIN_TREE_REPOSITORY_ALIAS,
+ UMB_MEDIA_RECYCLE_BIN_TREE_STORE_ALIAS,
+} from './constants.js';
+import { UmbMediaRecycleBinTreeRepository } from './media-recycle-bin-tree.repository.js';
+import { UmbMediaRecycleBinTreeStore } from './media-recycle-bin-tree.store.js';
+import { manifests as reloadTreeItemChildrenManifests } from './reload-tree-item-children/manifests.js';
+import type {
+ ManifestRepository,
+ ManifestTree,
+ ManifestTreeItem,
+ ManifestTreeStore,
+} from '@umbraco-cms/backoffice/extension-registry';
+
+const treeRepository: ManifestRepository = {
+ type: 'repository',
+ alias: UMB_MEDIA_RECYCLE_BIN_TREE_REPOSITORY_ALIAS,
+ name: 'Media Recycle Bin Tree Repository',
+ api: UmbMediaRecycleBinTreeRepository,
+};
+
+const treeStore: ManifestTreeStore = {
+ type: 'treeStore',
+ alias: UMB_MEDIA_RECYCLE_BIN_TREE_STORE_ALIAS,
+ name: 'Media Recycle Bin Tree Store',
+ api: UmbMediaRecycleBinTreeStore,
+};
+
+const tree: ManifestTree = {
+ type: 'tree',
+ kind: 'default',
+ alias: UMB_MEDIA_RECYCLE_BIN_TREE_ALIAS,
+ name: 'Media Recycle Bin Tree',
+ meta: {
+ repositoryAlias: UMB_MEDIA_RECYCLE_BIN_TREE_REPOSITORY_ALIAS,
+ },
+};
+
+const treeItem: ManifestTreeItem = {
+ type: 'treeItem',
+ kind: 'default',
+ alias: 'Umb.TreeItem.Media.RecycleBin',
+ name: 'Media Recycle Bin Tree Item',
+ forEntityTypes: [UMB_MEDIA_RECYCLE_BIN_ROOT_ENTITY_TYPE],
+};
+
+export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadTreeItemChildrenManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/media-recycle-bin-tree.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/media-recycle-bin-tree.repository.ts
new file mode 100644
index 0000000000..f027339993
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/media-recycle-bin-tree.repository.ts
@@ -0,0 +1,33 @@
+import { UMB_MEDIA_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../entity.js';
+import { UmbMediaRecycleBinTreeServerDataSource } from './media-recycle-bin-tree.server.data-source.js';
+import type { UmbMediaRecycleBinTreeItemModel, UmbMediaRecycleBinTreeRootModel } from './types.js';
+import { UMB_MEDIA_RECYCLE_BIN_TREE_STORE_CONTEXT } from './media-recycle-bin-tree.store.js';
+import { UmbTreeRepositoryBase } from '@umbraco-cms/backoffice/tree';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
+
+export class UmbMediaRecycleBinTreeRepository
+ extends UmbTreeRepositoryBase
+ implements UmbApi
+{
+ constructor(host: UmbControllerHost) {
+ super(host, UmbMediaRecycleBinTreeServerDataSource, UMB_MEDIA_RECYCLE_BIN_TREE_STORE_CONTEXT);
+ }
+
+ async requestTreeRoot() {
+ const { data: treeRootData } = await this._treeSource.getRootItems({ skip: 0, take: 1 });
+ const hasChildren = treeRootData?.total > 0;
+
+ const data = {
+ unique: null,
+ entityType: UMB_MEDIA_RECYCLE_BIN_ROOT_ENTITY_TYPE,
+ name: 'Recycle Bin',
+ icon: 'icon-trash',
+ hasChildren,
+ isContainer: false,
+ isFolder: true,
+ };
+
+ return { data };
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/media-recycle-bin-tree.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/media-recycle-bin-tree.server.data-source.ts
new file mode 100644
index 0000000000..a9fa6bdf6c
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/media-recycle-bin-tree.server.data-source.ts
@@ -0,0 +1,84 @@
+import { UMB_MEDIA_ENTITY_TYPE } from '../../entity.js';
+import type { UmbMediaRecycleBinTreeItemModel } from './types.js';
+import type { MediaRecycleBinItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
+import { MediaResource } from '@umbraco-cms/backoffice/external/backend-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import type {
+ UmbTreeAncestorsOfRequestArgs,
+ UmbTreeChildrenOfRequestArgs,
+ UmbTreeRootItemsRequestArgs,
+} from '@umbraco-cms/backoffice/tree';
+import { UmbTreeServerDataSourceBase } from '@umbraco-cms/backoffice/tree';
+
+/**
+ * A data source for the Media Recycle Bin tree that fetches data from the server
+ * @export
+ * @class UmbMediaRecycleBinTreeServerDataSource
+ * @implements {UmbTreeDataSource}
+ */
+export class UmbMediaRecycleBinTreeServerDataSource extends UmbTreeServerDataSourceBase<
+ MediaRecycleBinItemResponseModel,
+ UmbMediaRecycleBinTreeItemModel
+> {
+ /**
+ * Creates an instance of UmbMediaRecycleBinTreeServerDataSource.
+ * @param {UmbControllerHost} host
+ * @memberof UmbMediaRecycleBinTreeServerDataSource
+ */
+ constructor(host: UmbControllerHost) {
+ super(host, {
+ getRootItems,
+ getChildrenOf,
+ getAncestorsOf,
+ mapper,
+ });
+ }
+}
+
+const getRootItems = (args: UmbTreeRootItemsRequestArgs) =>
+ // eslint-disable-next-line local-rules/no-direct-api-import
+ MediaResource.getRecycleBinMediaRoot({ skip: args.skip, take: args.take });
+
+const getChildrenOf = (args: UmbTreeChildrenOfRequestArgs) => {
+ if (args.parentUnique === null) {
+ return getRootItems(args);
+ } else {
+ // eslint-disable-next-line local-rules/no-direct-api-import
+ return MediaResource.getRecycleBinMediaChildren({
+ parentId: args.parentUnique,
+ skip: args.skip,
+ take: args.take,
+ });
+ }
+};
+
+const getAncestorsOf = (args: UmbTreeAncestorsOfRequestArgs) =>
+ // eslint-disable-next-line local-rules/no-direct-api-import
+ MediaResource.getTreeMediaAncestors({
+ descendantId: args.descendantUnique,
+ });
+
+const mapper = (item: MediaRecycleBinItemResponseModel): UmbMediaRecycleBinTreeItemModel => {
+ return {
+ unique: item.id,
+ parentUnique: item.parent ? item.parent.id : null,
+ entityType: UMB_MEDIA_ENTITY_TYPE,
+ noAccess: false,
+ isTrashed: true,
+ hasChildren: item.hasChildren,
+ mediaType: {
+ unique: item.mediaType.id,
+ icon: item.mediaType.icon,
+ collection: item.mediaType.collection ? { unique: item.mediaType.collection.id } : null,
+ },
+ variants: item.variants.map((variant) => {
+ return {
+ name: variant.name,
+ culture: variant.culture || null,
+ segment: null, // TODO: add segment to the backend API?
+ };
+ }),
+ name: item.variants[0]?.name, // TODO: this is not correct. We need to get it from the variants. This is a temp solution.
+ isFolder: false,
+ };
+};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/media-recycle-bin-tree.store.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/media-recycle-bin-tree.store.ts
new file mode 100644
index 0000000000..6ccf7e34dd
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/media-recycle-bin-tree.store.ts
@@ -0,0 +1,24 @@
+import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { UmbUniqueTreeStore } from '@umbraco-cms/backoffice/tree';
+
+/**
+ * @export
+ * @class UmbMediaRecycleBinTreeStore
+ * @extends {UmbStoreBase}
+ * @description - Tree Data Store for Media Recycle Bin Tree Items
+ */
+export class UmbMediaRecycleBinTreeStore extends UmbUniqueTreeStore {
+ /**
+ * Creates an instance of UmbMediaRecycleBinTreeStore.
+ * @param {UmbControllerHost} host
+ * @memberof UmbMediaRecycleBinTreeStore
+ */
+ constructor(host: UmbControllerHost) {
+ super(host, UMB_MEDIA_RECYCLE_BIN_TREE_STORE_CONTEXT.toString());
+ }
+}
+
+export const UMB_MEDIA_RECYCLE_BIN_TREE_STORE_CONTEXT = new UmbContextToken(
+ 'UmbMediaRecycleBinTreeStore',
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/reload-tree-item-children/manifests.ts
new file mode 100644
index 0000000000..e4977c9214
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/reload-tree-item-children/manifests.ts
@@ -0,0 +1,12 @@
+import { UMB_MEDIA_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../../entity.js';
+import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifests: Array = [
+ {
+ type: 'entityAction',
+ kind: 'reloadTreeItemChildren',
+ alias: 'Umb.EntityAction.MediaRecycleBin.Tree.ReloadChildrenOf',
+ name: 'Reload Media Recycle Bin Tree Item Children Entity Action',
+ forEntityTypes: [UMB_MEDIA_RECYCLE_BIN_ROOT_ENTITY_TYPE],
+ },
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/types.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/types.ts
new file mode 100644
index 0000000000..b09498103f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/tree/types.ts
@@ -0,0 +1,6 @@
+import type { UmbMediaTreeItemModel } from '../../tree/index.js';
+import type { UmbUniqueTreeRootModel } from '@umbraco-cms/backoffice/tree';
+
+export interface UmbMediaRecycleBinTreeItemModel extends UmbMediaTreeItemModel {}
+
+export interface UmbMediaRecycleBinTreeRootModel extends UmbUniqueTreeRootModel {}
From 1b30cf2bdd50c3131b6a4bde9bfd823db613a301 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 13:01:53 +0200
Subject: [PATCH 077/280] picker modal from manifest
---
.../modal/restore-from-recycle-bin-modal.element.ts | 7 ++++---
.../modal/restore-from-recycle-bin-modal.token.ts | 3 +++
.../restore-from-recycle-bin.action.ts | 1 +
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
index 4efab40b7a..6bcb071416 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.element.ts
@@ -4,11 +4,10 @@ import type {
UmbRestoreFromRecycleBinModalValue,
} from './restore-from-recycle-bin-modal.token.js';
import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
-import { html, customElement, state, nothing, css } from '@umbraco-cms/backoffice/external/lit';
+import { html, customElement, state, css } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
-import { UMB_DOCUMENT_PICKER_MODAL } from '@umbraco-cms/backoffice/document';
import type { UmbItemRepository } from '@umbraco-cms/backoffice/repository';
const elementName = 'umb-restore-from-recycle-bin-modal';
@@ -99,8 +98,10 @@ export class UmbRestoreFromRecycleBinModalElement extends UmbModalBaseElement<
}
async #onSelectCustomDestination() {
+ if (!this.data?.pickerModal) throw new Error('Cannot select a destination without a picker modal.');
+
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
- const modal = modalManager.open(this, UMB_DOCUMENT_PICKER_MODAL, {
+ const modal = modalManager.open(this, this.data.pickerModal, {
data: {
multiple: false,
},
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
index ed2befadee..abab77f3f3 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
@@ -1,10 +1,13 @@
+import type { UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal';
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
+import type { UmbUniqueTreeItemModel, UmbUniqueTreeRootModel } from '@umbraco-cms/backoffice/tree';
export interface UmbRestoreFromRecycleBinModalData {
unique: string;
entityType: string;
recycleBinRepositoryAlias: string;
itemRepositoryAlias: string;
+ pickerModal: UmbModalToken> | string;
}
export interface UmbRestoreFromRecycleBinModalValue {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
index acc07f4adb..5910d4df6a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
@@ -16,6 +16,7 @@ export class UmbRestoreFromRecycleBinEntityAction extends UmbEntityActionBase
Date: Thu, 4 Apr 2024 13:27:54 +0200
Subject: [PATCH 078/280] add specific interface to tree picker value
---
src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts
index f6b81a7e1e..4d64ac0e63 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts
@@ -11,3 +11,5 @@ export interface UmbPickerModalValue {
export interface UmbTreePickerModalData extends UmbPickerModalData {
treeAlias?: string;
}
+
+export interface UmbTreePickerModalValue extends UmbPickerModalValue {}
From 1db28d07daf9feb0be8748a3cb2c28328ff7038e Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 13:28:04 +0200
Subject: [PATCH 079/280] add todo
---
.../src/packages/core/modal/types.ts | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts
index 4d64ac0e63..8f42e65ee0 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts
@@ -1,8 +1,8 @@
-export interface UmbPickerModalData {
+export interface UmbPickerModalData {
multiple?: boolean;
- hideTreeRoot?: boolean;
- filter?: (item: TreeItemType) => boolean;
- pickableFilter?: (item: TreeItemType) => boolean;
+ hideTreeRoot?: boolean; // TODO: this should be moved to a tree picker modal data interface
+ filter?: (item: ItemType) => boolean;
+ pickableFilter?: (item: ItemType) => boolean;
}
export interface UmbPickerModalValue {
selection: Array;
From 2039e6a052f6729dc05d37b025257b3870f6bbed Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 13:28:53 +0200
Subject: [PATCH 080/280] add picker interfaces
---
.../core/extension-registry/models/entity-action.model.ts | 4 ++--
.../modal/restore-from-recycle-bin-modal.token.ts | 5 ++---
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
index c0b7805c07..68ed28918a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts
@@ -2,7 +2,7 @@ import type { ConditionTypes } from '../conditions/types.js';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import type { UmbEntityAction } from '@umbraco-cms/backoffice/entity-action';
import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api';
-import type { UmbModalToken } from '@umbraco-cms/backoffice/modal';
+import type { UmbModalToken, UmbPickerModalData, UmbPickerModalValue } from '@umbraco-cms/backoffice/modal';
/**
* An action to perform on an entity
@@ -78,7 +78,7 @@ export interface ManifestEntityActionRestoreFromRecycleBinKind
export interface MetaEntityActionRestoreFromRecycleBinKind extends MetaEntityActionDefaultKind {
recycleBinRepositoryAlias: string;
itemRepositoryAlias: string;
- pickerModal: UmbModalToken | string;
+ pickerModal: UmbModalToken, UmbPickerModalValue> | string;
}
// EMPTY RECYCLE BIN
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
index abab77f3f3..63b94f4451 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/modal/restore-from-recycle-bin-modal.token.ts
@@ -1,13 +1,12 @@
-import type { UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal';
+import type { UmbPickerModalData, UmbPickerModalValue } from '@umbraco-cms/backoffice/modal';
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
-import type { UmbUniqueTreeItemModel, UmbUniqueTreeRootModel } from '@umbraco-cms/backoffice/tree';
export interface UmbRestoreFromRecycleBinModalData {
unique: string;
entityType: string;
recycleBinRepositoryAlias: string;
itemRepositoryAlias: string;
- pickerModal: UmbModalToken> | string;
+ pickerModal: UmbModalToken, UmbPickerModalValue> | string;
}
export interface UmbRestoreFromRecycleBinModalValue {
From 46c52153bca1ce88560eec1b834899edad04a9e8 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 13:30:39 +0200
Subject: [PATCH 081/280] null check
---
.../recycle-bin/tree/document-recycle-bin-tree.repository.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/document-recycle-bin-tree.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/document-recycle-bin-tree.repository.ts
index 23ed6a2004..c451dbb466 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/document-recycle-bin-tree.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/document-recycle-bin-tree.repository.ts
@@ -16,7 +16,7 @@ export class UmbDocumentRecycleBinTreeRepository
async requestTreeRoot() {
const { data: treeRootData } = await this._treeSource.getRootItems({ skip: 0, take: 1 });
- const hasChildren = treeRootData?.total > 0;
+ const hasChildren = treeRootData ? treeRootData.total > 0 : false;
const data = {
unique: null,
From ad3301d21953ec9175c71e3e52bf13d8125a9a71 Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Thu, 4 Apr 2024 13:52:36 +0200
Subject: [PATCH 082/280] multiple variants
---
.../modals/rollback/rollback-modal.element.ts | 38 +++++++++++++++----
1 file changed, 30 insertions(+), 8 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
index 2d6684cf5d..275e7e90cd 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
@@ -9,6 +9,7 @@ import { UmbUserItemRepository } from '@umbraco-cms/backoffice/user';
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../workspace/index.js';
import { UMB_DOCUMENT_PROPERTY_DATASET_CONTEXT } from '../../property-dataset-context/document-property-dataset-context.token.js';
import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property';
+import { UUISelectEvent } from '@umbraco-ui/uui';
type DocumentVersion = {
id: string;
@@ -35,19 +36,26 @@ export class UmbRollbackModalElement extends UmbModalBaseElement {
this.#propertyDatasetContext = instance;
+ this.currentCulture = this.#propertyDatasetContext.getVariantId().culture ?? undefined;
this.#requestVersions();
});
}
@@ -56,11 +64,10 @@ export class UmbRollbackModalElement extends UmbModalBaseElementLanguage
+
+ `;
+ }
+
#renderVersions() {
- return repeat(
+ return html` ${this.#renderCultureSelect()}
+ ${repeat(
this.versions,
(item) => item.id,
(item) => {
@@ -161,7 +183,7 @@ export class UmbRollbackModalElement extends UmbModalBaseElement
`;
},
- );
+ )}`;
}
#renderCurrentVersion() {
From 7fd8d70064e8ade7c95afbf0c1fa9cdf45b3f83f Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Thu, 4 Apr 2024 14:03:23 +0200
Subject: [PATCH 083/280] variant select
---
.../modals/rollback/rollback-modal.element.ts | 29 ++++++++++---------
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
index 275e7e90cd..773503e57e 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
@@ -6,10 +6,8 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import '../shared/document-variant-language-picker.element.js';
import { UmbUserItemRepository } from '@umbraco-cms/backoffice/user';
-import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../workspace/index.js';
-import { UMB_DOCUMENT_PROPERTY_DATASET_CONTEXT } from '../../property-dataset-context/document-property-dataset-context.token.js';
import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property';
-import { UUISelectEvent } from '@umbraco-ui/uui';
+import type { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui';
type DocumentVersion = {
id: string;
@@ -41,7 +39,7 @@ export class UmbRollbackModalElement extends UmbModalBaseElement {
tempItems.push({
date: item.versionDate,
- user: userItems?.find((user) => user.unique === item.user.id)?.name || '',
+ user: userItems?.find((user) => user.unique === item.user.id)?.name || 'Unknown user',
isCurrentlyPublishedVersion: item.isCurrentPublishedVersion,
id: item.id,
preventCleanup: item.preventCleanup,
@@ -103,14 +101,16 @@ export class UmbRollbackModalElement extends UmbModalBaseElement x.culture === this.currentCulture)?.name || data.variants[0].name,
id: data.id,
- properties: data.values.map((value: any) => {
- return {
- alias: value.alias,
- value: value.value,
- };
- }),
+ properties: data.values
+ .filter((x) => x.culture === this.currentCulture)
+ .map((value: any) => {
+ return {
+ alias: value.alias,
+ value: value.value,
+ };
+ }),
};
}
@@ -118,7 +118,8 @@ export class UmbRollbackModalElement extends UmbModalBaseElement 1 ? this.currentCulture : undefined;
+ this.#rollbackRepository.rollback(id, culture);
this.modalContext?.reject();
}
From 3382dd5a9a4d5d6f0b5e0b6d10d451b09bbe82ef Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Thu, 4 Apr 2024 14:13:22 +0200
Subject: [PATCH 084/280] correct date format
---
.../modals/rollback/rollback-modal.element.ts | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
index 773503e57e..570c51d3a7 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
@@ -48,6 +48,13 @@ export class UmbRollbackModalElement extends UmbModalBaseElement
-
+
${item.user}
${item.isCurrentlyPublishedVersion ? 'Current published version' : ''}
@@ -205,7 +212,9 @@ export class UmbRollbackModalElement extends UmbModalBaseElement
Date: Thu, 4 Apr 2024 14:25:48 +0200
Subject: [PATCH 085/280] get real languages
---
.../modals/rollback/rollback-modal.element.ts | 27 ++++++++++++++++---
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
index 570c51d3a7..f1abfaa2eb 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/rollback/rollback-modal.element.ts
@@ -8,6 +8,7 @@ import '../shared/document-variant-language-picker.element.js';
import { UmbUserItemRepository } from '@umbraco-cms/backoffice/user';
import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property';
import type { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui';
+import { UMB_VARIANT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
type DocumentVersion = {
id: string;
@@ -39,14 +40,15 @@ export class UmbRollbackModalElement extends UmbModalBaseElement {
this.#propertyDatasetContext = instance;
- this.currentCulture = this.#propertyDatasetContext.getVariantId().culture ?? undefined;
+ this.currentCulture = instance.getVariantId().culture ?? undefined;
this.#requestVersions();
});
+
+ this.consumeContext(UMB_VARIANT_WORKSPACE_CONTEXT, (instance) => {
+ this.#variantWorkspaceContext = instance;
+
+ // TODO: For some reason TS cant find languages on the context
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ instance.languages.subscribe((languages) => {
+ this.availableVariants = languages.map((language: any) => {
+ return {
+ name: language.name,
+ value: language.unique,
+ selected: language.unique === this.currentCulture,
+ };
+ });
+ });
+ });
}
async #requestVersions() {
@@ -106,7 +125,7 @@ export class UmbRollbackModalElement extends UmbModalBaseElement x.culture === this.currentCulture)?.name || data.variants[0].name,
id: data.id,
From 951d8831cd3509e11534391330ae38de28c5e501 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 14:51:18 +0200
Subject: [PATCH 086/280] move isAuthorized logic into the auth controller
---
.../src/apps/app/app-auth.controller.ts | 49 +++++++++++++++++--
.../src/apps/app/app.element.ts | 19 +------
2 files changed, 46 insertions(+), 22 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
index fdc4c6cb35..73c31479d9 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
@@ -1,9 +1,50 @@
-import { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth';
+import { UMB_AUTH_CONTEXT, UMB_STORAGE_REDIRECT_URL } from '@umbraco-cms/backoffice/auth';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
export class UmbAppAuthController extends UmbControllerBase {
- async makeAuthorizationRequest() {
- const authContext = await this.getContext(UMB_AUTH_CONTEXT);
- return authContext.makeAuthorizationRequest();
+ #authContext?: typeof UMB_AUTH_CONTEXT.TYPE;
+
+ constructor(host: UmbControllerHost) {
+ super(host);
+
+ this.consumeContext(UMB_AUTH_CONTEXT, (context) => {
+ this.#authContext = context;
+ });
+ }
+
+ /**
+ * Checks if the user is authorized.
+ * If not, the authorization flow is started.
+ */
+ async isAuthorized(): Promise {
+ if (!this.#authContext) {
+ throw new Error('[Fatal] Auth context is not available');
+ }
+
+ const isAuthorized = this.#authContext.getIsAuthorized();
+
+ if (isAuthorized) {
+ return true;
+ }
+
+ // Save location.href so we can redirect to it after login
+ window.sessionStorage.setItem(UMB_STORAGE_REDIRECT_URL, location.href);
+
+ // Make a request to the auth server to start the auth flow
+ return this.makeAuthorizationRequest();
+ }
+
+ async makeAuthorizationRequest(): Promise {
+ if (!this.#authContext) {
+ throw new Error('[Fatal] Auth context is not available');
+ }
+
+ this.#authContext.makeAuthorizationRequest();
+
+ // Reinitialize the auth flow (load the state from local storage)
+ this.#authContext.setInitialState();
+
+ return true;
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
index 89ab404a0f..3ccb67046a 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
@@ -186,24 +186,7 @@ export class UmbAppElement extends UmbLitElement {
}
#isAuthorizedGuard(): Guard {
- return async () => {
- if (!this.#authContext) {
- throw new Error('[Fatal] AuthContext requested before it was initialized');
- }
-
- if (this.#authContext.getIsAuthorized()) {
- return true;
- }
-
- // Save location.href so we can redirect to it after login
- window.sessionStorage.setItem(UMB_STORAGE_REDIRECT_URL, location.href);
-
- // Make a request to the auth server to start the auth flow
- await this.#authController.makeAuthorizationRequest();
-
- // Return false to prevent the route from being rendered
- return false;
- };
+ return () => this.#authController.isAuthorized();
}
#errorPage(errorMsg: string, error?: unknown) {
From 6f5b49886f15ef49e75f18111270e1d0f144e7e4 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 15:30:09 +0200
Subject: [PATCH 087/280] register public extensions in the app element
---
.../src/apps/app/app-auth.controller.ts | 12 ++++++++++++
.../src/apps/app/app.element.ts | 3 +++
.../src/apps/backoffice/backoffice.element.ts | 8 +-------
3 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
index 73c31479d9..9d0c7983c9 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
@@ -1,9 +1,13 @@
import { UMB_AUTH_CONTEXT, UMB_STORAGE_REDIRECT_URL } from '@umbraco-cms/backoffice/auth';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { UmbServerExtensionRegistrator } from '@umbraco-cms/backoffice/extension-api';
+import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
export class UmbAppAuthController extends UmbControllerBase {
#authContext?: typeof UMB_AUTH_CONTEXT.TYPE;
+ #serverExtensionRegistrator = new UmbServerExtensionRegistrator(this, umbExtensionsRegistry);
+ #init;
constructor(host: UmbControllerHost) {
super(host);
@@ -11,6 +15,8 @@ export class UmbAppAuthController extends UmbControllerBase {
this.consumeContext(UMB_AUTH_CONTEXT, (context) => {
this.#authContext = context;
});
+
+ this.#init = Promise.all([this.#serverExtensionRegistrator.registerPublicExtensions()]);
}
/**
@@ -35,11 +41,17 @@ export class UmbAppAuthController extends UmbControllerBase {
return this.makeAuthorizationRequest();
}
+ /**
+ * Starts the authorization flow.
+ * It will check which providers are available and either redirect directly to the provider or show a provider selection screen.
+ */
async makeAuthorizationRequest(): Promise {
if (!this.#authContext) {
throw new Error('[Fatal] Auth context is not available');
}
+ await this.#init;
+
this.#authContext.makeAuthorizationRequest();
// Reinitialize the auth flow (load the state from local storage)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
index 3ccb67046a..94cf02eed0 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
@@ -67,6 +67,9 @@ export class UmbAppElement extends UmbLitElement {
new UmbContextDebugController(this);
+ new UmbBundleExtensionInitializer(this, umbExtensionsRegistry);
+ new UmbEntryPointExtensionInitializer(this, umbExtensionsRegistry);
+
this.#umbIconRegistry.attach(this);
this.#uuiIconRegistry.attach(this);
}
diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts
index 4d77370af7..407e04a759 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts
@@ -1,11 +1,7 @@
import { UmbBackofficeContext } from './backoffice.context.js';
import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
-import {
- UmbBundleExtensionInitializer,
- UmbEntryPointExtensionInitializer,
- UmbServerExtensionRegistrator,
-} from '@umbraco-cms/backoffice/extension-api';
+import { UmbServerExtensionRegistrator } from '@umbraco-cms/backoffice/extension-api';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import './components/index.js';
@@ -53,8 +49,6 @@ export class UmbBackofficeElement extends UmbLitElement {
super();
new UmbBackofficeContext(this);
- new UmbBundleExtensionInitializer(this, umbExtensionsRegistry);
- new UmbEntryPointExtensionInitializer(this, umbExtensionsRegistry);
new UmbServerExtensionRegistrator(this, umbExtensionsRegistry).registerAllExtensions();
// So far local packages are this simple to registerer, so no need for a manager to do that:
From 6b57cf02edc4db03c662c4a239a80fbf62dc73dc Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 15:30:29 +0200
Subject: [PATCH 088/280] add imports
---
src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
index 94cf02eed0..b11e26695d 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
@@ -12,6 +12,11 @@ import type { Guard, UmbRoute } from '@umbraco-cms/backoffice/router';
import { pathWithoutBasePath } from '@umbraco-cms/backoffice/router';
import { OpenAPI, RuntimeLevelModel } from '@umbraco-cms/backoffice/external/backend-api';
import { UmbContextDebugController } from '@umbraco-cms/backoffice/debug';
+import {
+ UmbBundleExtensionInitializer,
+ UmbEntryPointExtensionInitializer,
+} from '@umbraco-cms/backoffice/extension-api';
+import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
@customElement('umb-app')
export class UmbAppElement extends UmbLitElement {
From 01fd7e02e9f42dc6600a9bd07be34cc995e85aa6 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 15:30:43 +0200
Subject: [PATCH 089/280] remove unused import
---
src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
index b11e26695d..f4a9bb8239 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
@@ -3,7 +3,7 @@ import { UmbAppContext } from './app.context.js';
import { UmbServerConnection } from './server-connection.js';
import { UmbAppAuthController } from './app-auth.controller.js';
import type { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth';
-import { UMB_STORAGE_REDIRECT_URL, UmbAuthContext } from '@umbraco-cms/backoffice/auth';
+import { UmbAuthContext } from '@umbraco-cms/backoffice/auth';
import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
import { UUIIconRegistryEssential } from '@umbraco-cms/backoffice/external/uui';
import { UmbIconRegistry } from '@umbraco-cms/backoffice/icon';
From 1b3d704b432228ebdfc2c8a298b12014cd081492 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 15:31:03 +0200
Subject: [PATCH 090/280] update the baseURL whenever it changes
---
.../src/apps/app/app.element.ts | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
index f4a9bb8239..6d3070339e 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
@@ -27,7 +27,12 @@ export class UmbAppElement extends UmbLitElement {
* @remarks This is the base URL of the Umbraco server, not the base URL of the backoffice.
*/
@property({ type: String })
- serverUrl = window.location.origin;
+ set serverUrl(url: string) {
+ OpenAPI.BASE = url;
+ }
+ get serverUrl() {
+ return OpenAPI.BASE;
+ }
/**
* The base path of the backoffice.
@@ -70,6 +75,8 @@ export class UmbAppElement extends UmbLitElement {
constructor() {
super();
+ OpenAPI.BASE = window.location.origin;
+
new UmbContextDebugController(this);
new UmbBundleExtensionInitializer(this, umbExtensionsRegistry);
@@ -85,14 +92,6 @@ export class UmbAppElement extends UmbLitElement {
}
async #setup() {
- if (this.serverUrl === undefined) throw new Error('No serverUrl provided');
-
- /* All requests to the server requires the base URL to be set.
- We make sure it happens before we get the server status.
- TODO: find the right place to set this
- */
- OpenAPI.BASE = this.serverUrl;
-
this.#serverConnection = await new UmbServerConnection(this.serverUrl).connect();
this.#authContext = new UmbAuthContext(this, this.serverUrl, this.backofficePath, this.bypassAuth);
From a25ec074c1c1838a393bc34aa3a4addaa103dc2c Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 15:31:13 +0200
Subject: [PATCH 091/280] add public manifest handlers
---
.../src/mocks/browser-handlers.ts | 4 +-
.../src/mocks/handlers/manifests.handlers.ts | 244 +++++++++---------
2 files changed, 129 insertions(+), 119 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts
index 6a3c44ce04..a5751325f3 100644
--- a/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts
+++ b/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts
@@ -90,11 +90,11 @@ switch (import.meta.env.VITE_UMBRACO_INSTALL_STATUS) {
switch (import.meta.env.VITE_UMBRACO_EXTENSION_MOCKS) {
case 'on':
- handlers.push(manifestsHandlers.manifestDevelopmentHandler);
+ handlers.push(...manifestsHandlers.manifestDevelopmentHandlers);
break;
default:
- handlers.push(manifestsHandlers.manifestEmptyHandler);
+ handlers.push(...manifestsHandlers.manifestEmptyHandlers);
}
export { handlers };
diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts
index 3a37e7aec5..df03f8cffd 100644
--- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts
+++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/manifests.handlers.ts
@@ -3,127 +3,137 @@ const { rest } = window.MockServiceWorker;
import type { PackageManifestResponse } from '../../packages/packages/types.js';
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
-export const manifestDevelopmentHandler = rest.get(umbracoPath('/package/manifest'), (_req, res, ctx) => {
- return res(
- // Respond with a 200 status code
- ctx.status(200),
- ctx.json([
- {
- name: 'My Package Name',
- version: '1.0.0',
- extensions: [
- {
- type: 'bundle',
- alias: 'My.Package.Bundle',
- name: 'My Package Bundle',
- js: '/App_Plugins/custom-bundle-package/index.js',
- },
- ],
- },
- {
- name: 'Named Package',
- version: '1.0.0',
- extensions: [
- {
- type: 'section',
- alias: 'My.Section.Custom',
- name: 'Custom Section',
- js: '/App_Plugins/section.js',
- elementName: 'my-section-custom',
- weight: 1,
- meta: {
- label: 'Custom',
- pathname: 'my-custom',
+export const manifestDevelopmentHandlers = [
+ rest.get(umbracoPath('/package/manifest'), (_req, res, ctx) => {
+ return res(
+ // Respond with a 200 status code
+ ctx.status(200),
+ ctx.json([
+ {
+ name: 'My Package Name',
+ version: '1.0.0',
+ extensions: [
+ {
+ type: 'bundle',
+ alias: 'My.Package.Bundle',
+ name: 'My Package Bundle',
+ js: '/App_Plugins/custom-bundle-package/index.js',
},
- },
- {
- type: 'propertyEditorUi',
- alias: 'My.PropertyEditorUI.Custom',
- name: 'My Custom Property Editor UI',
- js: '/App_Plugins/property-editor.js',
- elementName: 'my-property-editor-ui-custom',
- meta: {
- label: 'My Custom Property',
- icon: 'document',
- group: 'Common',
- propertyEditorSchema: 'Umbraco.TextBox',
+ ],
+ },
+ {
+ name: 'Named Package',
+ version: '1.0.0',
+ extensions: [
+ {
+ type: 'section',
+ alias: 'My.Section.Custom',
+ name: 'Custom Section',
+ js: '/App_Plugins/section.js',
+ elementName: 'my-section-custom',
+ weight: 1,
+ meta: {
+ label: 'Custom',
+ pathname: 'my-custom',
+ },
},
- },
- ],
- },
- {
- name: 'Package with an entry point',
- extensions: [
- {
- type: 'entryPoint',
- name: 'My Custom Entry Point',
- alias: 'My.Entrypoint.Custom',
- js: '/App_Plugins/custom-entrypoint.js',
- },
- ],
- },
- {
- name: 'Package with a view',
- extensions: [
- {
- type: 'packageView',
- alias: 'My.PackageView.Custom',
- name: 'My Custom Package View',
- js: '/App_Plugins/package-view.js',
- meta: {
- packageName: 'Package with a view',
+ {
+ type: 'propertyEditorUi',
+ alias: 'My.PropertyEditorUI.Custom',
+ name: 'My Custom Property Editor UI',
+ js: '/App_Plugins/property-editor.js',
+ elementName: 'my-property-editor-ui-custom',
+ meta: {
+ label: 'My Custom Property',
+ icon: 'document',
+ group: 'Common',
+ propertyEditorSchema: 'Umbraco.TextBox',
+ },
},
- },
- ],
- },
- {
- name: 'My MFA Package',
- extensions: [
- {
- type: 'mfaLoginProvider',
- alias: 'My.MfaLoginProvider.Custom',
- name: 'My Custom MFA Provider',
- forProviderName: 'sms',
- meta: {
- label: 'Setup SMS Verification',
+ ],
+ },
+ {
+ name: 'Package with an entry point',
+ extensions: [
+ {
+ type: 'entryPoint',
+ name: 'My Custom Entry Point',
+ alias: 'My.Entrypoint.Custom',
+ js: '/App_Plugins/custom-entrypoint.js',
},
- },
- ],
- },
- {
- name: 'My Auth Package',
- extensions: [
- {
- type: 'authProvider',
- alias: 'My.AuthProvider.Google',
- name: 'My Custom Auth Provider',
- forProviderName: 'Umbraco.Google',
- meta: {
- label: 'Sign in with Google',
+ ],
+ },
+ {
+ name: 'Package with a view',
+ extensions: [
+ {
+ type: 'packageView',
+ alias: 'My.PackageView.Custom',
+ name: 'My Custom Package View',
+ js: '/App_Plugins/package-view.js',
+ meta: {
+ packageName: 'Package with a view',
+ },
},
- },
- {
- type: 'authProvider',
- alias: 'My.AUthProvider.Github',
- name: 'My Github Auth Provider',
- forProviderName: 'Umbraco.Github',
- meta: {
- label: 'Use Github!',
- look: 'primary',
- icon: 'icon-github',
- color: 'success',
+ ],
+ },
+ {
+ name: 'My MFA Package',
+ extensions: [
+ {
+ type: 'mfaLoginProvider',
+ alias: 'My.MfaLoginProvider.Custom',
+ name: 'My Custom MFA Provider',
+ forProviderName: 'sms',
+ meta: {
+ label: 'Setup SMS Verification',
+ },
},
- },
- ],
- },
- ]),
- );
-});
+ ],
+ },
+ ]),
+ );
+ }),
+ rest.get(umbracoPath('/package/manifest/public'), (_req, res, ctx) => {
+ return res(
+ ctx.status(200),
+ ctx.json([
+ {
+ name: 'My Auth Package',
+ extensions: [
+ {
+ type: 'authProvider',
+ alias: 'My.AuthProvider.Google',
+ name: 'My Custom Auth Provider',
+ forProviderName: 'Umbraco.Google',
+ meta: {
+ label: 'Sign in with Google',
+ },
+ },
+ {
+ type: 'authProvider',
+ alias: 'My.AUthProvider.Github',
+ name: 'My Github Auth Provider',
+ forProviderName: 'Umbraco.Github',
+ meta: {
+ label: 'Use Github!',
+ look: 'primary',
+ icon: 'icon-github',
+ color: 'success',
+ },
+ },
+ ],
+ },
+ ]),
+ );
+ }),
+];
-export const manifestEmptyHandler = rest.get(umbracoPath('/package/manifest'), (_req, res, ctx) => {
- return res(
- // Respond with a 200 status code
- ctx.status(200),
- ctx.json([]),
- );
-});
+export const manifestEmptyHandlers = [
+ rest.get(umbracoPath('/package/manifest'), (_req, res, ctx) => {
+ return res(ctx.status(200), ctx.json([]));
+ }),
+ rest.get(umbracoPath('/package/manifest/public'), (_req, res, ctx) => {
+ return res(ctx.status(200), ctx.json([]));
+ }),
+];
From cc1bb06379061961c602896c17529df70ead318a Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 15:32:32 +0200
Subject: [PATCH 092/280] dont send cookies to the backend
---
src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
index 6d3070339e..95f3a81072 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
@@ -145,7 +145,6 @@ export class UmbAppElement extends UmbLitElement {
// Instruct all requests to use the auth flow to get and use the access_token for all subsequent requests
OpenAPI.TOKEN = () => this.#authContext!.getLatestToken();
OpenAPI.WITH_CREDENTIALS = true;
- OpenAPI.CREDENTIALS = 'include';
}
#redirect() {
From 2fe52cd500a2ad096f617800cdef5870697f51be Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 15:40:14 +0200
Subject: [PATCH 093/280] remove todo
---
src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
index 95f3a81072..36c88357c3 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
@@ -40,7 +40,6 @@ export class UmbAppElement extends UmbLitElement {
* @attr
*/
@property({ type: String })
- // TODO: get from base element or maybe move to UmbAuthContext.#getRedirectUrl since it is only used there
backofficePath = '/umbraco';
/**
From 184e498bc2fe07e0908c42b675673930de52ba50 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 16:02:35 +0200
Subject: [PATCH 094/280] initialize controllers only when it makes sense
---
.../src/apps/app/app.element.ts | 12 ++++++++++--
.../src/apps/backoffice/backoffice.element.ts | 7 -------
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
index 36c88357c3..91fff747cd 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
@@ -20,6 +20,13 @@ import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registr
@customElement('umb-app')
export class UmbAppElement extends UmbLitElement {
+ /**
+ * Backoffice extension registry.
+ * This enables to register and unregister extensions via DevTools, or just via querying this element via the DOM.
+ * @type {UmbExtensionsRegistry}
+ */
+ public extensionRegistry = umbExtensionsRegistry;
+
/**
* The base URL of the configured Umbraco server.
*
@@ -69,7 +76,7 @@ export class UmbAppElement extends UmbLitElement {
#umbIconRegistry = new UmbIconRegistry();
#uuiIconRegistry = new UUIIconRegistryEssential();
#serverConnection?: UmbServerConnection;
- #authController = new UmbAppAuthController(this);
+ #authController?: UmbAppAuthController;
constructor() {
super();
@@ -91,6 +98,7 @@ export class UmbAppElement extends UmbLitElement {
}
async #setup() {
+ this.#authController = new UmbAppAuthController(this);
this.#serverConnection = await new UmbServerConnection(this.serverUrl).connect();
this.#authContext = new UmbAuthContext(this, this.serverUrl, this.backofficePath, this.bypassAuth);
@@ -191,7 +199,7 @@ export class UmbAppElement extends UmbLitElement {
}
#isAuthorizedGuard(): Guard {
- return () => this.#authController.isAuthorized();
+ return () => this.#authController?.isAuthorized() ?? false;
}
#errorPage(errorMsg: string, error?: unknown) {
diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts
index 407e04a759..5e42145a82 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts
@@ -38,13 +38,6 @@ const CORE_PACKAGES = [
@customElement('umb-backoffice')
export class UmbBackofficeElement extends UmbLitElement {
- /**
- * Backoffice extension registry.
- * This enables to register and unregister extensions via DevTools, or just via querying this element via the DOM.
- * @type {UmbExtensionsRegistry}
- */
- public extensionRegistry = umbExtensionsRegistry;
-
constructor() {
super();
From 39cdeb261f1deb45e4681e02ab72caab60405cca Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 16:41:03 +0200
Subject: [PATCH 095/280] add types and js docs
---
.../recycle-bin-repository-base.ts | 48 +++++++++++++++++--
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository-base.ts
index ac12e66d1c..1dd19e0809 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository-base.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/recycle-bin-repository-base.ts
@@ -3,19 +3,44 @@ import type {
UmbRecycleBinDataSource,
UmbRecycleBinDataSourceConstructor,
} from './recycle-bin-data-source.interface.js';
+import type {
+ UmbRecycleBinOriginalParentRequestArgs,
+ UmbRecycleBinRestoreRequestArgs,
+ UmbRecycleBinTrashRequestArgs,
+} from './types.js';
import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository';
+/**
+ * Base class for recycle bin repositories.
+ * @export
+ * @abstract
+ * @class UmbRecycleBinRepositoryBase
+ * @extends {UmbRepositoryBase}
+ * @implements {UmbRecycleBinRepository}
+ */
export abstract class UmbRecycleBinRepositoryBase extends UmbRepositoryBase implements UmbRecycleBinRepository {
#recycleBinSource: UmbRecycleBinDataSource;
+ /**
+ * Creates an instance of UmbRecycleBinRepositoryBase.
+ * @param {UmbControllerHost} host
+ * @param {UmbRecycleBinDataSourceConstructor} recycleBinSource
+ * @memberof UmbRecycleBinRepositoryBase
+ */
constructor(host: UmbControllerHost, recycleBinSource: UmbRecycleBinDataSourceConstructor) {
super(host);
this.#recycleBinSource = new recycleBinSource(this);
}
- async requestTrash(args: any) {
+ /**
+ * Requests to trash an item.
+ * @param {UmbRecycleBinTrashRequestArgs} args
+ * @return {*}
+ * @memberof UmbRecycleBinRepositoryBase
+ */
+ async requestTrash(args: UmbRecycleBinTrashRequestArgs) {
const { error } = await this.#recycleBinSource.trash(args);
if (!error) {
@@ -27,7 +52,13 @@ export abstract class UmbRecycleBinRepositoryBase extends UmbRepositoryBase impl
return { error };
}
- async requestRestore(args: any) {
+ /**
+ * Requests to restore an item.
+ * @param {UmbRecycleBinRestoreRequestArgs} args
+ * @return {*}
+ * @memberof UmbRecycleBinRepositoryBase
+ */
+ async requestRestore(args: UmbRecycleBinRestoreRequestArgs) {
const { error } = await this.#recycleBinSource.restore(args);
if (!error) {
@@ -39,6 +70,11 @@ export abstract class UmbRecycleBinRepositoryBase extends UmbRepositoryBase impl
return { error };
}
+ /**
+ * Requests to empty the recycle bin.
+ * @return {*}
+ * @memberof UmbRecycleBinRepositoryBase
+ */
async requestEmpty() {
const { error } = await this.#recycleBinSource.empty();
@@ -51,7 +87,13 @@ export abstract class UmbRecycleBinRepositoryBase extends UmbRepositoryBase impl
return this.#recycleBinSource.empty();
}
- async requestOriginalParent(args: any) {
+ /**
+ * Requests the original parent of an item.
+ * @param {UmbRecycleBinOriginalParentRequestArgs} args
+ * @return {*}
+ * @memberof UmbRecycleBinRepositoryBase
+ */
+ async requestOriginalParent(args: UmbRecycleBinOriginalParentRequestArgs) {
return this.#recycleBinSource.getOriginalParent(args);
}
}
From 651751d390bbdbcb5db478ecf2ddeabc9518c974 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 16:44:13 +0200
Subject: [PATCH 096/280] add js docs
---
.../empty-recycle-bin/empty-recycle-bin.action.ts | 11 ++++++++++-
.../restore-from-recycle-bin.action.ts | 10 ++++++++++
.../entity-action/trash/trash.action.ts | 15 ++++++++++++---
3 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts
index d2059161be..acc0562252 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/empty-recycle-bin/empty-recycle-bin.action.ts
@@ -1,5 +1,4 @@
import { UmbEntityActionBase } from '../../../entity-action/entity-action-base.js';
-import { UmbRequestReloadStructureForEntityEvent } from '../../../entity-action/request-reload-structure-for-entity.event.js';
import type { UmbRecycleBinRepository } from '../../recycle-bin-repository.interface.js';
import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
import {
@@ -9,7 +8,17 @@ import {
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
import { UmbReloadTreeItemChildrenRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree';
+/**
+ * Entity action for emptying the recycle bin.
+ * @export
+ * @class UmbEmptyRecycleBinEntityAction
+ * @extends {UmbEntityActionBase}
+ */
export class UmbEmptyRecycleBinEntityAction extends UmbEntityActionBase {
+ /**
+ * Executes the action.
+ * @memberof UmbEmptyRecycleBinEntityAction
+ */
async execute() {
await umbConfirmModal(this._host, {
headline: `Empty Recycle Bin`,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
index 5910d4df6a..699c4ce03e 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
@@ -5,7 +5,17 @@ import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
import type { MetaEntityActionRestoreFromRecycleBinKind } from '@umbraco-cms/backoffice/extension-registry';
+/**
+ * Entity action for restoring an item from the recycle bin.
+ * @export
+ * @class UmbRestoreFromRecycleBinEntityAction
+ * @extends {UmbEntityActionBase}
+ */
export class UmbRestoreFromRecycleBinEntityAction extends UmbEntityActionBase {
+ /**
+ * Executes the action.
+ * @memberof UmbRestoreFromRecycleBinEntityAction
+ */
async execute() {
if (!this.args.unique) throw new Error('Cannot restore an item without a unique identifier.');
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts
index f1c9bbee35..14e29f7f11 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.ts
@@ -7,9 +7,17 @@ import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
import type { UmbItemRepository } from '@umbraco-cms/backoffice/repository';
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
+/**
+ * Entity action for trashing an item.
+ * @export
+ * @class UmbTrashEntityAction
+ * @extends {UmbEntityActionBase}
+ */
export class UmbTrashEntityAction extends UmbEntityActionBase {
- // TODO: make base type for item and detail models
-
+ /**
+ * Executes the action.
+ * @memberof UmbTrashEntityAction
+ */
async execute() {
if (!this.args.unique) throw new Error('Cannot trash an item without a unique identifier.');
@@ -47,4 +55,5 @@ export class UmbTrashEntityAction extends UmbEntityActionBase
Date: Thu, 4 Apr 2024 16:50:02 +0200
Subject: [PATCH 097/280] create modal to show auth providers
---
.../src/packages/core/auth/index.ts | 1 +
.../src/packages/core/auth/manifests.ts | 4 ++++
.../src/packages/core/auth/modals/index.ts | 1 +
.../src/packages/core/auth/modals/manifests.ts | 10 ++++++++++
.../auth/modals/umb-app-auth-modal.element.ts | 17 +++++++++++++++++
.../auth/modals/umb-app-auth-modal.token.ts | 8 ++++++++
.../src/packages/core/manifests.ts | 2 ++
7 files changed, 43 insertions(+)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/auth/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.token.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts
index e6dc7d478d..e99e9b0dcf 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts
@@ -1,3 +1,4 @@
export * from './auth.context.js';
export * from './auth.context.token.js';
+export * from './modals/index.js';
export * from './models/openApiConfiguration.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/manifests.ts
new file mode 100644
index 0000000000..8ba79428c9
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/manifests.ts
@@ -0,0 +1,4 @@
+import type { ManifestTypes } from '../extension-registry/models/index.js';
+import { manifests as modalManifests } from './modals/manifests.js';
+
+export const manifests: Array = [...modalManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/index.ts
new file mode 100644
index 0000000000..c574cd0af1
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/index.ts
@@ -0,0 +1 @@
+export * from './umb-app-auth-modal.token.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/manifests.ts
new file mode 100644
index 0000000000..315736dd1f
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/manifests.ts
@@ -0,0 +1,10 @@
+import type { ManifestModal } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifests: Array = [
+ {
+ type: 'modal',
+ alias: 'Umb.Modal.AppAuth',
+ name: 'Umb App Auth Modal',
+ js: () => import('./umb-app-auth-modal.element.js'),
+ },
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts
new file mode 100644
index 0000000000..1f8418e3ca
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts
@@ -0,0 +1,17 @@
+import { customElement, html } from '@umbraco-cms/backoffice/external/lit';
+import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
+
+@customElement('umb-app-auth-modal')
+export class UmbAppAuthModalElement extends UmbLitElement {
+ render() {
+ return html`Umb App Auth Modal `;
+ }
+}
+
+export default UmbAppAuthModalElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-app-auth-modal': UmbAppAuthModalElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.token.ts
new file mode 100644
index 0000000000..4b4e39656b
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.token.ts
@@ -0,0 +1,8 @@
+import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
+
+export const UMB_MODAL_APP_AUTH = new UmbModalToken('Umb.Modal.AppAuth', {
+ modal: {
+ size: 'small',
+ type: 'dialog',
+ },
+});
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts
index 66d11f9961..d80662cc2c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts
@@ -1,3 +1,4 @@
+import { manifests as authManifests } from './auth/manifests.js';
import { manifests as collectionManifests } from './collection/manifests.js';
import { manifests as contentTypeManifests } from './content-type/manifests.js';
import { manifests as cultureManifests } from './culture/manifests.js';
@@ -18,6 +19,7 @@ import { manifests as workspaceManifests } from './workspace/manifests.js';
import type { ManifestTypes, UmbBackofficeManifestKind } from './extension-registry/index.js';
export const manifests: Array = [
+ ...authManifests,
...collectionManifests,
...contentTypeManifests,
...cultureManifests,
From 5c8c0dd15eeee9aec22006a90c0d6cb0e6b7d266 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 16:50:23 +0200
Subject: [PATCH 098/280] load core extensions in app element
---
src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts | 3 +++
.../src/apps/backoffice/backoffice.element.ts | 1 -
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
index 91fff747cd..3e3dea0b60 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
@@ -1,3 +1,4 @@
+import { extensions as coreExtensions } from '../../packages/core/umbraco-package.js';
import type { UmbAppErrorElement } from './app-error.element.js';
import { UmbAppContext } from './app.context.js';
import { UmbServerConnection } from './server-connection.js';
@@ -90,6 +91,8 @@ export class UmbAppElement extends UmbLitElement {
this.#umbIconRegistry.attach(this);
this.#uuiIconRegistry.attach(this);
+
+ umbExtensionsRegistry.registerMany(coreExtensions);
}
connectedCallback(): void {
diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts
index 5e42145a82..ae2d293e3e 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts
@@ -10,7 +10,6 @@ import './components/index.js';
const CORE_PACKAGES = [
import('../../packages/audit-log/umbraco-package.js'),
import('../../packages/block/umbraco-package.js'),
- import('../../packages/core/umbraco-package.js'),
import('../../packages/data-type/umbraco-package.js'),
import('../../packages/dictionary/umbraco-package.js'),
import('../../packages/documents/umbraco-package.js'),
From 94c3d5fca8983074087382adaff9da2143dbcb84 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Thu, 4 Apr 2024 16:50:38 +0200
Subject: [PATCH 099/280] add check to see if any auth providers are registered
---
.../src/apps/app/app-auth.controller.ts | 29 +++++++++++++++++--
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
index 9d0c7983c9..dba8a08626 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
@@ -1,8 +1,10 @@
-import { UMB_AUTH_CONTEXT, UMB_STORAGE_REDIRECT_URL } from '@umbraco-cms/backoffice/auth';
+import { UMB_AUTH_CONTEXT, UMB_MODAL_APP_AUTH, UMB_STORAGE_REDIRECT_URL } from '@umbraco-cms/backoffice/auth';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbServerExtensionRegistrator } from '@umbraco-cms/backoffice/extension-api';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
+import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs';
+import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
export class UmbAppAuthController extends UmbControllerBase {
#authContext?: typeof UMB_AUTH_CONTEXT.TYPE;
@@ -52,11 +54,32 @@ export class UmbAppAuthController extends UmbControllerBase {
await this.#init;
- this.#authContext.makeAuthorizationRequest();
+ // Figure out which providers are available
+ const availableProviders = await firstValueFrom(umbExtensionsRegistry.byType('authProvider'));
+ if (availableProviders.length === 0) {
+ // No providers available, initiate the authorization request to the default provider
+ this.#authContext.makeAuthorizationRequest();
+ } else {
+ // Check if any provider is redirecting directly to the provider, and if so, redirect to that provider
+ const redirectProvider = availableProviders.find((provider) => provider.meta?.autoRedirect);
+ if (redirectProvider) {
+ this.#authContext.makeAuthorizationRequest(redirectProvider.forProviderName);
+ return true;
+ }
+
+ // Show the provider selection screen
+ console.log('show modal for', availableProviders);
+ const modalContext = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
+ await modalContext
+ .open(this._host, UMB_MODAL_APP_AUTH)
+ .onSubmit()
+ .catch(() => undefined);
+ }
// Reinitialize the auth flow (load the state from local storage)
this.#authContext.setInitialState();
- return true;
+ // The authorization flow is finished, so let the caller know if the user is authorized
+ return this.#authContext.getIsAuthorized();
}
}
From aca4f640bd4ec6c6cacceb12c63710ba80d3ab15 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 4 Apr 2024 16:53:14 +0200
Subject: [PATCH 100/280] bump trash action weight
---
.../core/recycle-bin/entity-action/trash/trash.action.kind.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.kind.ts
index fa78c1185b..1b2b310a40 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.kind.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/trash/trash.action.kind.ts
@@ -11,7 +11,7 @@ export const manifest: UmbBackofficeManifestKind = {
type: 'entityAction',
kind: 'trash',
api: () => import('./trash.action.js'),
- weight: 1050,
+ weight: 1150,
forEntityTypes: [],
meta: {
icon: 'icon-trash',
From 9c4bbed87c4581e075b21c1772cb9a11f2f70a13 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 08:59:30 +0200
Subject: [PATCH 101/280] extend the auth provider model
---
.../models/auth-provider.model.ts | 30 ++++++++++++++-----
1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/auth-provider.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/auth-provider.model.ts
index e212a5208e..1abff595fd 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/auth-provider.model.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/auth-provider.model.ts
@@ -29,7 +29,7 @@ export interface MetaAuthProvider {
* The default view of the provider that is shown to the user.
* If no element is provided, then the button will be rendered as a @see {UUIButtonElement} using these options.
*/
- defaultView: {
+ defaultView?: {
/**
* The icon of the provider that is shown to the user.
* @examples ['icon-cloud', 'icon-github', 'icon-google', 'icon-facebook', 'icon-twitter', 'icon-x', 'icon-microsoft']
@@ -51,14 +51,30 @@ export interface MetaAuthProvider {
};
/**
- * If true, the Umbraco backoffice login will be disabled.
- * @default false
+ * The behavior of the provider when it is used.
*/
- denyLocalLogin?: boolean;
+ behavior?: {
+ /**
+ * If true, the Umbraco backoffice login will be disabled.
+ * @default false
+ */
+ denyLocalLogin?: boolean;
+
+ /**
+ * If true, the user will be redirected to the provider's login page immediately.
+ * @default false
+ */
+ autoRedirect?: boolean;
+ };
/**
- * If true, the user will be redirected to the provider's login page immediately.
- * @default false
+ * The linking options of the provider when it is used.
*/
- autoRedirect?: boolean;
+ linking?: {
+ /**
+ * If true, the user will be able to link the provider to an existing account.
+ * @default false
+ */
+ allowManualLinking?: boolean;
+ };
}
From 307c9b37e6b94b41cb5192ebfe6fd6fb1813113e Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 09:50:50 +0200
Subject: [PATCH 102/280] register Umbraco as a provider
---
.../src/packages/core/auth/manifests.ts | 3 ++-
.../src/packages/core/auth/providers/manifests.ts | 14 ++++++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/auth/providers/manifests.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/manifests.ts
index 8ba79428c9..f0f6228203 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/manifests.ts
@@ -1,4 +1,5 @@
import type { ManifestTypes } from '../extension-registry/models/index.js';
import { manifests as modalManifests } from './modals/manifests.js';
+import { manifests as providerManifests } from './providers/manifests.js';
-export const manifests: Array = [...modalManifests];
+export const manifests: Array = [...modalManifests, ...providerManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/providers/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/providers/manifests.ts
new file mode 100644
index 0000000000..29f9ca30f6
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/providers/manifests.ts
@@ -0,0 +1,14 @@
+import type { ManifestAuthProvider } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifests: Array = [
+ {
+ type: 'authProvider',
+ alias: 'Umb.AuthProviders.Umbraco',
+ name: 'Umbraco login provider',
+ forProviderName: 'Umbraco',
+ weight: 1000,
+ meta: {
+ label: 'Umbraco',
+ },
+ },
+];
From 9c4bb5ba7773d048c834e6b9fba902d87042b83a Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 09:51:30 +0200
Subject: [PATCH 103/280] let the auth context know when exactly its container
extension has been loaded and use it to return the providers
---
.../src/packages/core/auth/auth.context.ts | 13 +++++++++++++
.../src/packages/core/index.ts | 6 ++++++
2 files changed, 19 insertions(+)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts
index f5a64ff438..a46deed70d 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts
@@ -1,3 +1,4 @@
+import { umbExtensionsRegistry } from '../extension-registry/index.js';
import { UmbAuthFlow } from './auth-flow.js';
import { UMB_AUTH_CONTEXT } from './auth.context.token.js';
import type { UmbOpenApiConfiguration } from './models/openApiConfiguration.js';
@@ -5,11 +6,15 @@ import { OpenAPI } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api';
+import { ReplaySubject, filter, switchMap } from '@umbraco-cms/backoffice/external/rxjs';
export class UmbAuthContext extends UmbContextBase {
#isAuthorized = new UmbBooleanState(false);
readonly isAuthorized = this.#isAuthorized.asObservable();
+ #isInitialized = new ReplaySubject(1);
+ readonly isInitialized = this.#isInitialized.asObservable().pipe(filter((isInitialized) => isInitialized));
+
#isBypassed = false;
#serverUrl;
#backofficePath;
@@ -143,6 +148,14 @@ export class UmbAuthContext extends UmbContextBase {
};
}
+ setInitialized() {
+ this.#isInitialized.next(true);
+ }
+
+ getAuthProviders() {
+ return this.isInitialized.pipe(switchMap(() => umbExtensionsRegistry.byType('authProvider')));
+ }
+
#getRedirectUrl() {
return `${window.location.origin}${this.#backofficePath}`;
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/index.ts
index 1896412056..7db1162c20 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/index.ts
@@ -1,3 +1,4 @@
+import { UMB_AUTH_CONTEXT } from './auth/auth.context.token.js';
import { UmbBackofficeNotificationContainerElement, UmbBackofficeModalContainerElement } from './components/index.js';
import { UmbActionEventContext } from './action/action-event.context.js';
import { manifests as coreManifests } from './manifests.js';
@@ -46,4 +47,9 @@ export const onInit: UmbEntryPointOnInit = (host, extensionRegistry) => {
new UmbNotificationContext(host);
new UmbModalManagerContext(host);
new UmbActionEventContext(host);
+
+ host.consumeContext(UMB_AUTH_CONTEXT, (authContext) => {
+ // Initialize the auth context to let the app context know that the core module is ready
+ authContext.setInitialized();
+ });
};
From ced4abd1c2905a81034268b32fd8c54388ec6e0b Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 09:51:59 +0200
Subject: [PATCH 104/280] let the app element initiate the public server
extensions and wait to new up the auth controller until auth is required
(i.e. not in install mode)
---
src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
index 3e3dea0b60..80be3c84e1 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts
@@ -16,6 +16,7 @@ import { UmbContextDebugController } from '@umbraco-cms/backoffice/debug';
import {
UmbBundleExtensionInitializer,
UmbEntryPointExtensionInitializer,
+ UmbServerExtensionRegistrator,
} from '@umbraco-cms/backoffice/extension-api';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
@@ -101,12 +102,13 @@ export class UmbAppElement extends UmbLitElement {
}
async #setup() {
- this.#authController = new UmbAppAuthController(this);
this.#serverConnection = await new UmbServerConnection(this.serverUrl).connect();
this.#authContext = new UmbAuthContext(this, this.serverUrl, this.backofficePath, this.bypassAuth);
new UmbAppContext(this, { backofficePath: this.backofficePath, serverUrl: this.serverUrl });
+ await new UmbServerExtensionRegistrator(this, umbExtensionsRegistry).registerPublicExtensions();
+
// Try to initialise the auth flow and get the runtime status
try {
// If the runtime level is "install" we should clear any cached tokens
@@ -114,6 +116,7 @@ export class UmbAppElement extends UmbLitElement {
if (this.#serverConnection.getStatus() === RuntimeLevelModel.INSTALL) {
await this.#authContext.clearTokenStorage();
} else {
+ this.#authController = new UmbAppAuthController(this);
await this.#setAuthStatus();
}
From 5e0916bb11bee7cc71930d167a87c6df6142efb8 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 09:52:15 +0200
Subject: [PATCH 105/280] let the auth controller use the auth context to fetch
the providers
---
.../src/apps/app/app-auth.controller.ts | 52 +++++++++++--------
1 file changed, 29 insertions(+), 23 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
index dba8a08626..290508e72a 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
@@ -1,15 +1,11 @@
import { UMB_AUTH_CONTEXT, UMB_MODAL_APP_AUTH, UMB_STORAGE_REDIRECT_URL } from '@umbraco-cms/backoffice/auth';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
-import { UmbServerExtensionRegistrator } from '@umbraco-cms/backoffice/extension-api';
-import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
export class UmbAppAuthController extends UmbControllerBase {
#authContext?: typeof UMB_AUTH_CONTEXT.TYPE;
- #serverExtensionRegistrator = new UmbServerExtensionRegistrator(this, umbExtensionsRegistry);
- #init;
constructor(host: UmbControllerHost) {
super(host);
@@ -17,8 +13,6 @@ export class UmbAppAuthController extends UmbControllerBase {
this.consumeContext(UMB_AUTH_CONTEXT, (context) => {
this.#authContext = context;
});
-
- this.#init = Promise.all([this.#serverExtensionRegistrator.registerPublicExtensions()]);
}
/**
@@ -52,28 +46,40 @@ export class UmbAppAuthController extends UmbControllerBase {
throw new Error('[Fatal] Auth context is not available');
}
- await this.#init;
-
// Figure out which providers are available
- const availableProviders = await firstValueFrom(umbExtensionsRegistry.byType('authProvider'));
+ const availableProviders = await firstValueFrom(this.#authContext.getAuthProviders());
+
if (availableProviders.length === 0) {
- // No providers available, initiate the authorization request to the default provider
+ throw new Error('[Fatal] No auth providers available');
+ }
+
+ if (availableProviders.length === 1) {
+ // One provider available (most likely the Umbraco provider), so initiate the authorization request to the default provider
this.#authContext.makeAuthorizationRequest();
} else {
- // Check if any provider is redirecting directly to the provider, and if so, redirect to that provider
- const redirectProvider = availableProviders.find((provider) => provider.meta?.autoRedirect);
- if (redirectProvider) {
- this.#authContext.makeAuthorizationRequest(redirectProvider.forProviderName);
- return true;
- }
+ // Check if any provider is redirecting directly to the provider
+ const redirectProvider = availableProviders.find((provider) => provider.meta?.behavior?.autoRedirect);
- // Show the provider selection screen
- console.log('show modal for', availableProviders);
- const modalContext = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
- await modalContext
- .open(this._host, UMB_MODAL_APP_AUTH)
- .onSubmit()
- .catch(() => undefined);
+ if (redirectProvider) {
+ // Redirect directly to the provider
+ this.#authContext.makeAuthorizationRequest(redirectProvider.forProviderName);
+ } else {
+ // Show the provider selection screen
+ console.log('show modal for', availableProviders);
+ const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
+ await modalManager
+ .open(this._host, UMB_MODAL_APP_AUTH)
+ .onSubmit()
+ .catch(() => undefined);
+ }
+ }
+
+ return this.#updateState();
+ }
+
+ #updateState() {
+ if (!this.#authContext) {
+ throw new Error('[Fatal] Auth context is not available');
}
// Reinitialize the auth flow (load the state from local storage)
From c0bb2d3d9795d75593cd01be44268df9d597a51d Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 10:17:43 +0200
Subject: [PATCH 106/280] append to shadowRoot
---
src/Umbraco.Web.UI.Client/src/packages/core/index.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/index.ts
index 7db1162c20..3e424e1398 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/index.ts
@@ -39,10 +39,10 @@ export const onInit: UmbEntryPointOnInit = (host, extensionRegistry) => {
extensionRegistry.registerMany(coreManifests);
const notificationContainerElement = new UmbBackofficeNotificationContainerElement();
- host.appendChild(notificationContainerElement);
+ host.shadowRoot?.appendChild(notificationContainerElement);
const modalContainerElement = new UmbBackofficeModalContainerElement();
- host.appendChild(modalContainerElement);
+ host.shadowRoot?.appendChild(modalContainerElement);
new UmbNotificationContext(host);
new UmbModalManagerContext(host);
From abc1a9f32ec997b7e187681ee10e7f3db42cfaf0 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 12:08:42 +0200
Subject: [PATCH 107/280] add more to default provider
---
.../src/apps/app/app-auth.controller.ts | 9 +++++++--
.../src/packages/core/auth/providers/manifests.ts | 5 ++++-
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
index 290508e72a..0c2eac7678 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
@@ -65,12 +65,17 @@ export class UmbAppAuthController extends UmbControllerBase {
this.#authContext.makeAuthorizationRequest(redirectProvider.forProviderName);
} else {
// Show the provider selection screen
- console.log('show modal for', availableProviders);
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
- await modalManager
+ const selected = await modalManager
.open(this._host, UMB_MODAL_APP_AUTH)
.onSubmit()
.catch(() => undefined);
+
+ if (!selected?.providerName) {
+ return false;
+ }
+
+ this.#authContext.makeAuthorizationRequest(selected.providerName);
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/providers/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/providers/manifests.ts
index 29f9ca30f6..f1f2f89b41 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/providers/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/providers/manifests.ts
@@ -8,7 +8,10 @@ export const manifests: Array = [
forProviderName: 'Umbraco',
weight: 1000,
meta: {
- label: 'Umbraco',
+ label: 'Sign in with Umbraco',
+ defaultView: {
+ look: 'primary',
+ },
},
},
];
From 59d372249098ce1708e1722881e830eeaa23bac9 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 12:08:50 +0200
Subject: [PATCH 108/280] fix typo for typings
---
.../core/extension-registry/models/auth-provider.model.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/auth-provider.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/auth-provider.model.ts
index 1abff595fd..116be49a73 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/auth-provider.model.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/auth-provider.model.ts
@@ -41,13 +41,13 @@ export interface MetaAuthProvider {
* The color of the provider that is shown to the user.
* @default 'secondary'
*/
- color?: UUIInterfaceLook;
+ color?: UUIInterfaceColor;
/**
* The look of the provider that is shown to the user.
* @default 'default'
*/
- look?: UUIInterfaceColor;
+ look?: UUIInterfaceLook;
};
/**
From fe40efdf1da993467b25f4eb6c6ef95ebb049587 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 12:09:12 +0200
Subject: [PATCH 109/280] show a modal when more than 1 provider and add a
default element if nothing is provided
---
.../auth-provider-default.element.ts | 50 +++++++++++++++++++
.../packages/core/auth/components/index.ts | 1 +
.../src/packages/core/auth/index.ts | 3 ++
.../auth/modals/umb-app-auth-modal.element.ts | 40 +++++++++++++--
.../auth/modals/umb-app-auth-modal.token.ts | 7 ++-
5 files changed, 94 insertions(+), 7 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/auth/components/auth-provider-default.element.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/auth/components/index.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/auth-provider-default.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/auth-provider-default.element.ts
new file mode 100644
index 0000000000..58e04c5797
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/auth-provider-default.element.ts
@@ -0,0 +1,50 @@
+import type { ManifestAuthProvider } from '../../index.js';
+import { UmbLitElement } from '../../lit-element/lit-element.element.js';
+import { UmbTextStyles } from '../../style/index.js';
+import { css, customElement, html, nothing, property } from '@umbraco-cms/backoffice/external/lit';
+
+@customElement('umb-auth-provider-default')
+export class UmbAuthProviderDefaultElement extends UmbLitElement {
+ @property({ attribute: false })
+ manifest!: ManifestAuthProvider;
+
+ @property({ attribute: false })
+ onSubmit!: (providerName: string) => void;
+
+ render() {
+ return html`
+ this.onSubmit(this.manifest.forProviderName)}
+ id="auth-provider-button"
+ .label=${this.manifest.meta?.label ?? this.manifest.forProviderName}
+ .look=${this.manifest.meta?.defaultView?.look ?? 'outline'}
+ .color=${this.manifest.meta?.defaultView?.color ?? 'default'}>
+ ${this.manifest.meta?.defaultView?.icon
+ ? html` `
+ : nothing}
+ ${this.manifest.meta?.label ?? this.manifest.forProviderName}
+
+ `;
+ }
+
+ static styles = [
+ UmbTextStyles,
+ css`
+ :host {
+ display: block;
+ padding: 20px;
+ }
+
+ #auth-provider-button {
+ width: 100%;
+ }
+ `,
+ ];
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-auth-provider-default': UmbAuthProviderDefaultElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/index.ts
new file mode 100644
index 0000000000..e5fdd6f189
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/index.ts
@@ -0,0 +1 @@
+export * from './auth-provider-default.element.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts
index e99e9b0dcf..e05fbbb7ed 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts
@@ -1,4 +1,7 @@
+import './components/index.js';
+
export * from './auth.context.js';
export * from './auth.context.token.js';
export * from './modals/index.js';
export * from './models/openApiConfiguration.js';
+export * from './components/index.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts
index 1f8418e3ca..69b3b8b8ef 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts
@@ -1,11 +1,41 @@
-import { customElement, html } from '@umbraco-cms/backoffice/external/lit';
-import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
+import { UmbModalBaseElement } from '../../modal/index.js';
+import type { UmbModalAppAuthValue } from './umb-app-auth-modal.token.js';
+import { css, customElement, html } from '@umbraco-cms/backoffice/external/lit';
+import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
@customElement('umb-app-auth-modal')
-export class UmbAppAuthModalElement extends UmbLitElement {
- render() {
- return html`Umb App Auth Modal `;
+export class UmbAppAuthModalElement extends UmbModalBaseElement {
+ get props() {
+ return {
+ onSubmit: this.onSubmit,
+ };
}
+
+ render() {
+ return html`
+
+
+
+ `;
+ }
+
+ private onSubmit = (providerName: string) => {
+ this.value = { providerName };
+ this._submitModal();
+ };
+
+ static styles = [
+ UmbTextStyles,
+ css`
+ :host {
+ display: block;
+ padding: 20px;
+ }
+ `,
+ ];
}
export default UmbAppAuthModalElement;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.token.ts
index 4b4e39656b..20ce925dd9 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.token.ts
@@ -1,8 +1,11 @@
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
-export const UMB_MODAL_APP_AUTH = new UmbModalToken('Umb.Modal.AppAuth', {
+export type UmbModalAppAuthValue = {
+ providerName?: string;
+};
+
+export const UMB_MODAL_APP_AUTH = new UmbModalToken('Umb.Modal.AppAuth', {
modal: {
- size: 'small',
type: 'dialog',
},
});
From f46f7bb459e5ce07daea7cca3762be2080bd0ed4 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 13:24:40 +0200
Subject: [PATCH 110/280] adjust size and color
---
.../core/auth/modals/umb-app-auth-modal.element.ts | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts
index 69b3b8b8ef..5acc1ebe77 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts
@@ -13,8 +13,9 @@ export class UmbAppAuthModalElement extends UmbModalBaseElement
+
@@ -33,6 +34,12 @@ export class UmbAppAuthModalElement extends UmbModalBaseElement
Date: Fri, 5 Apr 2024 13:24:48 +0200
Subject: [PATCH 111/280] add fallback variable for color to body layout
---
.../packages/core/components/body-layout/body-layout.element.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/body-layout/body-layout.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/body-layout/body-layout.element.ts
index 1d589df449..22be2b754a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/components/body-layout/body-layout.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/body-layout/body-layout.element.ts
@@ -134,7 +134,7 @@ export class UmbBodyLayoutElement extends LitElement {
css`
:host {
display: flex;
- background-color: var(--uui-color-background);
+ background-color: var(--umb-body-layout-color-background, var(--uui-color-background));
width: 100%;
height: 100%;
flex-direction: column;
From 02a08e5d5f3a68b95f35b965b679e8ff06a39e0e Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 13:25:40 +0200
Subject: [PATCH 112/280] add language keys
---
src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 4 ++++
src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts
index d802dcc5cd..c038966225 100644
--- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts
+++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts
@@ -1013,6 +1013,10 @@ export default {
lockoutWillOccur: 'Du har været inaktiv, og du vil blive logget ud om',
renewSession: 'Forny for at gemme dine ændringer',
},
+ login: {
+ instruction: 'Log ind på Umbraco',
+ signInWith: 'Log ind med {0}',
+ },
main: {
dashboard: 'Skrivebord',
sections: 'Sektioner',
diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts
index 3d2682e341..682a1bbb9a 100644
--- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts
+++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts
@@ -1010,6 +1010,10 @@ export default {
lockoutWillOccur: "You've been idle and logout will automatically occur in",
renewSession: 'Renew now to save your work',
},
+ login: {
+ instruction: 'Sign in to Umbraco',
+ signInWith: 'Sign in with {0}',
+ },
main: {
dashboard: 'Dashboard',
sections: 'Sections',
From bcc99cd16355a8f70e4cef5ff35f9f92fc6c9fde Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 13:25:47 +0200
Subject: [PATCH 113/280] remove padding
---
.../core/auth/components/auth-provider-default.element.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/auth-provider-default.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/auth-provider-default.element.ts
index 58e04c5797..b7e523adfc 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/auth-provider-default.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/auth-provider-default.element.ts
@@ -33,7 +33,6 @@ export class UmbAuthProviderDefaultElement extends UmbLitElement {
css`
:host {
display: block;
- padding: 20px;
}
#auth-provider-button {
From 0494e514c18d4e6c703c721faf0b2d9ba5244e13 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 13:29:16 +0200
Subject: [PATCH 114/280] add margin and icon
---
.../core/auth/components/auth-provider-default.element.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/auth-provider-default.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/auth-provider-default.element.ts
index b7e523adfc..8c30b32f48 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/auth-provider-default.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/components/auth-provider-default.element.ts
@@ -21,7 +21,7 @@ export class UmbAuthProviderDefaultElement extends UmbLitElement {
.look=${this.manifest.meta?.defaultView?.look ?? 'outline'}
.color=${this.manifest.meta?.defaultView?.color ?? 'default'}>
${this.manifest.meta?.defaultView?.icon
- ? html` `
+ ? html` `
: nothing}
${this.manifest.meta?.label ?? this.manifest.forProviderName}
@@ -33,6 +33,7 @@ export class UmbAuthProviderDefaultElement extends UmbLitElement {
css`
:host {
display: block;
+ margin-bottom: var(--uui-size-space-5);
}
#auth-provider-button {
From 0f55f62be06642b25ea13c9fb942a30a60ba48dd Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 13:42:10 +0200
Subject: [PATCH 115/280] map up the onSubmit, state and provider
---
.../src/apps/app/app-auth.controller.ts | 17 +++++++++++----
.../src/packages/core/auth/index.ts | 2 ++
.../auth/modals/umb-app-auth-modal.element.ts | 5 +++--
.../auth/modals/umb-app-auth-modal.token.ts | 21 ++++++++++++++++---
.../src/packages/core/auth/types.ts | 5 +++++
5 files changed, 41 insertions(+), 9 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/auth/types.ts
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
index 0c2eac7678..d0335524f1 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
@@ -1,4 +1,9 @@
-import { UMB_AUTH_CONTEXT, UMB_MODAL_APP_AUTH, UMB_STORAGE_REDIRECT_URL } from '@umbraco-cms/backoffice/auth';
+import {
+ UMB_AUTH_CONTEXT,
+ UMB_MODAL_APP_AUTH,
+ UMB_STORAGE_REDIRECT_URL,
+ type UmbUserLoginState,
+} from '@umbraco-cms/backoffice/auth';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs';
@@ -41,7 +46,7 @@ export class UmbAppAuthController extends UmbControllerBase {
* Starts the authorization flow.
* It will check which providers are available and either redirect directly to the provider or show a provider selection screen.
*/
- async makeAuthorizationRequest(): Promise {
+ async makeAuthorizationRequest(userLoginState: UmbUserLoginState = 'loggingIn'): Promise {
if (!this.#authContext) {
throw new Error('[Fatal] Auth context is not available');
}
@@ -67,7 +72,11 @@ export class UmbAppAuthController extends UmbControllerBase {
// Show the provider selection screen
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
const selected = await modalManager
- .open(this._host, UMB_MODAL_APP_AUTH)
+ .open(this._host, UMB_MODAL_APP_AUTH, {
+ data: {
+ userLoginState,
+ },
+ })
.onSubmit()
.catch(() => undefined);
@@ -75,7 +84,7 @@ export class UmbAppAuthController extends UmbControllerBase {
return false;
}
- this.#authContext.makeAuthorizationRequest(selected.providerName);
+ this.#authContext.makeAuthorizationRequest(selected.providerName, selected.loginHint);
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts
index e05fbbb7ed..2f5cf6b67d 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/index.ts
@@ -5,3 +5,5 @@ export * from './auth.context.token.js';
export * from './modals/index.js';
export * from './models/openApiConfiguration.js';
export * from './components/index.js';
+
+export type * from './types.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts
index 5acc1ebe77..7cba576d77 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts
@@ -1,12 +1,13 @@
import { UmbModalBaseElement } from '../../modal/index.js';
-import type { UmbModalAppAuthValue } from './umb-app-auth-modal.token.js';
+import type { UmbModalAppAuthConfig, UmbModalAppAuthValue } from './umb-app-auth-modal.token.js';
import { css, customElement, html } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
@customElement('umb-app-auth-modal')
-export class UmbAppAuthModalElement extends UmbModalBaseElement {
+export class UmbAppAuthModalElement extends UmbModalBaseElement {
get props() {
return {
+ userLoginState: this.data?.userLoginState ?? 'loggingIn',
onSubmit: this.onSubmit,
};
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.token.ts
index 20ce925dd9..9b763e4c36 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.token.ts
@@ -1,10 +1,25 @@
+import type { UmbUserLoginState } from '../types.js';
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
-export type UmbModalAppAuthValue = {
- providerName?: string;
+export type UmbModalAppAuthConfig = {
+ userLoginState: UmbUserLoginState;
};
-export const UMB_MODAL_APP_AUTH = new UmbModalToken('Umb.Modal.AppAuth', {
+export type UmbModalAppAuthValue = {
+ /**
+ * The name of the provider that the user has selected to authenticate with.
+ * @required
+ */
+ providerName?: string;
+
+ /**
+ * The login hint that the user has provided to the provider.
+ * @optional
+ */
+ loginHint?: string;
+};
+
+export const UMB_MODAL_APP_AUTH = new UmbModalToken('Umb.Modal.AppAuth', {
modal: {
type: 'dialog',
},
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/types.ts
new file mode 100644
index 0000000000..d1933d0607
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/types.ts
@@ -0,0 +1,5 @@
+/**
+ * User login state that can be used to determine the current state of the user.
+ * @example 'loggedIn'
+ */
+export type UmbUserLoginState = 'loggingIn' | 'loggedOut' | 'timedOut';
From 0755d4d410b5db5e941f2e135c5d45381e79723a Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 13:51:09 +0200
Subject: [PATCH 116/280] add state to logout button
---
.../modals/current-user/current-user-modal.element.ts | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user/current-user-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user/current-user-modal.element.ts
index 9ad8bd483b..1e89d04f19 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user/current-user-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user/current-user-modal.element.ts
@@ -1,12 +1,12 @@
import { UMB_CURRENT_USER_CONTEXT } from '../../current-user.context.js';
import type { UmbCurrentUserModel } from '../../types.js';
-import { UMB_APP_CONTEXT } from '@umbraco-cms/backoffice/app';
import { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit';
import { css, html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
import type { UmbModalContext } from '@umbraco-cms/backoffice/modal';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
+import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui';
@customElement('umb-current-user-modal')
export class UmbCurrentUserModalElement extends UmbLitElement {
@@ -16,6 +16,9 @@ export class UmbCurrentUserModalElement extends UmbLitElement {
@state()
private _currentUser?: UmbCurrentUserModel;
+ @state()
+ private _logOutButtonState?: UUIButtonState;
+
#authContext?: typeof UMB_AUTH_CONTEXT.TYPE;
#currentUserContext?: typeof UMB_CURRENT_USER_CONTEXT.TYPE;
@@ -50,7 +53,9 @@ export class UmbCurrentUserModalElement extends UmbLitElement {
private async _logout() {
if (!this.#authContext) return;
- this.#authContext.signOut();
+ this._logOutButtonState = 'waiting';
+ await this.#authContext.signOut();
+ this._logOutButtonState = 'success';
}
render() {
@@ -65,6 +70,7 @@ export class UmbCurrentUserModalElement extends UmbLitElement {
From e838c0ea1b721f0f4d22aac760f6942e9a0166cb Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 14:23:42 +0200
Subject: [PATCH 117/280] let the auth context know if a 401 is encountered,
which most likely means the user is timed out
---
.../src/packages/core/auth/auth.context.ts | 10 ++++++
.../core/resources/resource.controller.ts | 35 +++++++++++--------
2 files changed, 31 insertions(+), 14 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts
index a46deed70d..cf99b23c35 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts
@@ -95,6 +95,16 @@ export class UmbAuthContext extends UmbContextBase {
return this.#authFlow.clearTokenStorage();
}
+ /**
+ * Handles the case where the user has timed out, i.e. the token has expired.
+ * This will clear the token storage and set the user as unauthorized.
+ * @memberof UmbAuthContext
+ */
+ timeOut() {
+ this.clearTokenStorage();
+ this.#isAuthorized.setValue(false);
+ }
+
/**
* Signs the user out by removing any tokens from the browser.
* @memberof UmbAuthContext
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
index b7dc4e9992..edbefc578b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
@@ -1,4 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
+import { UMB_AUTH_CONTEXT } from '../auth/index.js';
import { isApiError, isCancelError, isCancelablePromise } from './apiTypeValidators.function.js';
import { UMB_NOTIFICATION_CONTEXT, type UmbNotificationOptions } from '@umbraco-cms/backoffice/notification';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
@@ -11,6 +12,8 @@ export class UmbResourceController extends UmbControllerBase {
#notificationContext?: typeof UMB_NOTIFICATION_CONTEXT.TYPE;
+ #authContext?: typeof UMB_AUTH_CONTEXT.TYPE;
+
constructor(host: UmbControllerHost, promise: Promise, alias?: string) {
super(host, alias);
@@ -19,6 +22,10 @@ export class UmbResourceController extends UmbControllerBase {
new UmbContextConsumerController(host, UMB_NOTIFICATION_CONTEXT, (_instance) => {
this.#notificationContext = _instance;
});
+
+ new UmbContextConsumerController(host, UMB_AUTH_CONTEXT, (_instance) => {
+ this.#authContext = _instance;
+ });
}
hostConnected(): void {
@@ -78,21 +85,21 @@ export class UmbResourceController extends UmbControllerBase {
// Go through the error status codes and act accordingly
switch (error.status ?? 0) {
- case 401:
- // Unauthorized
- console.log('Unauthorized');
-
- // TODO: Do not remove the token here but instead let whatever is listening to the event decide what to do
- localStorage.removeItem('umb:userAuthTokenResponse');
-
- // TODO: Show a modal dialog to login either by bubbling an event to UmbAppElement or by showing a modal directly
- this.#notificationContext?.peek('warning', {
- data: {
- headline: 'Session Expired',
- message: 'Your session has expired. Please refresh the page.',
- },
- });
+ case 401: {
+ // See if we can get the UmbAuthContext and let it know the user is timed out
+ if (this.#authContext) {
+ this.#authContext.timeOut();
+ } else {
+ // If we can't get the auth context, show a notification
+ this.#notificationContext?.peek('warning', {
+ data: {
+ headline: 'Session Expired',
+ message: 'Your session has expired. Please refresh the page.',
+ },
+ });
+ }
break;
+ }
case 500:
// Server Error
From 362c3188be3e32f21aa7931bd69d4bcb09165752 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 14:23:59 +0200
Subject: [PATCH 118/280] listen to changes for timeout but only if the value
changed
---
.../src/apps/app/app-auth.controller.ts | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
index d0335524f1..dfeb8455c1 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
@@ -6,7 +6,7 @@ import {
} from '@umbraco-cms/backoffice/auth';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
-import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs';
+import { distinctUntilChanged, filter, firstValueFrom, skip } from '@umbraco-cms/backoffice/external/rxjs';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
export class UmbAppAuthController extends UmbControllerBase {
@@ -17,6 +17,22 @@ export class UmbAppAuthController extends UmbControllerBase {
this.consumeContext(UMB_AUTH_CONTEXT, (context) => {
this.#authContext = context;
+
+ // Observe the user's authorization state and start the authorization flow if the user is not authorized
+ this.observe(
+ context.isAuthorized.pipe(
+ // Only continue if the value has changed
+ distinctUntilChanged(),
+ // Skip the first since it is always false
+ skip(1),
+ // Only continue if the value is false
+ filter((x) => !x),
+ ),
+ () => {
+ this.makeAuthorizationRequest('timedOut');
+ },
+ '_authState',
+ );
});
}
From c5d25e4b7a0ee9371b5b99fbdb85144ba91e4906 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 14:24:05 +0200
Subject: [PATCH 119/280] add skip
---
src/Umbraco.Web.UI.Client/src/external/rxjs/index.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Umbraco.Web.UI.Client/src/external/rxjs/index.ts b/src/Umbraco.Web.UI.Client/src/external/rxjs/index.ts
index f7d17284b7..cc5b1fcd73 100644
--- a/src/Umbraco.Web.UI.Client/src/external/rxjs/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/external/rxjs/index.ts
@@ -17,4 +17,5 @@ export {
switchMap,
filter,
startWith,
+ skip,
} from 'rxjs';
From 78497b3032ebd7426747985dbb810ec40e88a684 Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 15:27:17 +0200
Subject: [PATCH 120/280] add support to set a backdrop for a modal
---
.../backoffice-modal-container.element.ts | 24 ++++++++++++++++---
.../modal/context/modal-manager.context.ts | 5 ++++
.../core/modal/context/modal.context.ts | 3 +++
3 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/backoffice-modal-container/backoffice-modal-container.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/backoffice-modal-container/backoffice-modal-container.element.ts
index 48d0068860..ee8be1c38b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/components/backoffice-modal-container/backoffice-modal-container.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/backoffice-modal-container/backoffice-modal-container.element.ts
@@ -1,6 +1,6 @@
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit';
-import { css, html, repeat, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit';
+import { css, html, repeat, customElement, state, nothing, property } from '@umbraco-cms/backoffice/external/lit';
import type { UmbModalManagerContext, UmbModalContext } from '@umbraco-cms/backoffice/modal';
import { UMB_MODAL_MANAGER_CONTEXT, UmbModalElement } from '@umbraco-cms/backoffice/modal';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
@@ -13,6 +13,9 @@ export class UmbBackofficeModalContainerElement extends UmbLitElement {
@state()
_modals: Array = [];
+ @property({ reflect: true, attribute: 'fill-background' })
+ fillBackground = false;
+
private _modalManager?: UmbModalManagerContext;
constructor() {
@@ -35,6 +38,7 @@ export class UmbBackofficeModalContainerElement extends UmbLitElement {
/** We cannot render the umb-modal element directly in the uui-modal-container because it wont get recognized by UUI.
* We therefore have a helper class which creates the uui-modal element and returns it. */
#createModalElements(modals: Array) {
+ this.fillBackground = false;
const oldValue = this._modals;
this._modals = modals;
@@ -61,6 +65,15 @@ export class UmbBackofficeModalContainerElement extends UmbLitElement {
modal.addEventListener('umb:destroy', this.#onCloseEnd.bind(this, modal.key));
this._modalElementMap.set(modal.key, modalElement);
+
+ // If any of the modals are fillBackground, set the fillBackground property to true
+ if (modal.backdropBackground) {
+ this.fillBackground = true;
+ this.shadowRoot
+ ?.getElementById('container')
+ ?.style.setProperty('--backdrop-background', modal.backdropBackground);
+ }
+
this.requestUpdate();
});
}
@@ -78,13 +91,13 @@ export class UmbBackofficeModalContainerElement extends UmbLitElement {
render() {
return html`
-
+
${this._modals.length > 0
? repeat(
this._modals,
(modal) => modal.key,
(modal) => this.#renderModal(modal.key),
- )
+ )
: ''}
`;
@@ -97,6 +110,11 @@ export class UmbBackofficeModalContainerElement extends UmbLitElement {
position: absolute;
z-index: 1000;
}
+
+ :host([fill-background]) #container::after {
+ background: var(--backdrop-background);
+ opacity: 0.75;
+ }
`,
];
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal-manager.context.ts
index d923e06b0b..eb74e7deca 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal-manager.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal-manager.context.ts
@@ -12,6 +12,11 @@ export interface UmbModalConfig {
key?: string;
type?: UmbModalType;
size?: UUIModalSidebarSize;
+
+ /**
+ * Set the background property of the modal backdrop
+ */
+ backdropBackground?: string;
}
export class UmbModalManagerContext extends UmbContextBase {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts
index a22c2dd674..05d6220b7a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts
@@ -32,6 +32,7 @@ export class UmbModalContext;
@@ -51,10 +52,12 @@ export class UmbModalContext
Date: Fri, 5 Apr 2024 15:27:34 +0200
Subject: [PATCH 121/280] track if it's the first time logging in and set a
backdrop corresponding to that
---
.../src/apps/app/app-auth.controller.ts | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
index dfeb8455c1..518f62d1ff 100644
--- a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
@@ -11,6 +11,7 @@ import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
export class UmbAppAuthController extends UmbControllerBase {
#authContext?: typeof UMB_AUTH_CONTEXT.TYPE;
+ #firstTimeLoggingIn = true;
constructor(host: UmbControllerHost) {
super(host);
@@ -29,6 +30,7 @@ export class UmbAppAuthController extends UmbControllerBase {
filter((x) => !x),
),
() => {
+ this.#firstTimeLoggingIn = false;
this.makeAuthorizationRequest('timedOut');
},
'_authState',
@@ -92,6 +94,11 @@ export class UmbAppAuthController extends UmbControllerBase {
data: {
userLoginState,
},
+ modal: {
+ backdropBackground: this.#firstTimeLoggingIn
+ ? "url('https://picsum.photos/1440') center center / cover no-repeat"
+ : 'rgb(0, 0, 0)',
+ },
})
.onSubmit()
.catch(() => undefined);
From 9a5fe32c613e80d7ea8fe3e349250e623275af5f Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 5 Apr 2024 15:28:39 +0200
Subject: [PATCH 122/280] remove temp login screen
---
.../apps/auth/e2e/login.spec.ts | 19 ---
.../apps/auth/index.html | 15 --
.../apps/auth/package.json | 20 ---
.../apps/auth/playwright.config.ts | 108 -------------
.../apps/auth/public/favicon.svg | 17 --
.../apps/auth/public/login.jpeg | Bin 30678 -> 0 bytes
.../apps/auth/public/umbraco_logo_white.svg | 1 -
.../auth/public/umbraco_logomark_white.svg | 1 -
.../apps/auth/src/auth-layout.element.ts | 72 ---------
.../apps/auth/src/auth-legacy.context.ts | 10 --
.../apps/auth/src/auth.context.ts | 13 --
.../apps/auth/src/auth.repository.ts | 44 ------
.../external-login-provider-test.element.ts | 40 -----
.../external-login-provider-test2.element.ts | 53 -------
.../src/external-login-providers/manifests.ts | 29 ----
.../apps/auth/src/index.ts | 7 -
.../apps/auth/src/login.element.ts | 148 ------------------
.../apps/auth/src/login.test.ts | 21 ---
.../apps/auth/src/types.ts | 16 --
.../apps/auth/src/vite-env.d.ts | 6 -
.../apps/auth/tsconfig.json | 12 --
.../apps/auth/tsconfig.node.json | 9 --
.../apps/auth/vite.config.ts | 32 ----
src/Umbraco.Web.UI.Client/package.json | 3 +-
24 files changed, 1 insertion(+), 695 deletions(-)
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/e2e/login.spec.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/index.html
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/package.json
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/playwright.config.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/public/favicon.svg
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/public/login.jpeg
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/public/umbraco_logo_white.svg
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/public/umbraco_logomark_white.svg
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/auth-layout.element.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/auth.repository.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/external-login-providers/external-login-provider-test.element.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/external-login-providers/external-login-provider-test2.element.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/external-login-providers/manifests.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/index.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/login.test.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/types.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/vite-env.d.ts
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/tsconfig.json
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/tsconfig.node.json
delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts
diff --git a/src/Umbraco.Web.UI.Client/apps/auth/e2e/login.spec.ts b/src/Umbraco.Web.UI.Client/apps/auth/e2e/login.spec.ts
deleted file mode 100644
index d34e280a56..0000000000
--- a/src/Umbraco.Web.UI.Client/apps/auth/e2e/login.spec.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { expect, test } from '@playwright/test';
-
-test('login', async ({ page }) => {
- await page.goto('/');
-
- // Fill input[name="email"]
- await page.locator('input[name="email"]').fill('test@umbraco.com');
-
- // Fill input[name="password"]
- await page.locator('input[name="password"]').fill('test123456');
-
- // Wait for console.log to be called
- page.on('console', (message) => {
- expect(message.text()).toBe('login');
- });
-
- // Click [aria-label="Login"]
- await page.locator('[aria-label="Login"]').click();
-});
diff --git a/src/Umbraco.Web.UI.Client/apps/auth/index.html b/src/Umbraco.Web.UI.Client/apps/auth/index.html
deleted file mode 100644
index 75922ccae2..0000000000
--- a/src/Umbraco.Web.UI.Client/apps/auth/index.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
- Umbraco Auth
-
-
-
-
-
-
-
-
diff --git a/src/Umbraco.Web.UI.Client/apps/auth/package.json b/src/Umbraco.Web.UI.Client/apps/auth/package.json
deleted file mode 100644
index addf6d7ebf..0000000000
--- a/src/Umbraco.Web.UI.Client/apps/auth/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "@umbraco-cms/login",
- "version": "0.0.0",
- "license": "MIT",
- "author": {
- "name": "Umbraco HQ",
- "email": "backoffice@umbraco.com"
- },
- "type": "module",
- "module": "dist/main.js",
- "files": [
- "dist"
- ],
- "scripts": {
- "dev": "vite",
- "build": "tsc && vite build",
- "build:watch": "vite build --watch",
- "preview": "vite preview"
- }
-}
diff --git a/src/Umbraco.Web.UI.Client/apps/auth/playwright.config.ts b/src/Umbraco.Web.UI.Client/apps/auth/playwright.config.ts
deleted file mode 100644
index f7bf259530..0000000000
--- a/src/Umbraco.Web.UI.Client/apps/auth/playwright.config.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-import type { PlaywrightTestConfig } from '@playwright/test';
-import { devices } from '@playwright/test';
-
-/**
- * Read environment variables from file.
- * https://github.com/motdotla/dotenv
- */
-// require('dotenv').config();
-
-/**
- * See https://playwright.dev/docs/test-configuration.
- */
-const config: PlaywrightTestConfig = {
- testDir: './e2e',
- /* Maximum time one test can run for. */
- timeout: 30 * 1000,
- expect: {
- /**
- * Maximum time expect() should wait for the condition to be met.
- * For example in `await expect(locator).toHaveText();`
- */
- timeout: 5000,
- },
- /* Run tests in files in parallel */
- fullyParallel: true,
- /* Fail the build on CI if you accidentally left test.only in the source code. */
- forbidOnly: !!process.env.CI,
- /* Retry on CI only */
- retries: process.env.CI ? 2 : 0,
- /* Opt out of parallel tests on CI. */
- workers: process.env.CI ? 1 : undefined,
- /* Reporter to use. See https://playwright.dev/docs/test-reporters */
- reporter: 'html',
- /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
- use: {
- /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
- actionTimeout: 0,
- /* Base URL to use in actions like `await page.goto('/')`. */
- // baseURL: 'http://localhost:3000',
-
- /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
- trace: 'on-first-retry',
- },
-
- /* Configure projects for major browsers */
- projects: [
- {
- name: 'chromium',
- use: {
- ...devices['Desktop Chrome'],
- },
- },
-
- {
- name: 'firefox',
- use: {
- ...devices['Desktop Firefox'],
- },
- },
-
- {
- name: 'webkit',
- use: {
- ...devices['Desktop Safari'],
- },
- },
-
- /* Test against mobile viewports. */
- // {
- // name: 'Mobile Chrome',
- // use: {
- // ...devices['Pixel 5'],
- // },
- // },
- // {
- // name: 'Mobile Safari',
- // use: {
- // ...devices['iPhone 12'],
- // },
- // },
-
- /* Test against branded browsers. */
- // {
- // name: 'Microsoft Edge',
- // use: {
- // channel: 'msedge',
- // },
- // },
- // {
- // name: 'Google Chrome',
- // use: {
- // channel: 'chrome',
- // },
- // },
- ],
-
- /* Folder for test artifacts such as screenshots, videos, traces, etc. */
- // outputDir: 'test-results/',
-
- /* Run your local dev server before starting the tests */
- webServer: {
- command: 'npm run dev',
- port: 5173,
- reuseExistingServer: !process.env.CI,
- },
-};
-
-export default config;
diff --git a/src/Umbraco.Web.UI.Client/apps/auth/public/favicon.svg b/src/Umbraco.Web.UI.Client/apps/auth/public/favicon.svg
deleted file mode 100644
index 19acb4bc1e..0000000000
--- a/src/Umbraco.Web.UI.Client/apps/auth/public/favicon.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
diff --git a/src/Umbraco.Web.UI.Client/apps/auth/public/login.jpeg b/src/Umbraco.Web.UI.Client/apps/auth/public/login.jpeg
deleted file mode 100644
index 412cd17865c1b847affa4f0c2abc74645f678187..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 30678
zcmd4(c|4V07e9>ebB=kQGiPWpXAYr5$PkV>MCK{VoVg=oiX?={JY*g#4HBYI#>`1F
zMNw&@>9?9Z;$q*)&Be~i
z$+JsrFAtvxKPRWaenAm&32ABRoqOe#ubU?C{&h9XpFe*LFy9pLe;M*)$&FFk2I3n^)V@>4-6FjPHzZ;{w9RHCq$2A@
z*P@eiwq~gm8hQ_~aAP+t3b3Y|96@Hv%MlW!+k6tyy?ddhfaONcmg$}iX0t>~qfItg
z%Ca0ls~E5$2+~nJ`pb?&jT}z^Fq0nvDn52YX~@HzxNSz0_0*#oIRsmSsXPKuj#C?Y
zrr1BGb3lD%=R=4Sxoi#+b!HKuUT!We8GhGB8(3m0PO^NzVg@;;*c2?Ri1~%^z{&~$
zBUUK=O_-unojxbSAjm_QB)_T+;7$jCOnoze^kT53NHv=HZ1Pi#+uqEXSPe3aSrQfvUThY>G#jp@$
znK*X15NGoZ;{o7>LkFM$Itywg2!QrBC~cFz>vR8en21*h(0SU1x9cMw_K&PCF(2aG
zshYnR6S09-%XhNgk{Vk%uI{+XjK5#15d>?)!lSiXwOdvQc~*KkX5hLrUF>
zi0c$n7^@jm{Dz7S*)(KX53_Fogp%#vxK|?}?HS5};(?;0sDv5T&81uU=sx20J5WD5?AvI`L2@)m*Rvmha1v5umF5a{z^pE)nD(e@s$r8idR?v3XR3
zz*m0a5WwVoJO?OgRL&wwHnDdAxMtpj>wyUzX)i3Uj|hUG7a28Ljva*Hqlw*hsqH6l{H8Bcf|c9^#8_0eiX
z=K8tV+1b+G*#e7xJOnsQXQ(L=%{D20sRpj81aZd>=~_I(p#o3PAvJN3--7t}Hwe2$
zPO>>5I*Op(f?$ohy1-+UKJo_wIP@HVLN2u+!|3vpgHyL`zvjrIvwgXD&
z)#5?Yi(((P6iD4TiA5ET;5Q-Ec3zmckwbE+ViP7*PB-viwRd}wDb%!cHq`ppgYgm*
zy?@wZPITc(_8Dv;Xz9&xiK;n;#bnyyw-m5;t{rXwGUeOTr_X_Bk3g^4u&62*{Dwd%
zX^%u7<`2MV)oo#DX`;<^DjB*9NQ6xPX^mRC^l0YfMJ|SIPy@d?WRleyJa71r7j~;7
zq$X`T%s>Bo#s%0T1TAW1Fcg?CS6#Le0Y~oCDHqi0U9Hct^_e1G({=P?`
z*x?eAJZ^k*b6U>BOuGYV{=0jo*uTeyz652eUqJsUp105kxwN3vnYKGbY2pc~aeHWn
zJZXS=A&UWvvVZhx3V^&gLP|!_{3zljVEqRR6L^hw$I9OSV`2B$;v7~lbaTrwca6l;n_HTc8xWByJbx=K93YGVvU
z;O{Yjc(_4ar(s&4+LN6hfJ_J_gh%>7Dj0k>JbrT=XtWJ#Uyc|Sus%7chh%5^9K_Q%
zMnj(?gf4|mf0N;^W{lwTW?;Uk;EzT$@o*AbWB+Z2aA-JNS>;~9&0dsU-V6bhHV%1o
z0d_M^Kz^GF9C2Xu8xNZOX;x_f9>OSgWZ?wqHV+A6$efInkWlP{K$d%uSmwt8gL(oY
z$W#jJLKK#eO%aILQC{08IcYZ6EIEb>H*#ZF9
zhhKoJ`1Obl0YPcww>1C=`^oF&0LlZN+t`G=%-26HHWhnA#R2Ms+qT(%F{WQ&_f2p>yy}=6r!?G>@7lXce8UTB{|59yZsFgq*sQv(D
z9%5DOHvA7mTKJ}!_zE7Pc*IBkBqDg2HVGx%V}l+Vgc8rcuOcLUp#}I&GXQp&VJU-=
zehRS2Ir)PyzKfZ4+P?wr;Re(zWCj#!M9sfpgj=xUee{VA;Uw=A%~yON>>$xfD2SGW
z*!G1VF+hmuw*N=3dkzTe{6%Ttpy|$eLStl+ijc7o^Znz?wAM8@5(M#3g%Zv7o%qlk
zvJ?RYIQ$)cRPI>F81f