From b97c5fa6fbbf7eb807abfcc30aa4471dcaa24b13 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 17 Jul 2024 11:01:44 +0100 Subject: [PATCH 1/7] Entity Bulk Action: adds "default" kind --- .../default/default.action.kind.ts | 19 ++++++++ .../entity-bulk-action/default/manifests.ts | 4 ++ .../entity-bulk-action-element.interface.ts | 3 ++ .../entity-bulk-action.element.ts | 43 ++++++++++++------- .../packages/core/entity-bulk-action/index.ts | 3 ++ .../core/entity-bulk-action/manifests.ts | 6 +++ .../models/entity-bulk-action.model.ts | 15 +++++-- .../src/packages/core/manifests.ts | 2 + 8 files changed, 76 insertions(+), 19 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/default/default.action.kind.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/default/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/entity-bulk-action-element.interface.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/default/default.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/default/default.action.kind.ts new file mode 100644 index 0000000000..f36eaf6dd4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/default/default.action.kind.ts @@ -0,0 +1,19 @@ +import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const UMB_ENTITY_BULK_ACTION_DEFAULT_KIND_MANIFEST: UmbBackofficeManifestKind = { + type: 'kind', + alias: 'Umb.Kind.EntityBulkAction.Default', + matchKind: 'default', + matchType: 'entityBulkAction', + manifest: { + type: 'entityBulkAction', + kind: 'default', + weight: 1000, + element: () => import('../entity-bulk-action.element.js'), + meta: { + label: 'Default Entity Bulk Action', + }, + }, +}; + +export const manifest = UMB_ENTITY_BULK_ACTION_DEFAULT_KIND_MANIFEST; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/default/manifests.ts new file mode 100644 index 0000000000..3cb64a6f47 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/default/manifests.ts @@ -0,0 +1,4 @@ +import { manifest as defaultKindManifest } from './default.action.kind.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [defaultKindManifest]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/entity-bulk-action-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/entity-bulk-action-element.interface.ts new file mode 100644 index 0000000000..6cc4b315a9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/entity-bulk-action-element.interface.ts @@ -0,0 +1,3 @@ +import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; + +export interface UmbEntityBulkActionElement extends UmbControllerHostElement {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/entity-bulk-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/entity-bulk-action.element.ts index 20baaa6da0..d1ccb48953 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/entity-bulk-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/entity-bulk-action.element.ts @@ -1,16 +1,25 @@ -import type { UmbEntityBulkActionBase } from './entity-bulk-action-base.js'; -import { UmbActionExecutedEvent } from '@umbraco-cms/backoffice/event'; +import type { UmbEntityBulkAction } from './entity-bulk-action.interface.js'; +import type { UmbEntityBulkActionElement } from './entity-bulk-action-element.interface.js'; import { html, ifDefined, customElement, property } from '@umbraco-cms/backoffice/external/lit'; -import type { ManifestEntityBulkAction, MetaEntityBulkAction } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbActionExecutedEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import type { + ManifestEntityBulkAction, + MetaEntityBulkActionDefaultKind, +} from '@umbraco-cms/backoffice/extension-registry'; -@customElement('umb-entity-bulk-action') -export class UmbEntityBulkActionElement< - MetaType extends MetaEntityBulkAction = MetaEntityBulkAction, - ApiType extends UmbEntityBulkActionBase = UmbEntityBulkActionBase, -> extends UmbLitElement { +const elementName = 'umb-entity-bulk-action'; + +@customElement(elementName) +export class UmbEntityBulkActionDefaultElement< + MetaType extends MetaEntityBulkActionDefaultKind = MetaEntityBulkActionDefaultKind, + ApiType extends UmbEntityBulkAction = UmbEntityBulkAction, + > + extends UmbLitElement + implements UmbEntityBulkActionElement +{ @property({ attribute: false }) - manifest?: ManifestEntityBulkAction; + manifest?: ManifestEntityBulkAction; api?: ApiType; @@ -22,16 +31,20 @@ export class UmbEntityBulkActionElement< } override render() { - return html``; + return html` + + `; } } +export default UmbEntityBulkActionDefaultElement; + declare global { interface HTMLElementTagNameMap { - 'umb-entity-bulk-action': UmbEntityBulkActionElement; + [elementName]: UmbEntityBulkActionDefaultElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts index 24e16cf0cb..2e6df40165 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts @@ -2,3 +2,6 @@ export * from './types.js'; export * from './entity-bulk-action-base.js'; export * from './entity-bulk-action.element.js'; export * from './entity-bulk-action.interface.js'; +export type * from './entity-bulk-action-element.interface.js'; + +export { UMB_ENTITY_BULK_ACTION_DEFAULT_KIND_MANIFEST } from './default/default.action.kind.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/manifests.ts new file mode 100644 index 0000000000..8090bb3267 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/manifests.ts @@ -0,0 +1,6 @@ +import { manifests as defaultEntityBulkActionManifests } from './default/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + ...defaultEntityBulkActionManifests, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-bulk-action.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-bulk-action.model.ts index 984aa12384..cd4bed17f4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-bulk-action.model.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-bulk-action.model.ts @@ -1,6 +1,6 @@ import type { ConditionTypes } from '../conditions/types.js'; -import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; -import type { UmbEntityBulkActionBase } from '@umbraco-cms/backoffice/entity-bulk-action'; +import type { UmbEntityBulkActionElement } from '../../entity-bulk-action/entity-bulk-action-element.interface.js'; +import type { UmbEntityBulkAction } from '@umbraco-cms/backoffice/entity-bulk-action'; import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; /** @@ -8,14 +8,21 @@ import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbr * For example for content you may wish to move one or more documents in bulk */ export interface ManifestEntityBulkAction - extends ManifestElementAndApi>, + extends ManifestElementAndApi>, ManifestWithDynamicConditions { type: 'entityBulkAction'; forEntityTypes: Array; meta: MetaType; } -export interface MetaEntityBulkAction { +export interface MetaEntityBulkAction {} + +export interface ManifestEntityBulkActionDefaultKind extends ManifestEntityBulkAction { + type: 'entityBulkAction'; + kind: 'default'; +} + +export interface MetaEntityBulkActionDefaultKind extends MetaEntityBulkAction { /** * The friendly name of the action to perform * 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 5f6f036ea4..a9e6fb1ecd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts @@ -5,6 +5,7 @@ import { manifests as contentTypeManifests } from './content-type/manifests.js'; import { manifests as cultureManifests } from './culture/manifests.js'; import { manifests as debugManifests } from './debug/manifests.js'; import { manifests as entityActionManifests } from './entity-action/manifests.js'; +import { manifests as entityBulkActionManifests } from './entity-bulk-action/manifests.js'; import { manifests as extensionManifests } from './extension-registry/manifests.js'; import { manifests as iconRegistryManifests } from './icon-registry/manifests.js'; import { manifests as localizationManifests } from './localization/manifests.js'; @@ -38,6 +39,7 @@ export const manifests: Array = [ ...settingsManifests, ...modalManifests, ...entityActionManifests, + ...entityBulkActionManifests, ...propertyActionManifests, ...serverFileSystemManifests, ...debugManifests, From 7622158736b45da5d1e79d45f3fa32e87674dcb8 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 17 Jul 2024 11:06:34 +0100 Subject: [PATCH 2/7] Entity Bulk Action: adds "moveTo" kind --- .../core/entity-bulk-action/common/index.ts | 1 + .../common/move-to/index.ts | 2 + .../common/move-to/manifests.ts | 4 ++ .../move-to/move-to-repository.interface.ts | 7 +++ .../common/move-to/move-to.action.kind.ts | 22 ++++++++ .../common/move-to/move-to.action.ts | 55 +++++++++++++++++++ .../common/move-to/types.ts | 6 ++ .../packages/core/entity-bulk-action/index.ts | 1 + .../core/entity-bulk-action/manifests.ts | 2 + .../models/entity-bulk-action.model.ts | 13 +++++ 10 files changed, 113 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to-repository.interface.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to.action.kind.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to.action.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/index.ts new file mode 100644 index 0000000000..38cd1d7714 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/index.ts @@ -0,0 +1 @@ +export * from './move-to/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/index.ts new file mode 100644 index 0000000000..d7dbc13a3b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/index.ts @@ -0,0 +1,2 @@ +export type { UmbBulkMoveToRepository } from './move-to-repository.interface.js'; +export type { UmbBulkMoveToRequestArgs } from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/manifests.ts new file mode 100644 index 0000000000..701878051e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/manifests.ts @@ -0,0 +1,4 @@ +import { manifest as moveToKindManifest } from './move-to.action.kind.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [moveToKindManifest]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to-repository.interface.ts new file mode 100644 index 0000000000..3345adb499 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to-repository.interface.ts @@ -0,0 +1,7 @@ +import type { UmbRepositoryErrorResponse } from '../../../repository/types.js'; +import type { UmbBulkMoveToRequestArgs } from './types.js'; +import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; + +export interface UmbBulkMoveToRepository extends UmbApi { + requestBulkMoveTo(args: UmbBulkMoveToRequestArgs): Promise; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to.action.kind.ts new file mode 100644 index 0000000000..5bae68e01d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to.action.kind.ts @@ -0,0 +1,22 @@ +import { UMB_ENTITY_BULK_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.EntityBulkAction.MoveTo', + matchKind: 'moveTo', + matchType: 'entityBulkAction', + manifest: { + ...UMB_ENTITY_BULK_ACTION_DEFAULT_KIND_MANIFEST.manifest, + type: 'entityBulkAction', + kind: 'moveTo', + api: () => import('./move-to.action.js'), + weight: 700, + forEntityTypes: [], + meta: { + label: '#actions_move', + bulkMoveRepositoryAlias: '', + treeAlias: '', + }, + }, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to.action.ts new file mode 100644 index 0000000000..a008d2c080 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to.action.ts @@ -0,0 +1,55 @@ +import type { UmbBulkMoveToRepository } from './move-to-repository.interface.js'; +import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbEntityBulkActionBase } from '@umbraco-cms/backoffice/entity-bulk-action'; +import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_TREE_PICKER_MODAL } from '@umbraco-cms/backoffice/tree'; +import type { MetaEntityBulkActionMoveToKind } from '@umbraco-cms/backoffice/extension-registry'; + +export class UmbMediaMoveEntityBulkAction extends UmbEntityBulkActionBase { + async execute() { + if (this.selection?.length === 0) return; + + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + + const modalContext = modalManager.open(this, UMB_TREE_PICKER_MODAL, { + data: { + foldersOnly: this.args.meta.foldersOnly, + hideTreeRoot: this.args.meta.hideTreeRoot, + treeAlias: this.args.meta.treeAlias, + }, + }); + + const value = await modalContext.onSubmit().catch(() => undefined); + if (!value?.selection?.length) return; + + const destinationUnique = value.selection[0]; + if (destinationUnique === undefined) throw new Error('Destination Unique is not available'); + + const bulkMoveRepository = await createExtensionApiByAlias( + this, + this.args.meta.bulkMoveRepositoryAlias, + ); + if (!bulkMoveRepository) throw new Error('Bulk Move Repository is not available'); + + await bulkMoveRepository.requestBulkMoveTo({ uniques: this.selection, destination: { unique: destinationUnique } }); + + const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); + if (!entityContext) throw new Error('Entity Context is not available'); + + const entityType = entityContext.getEntityType(); + const unique = entityContext.getUnique(); + + if (entityType && unique !== undefined) { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + if (!eventContext) throw new Error('Event Context is not available'); + + const event = new UmbRequestReloadChildrenOfEntityEvent({ entityType, unique }); + eventContext.dispatchEvent(event); + } + } +} + +export { UmbMediaMoveEntityBulkAction as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/types.ts new file mode 100644 index 0000000000..75a99ea4ee --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/types.ts @@ -0,0 +1,6 @@ +export interface UmbBulkMoveToRequestArgs { + uniques: Array; + destination: { + unique: string | null; + }; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts index 2e6df40165..bf14ffa917 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts @@ -1,4 +1,5 @@ export * from './types.js'; +export * from './common/index.js'; export * from './entity-bulk-action-base.js'; export * from './entity-bulk-action.element.js'; export * from './entity-bulk-action.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/manifests.ts index 8090bb3267..e646693e2f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/manifests.ts @@ -1,6 +1,8 @@ import { manifests as defaultEntityBulkActionManifests } from './default/manifests.js'; +import { manifests as moveToEntityBulkActionManifests } from './common/move-to/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ ...defaultEntityBulkActionManifests, + ...moveToEntityBulkActionManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-bulk-action.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-bulk-action.model.ts index cd4bed17f4..7bd4c186e7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-bulk-action.model.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-bulk-action.model.ts @@ -33,3 +33,16 @@ export interface MetaEntityBulkActionDefaultKind extends MetaEntityBulkAction { */ label?: string; } + +// MOVE TO +export interface ManifestEntityBulkActionMoveToKind extends ManifestEntityBulkAction { + type: 'entityBulkAction'; + kind: 'moveTo'; +} + +export interface MetaEntityBulkActionMoveToKind extends MetaEntityBulkActionDefaultKind { + bulkMoveRepositoryAlias: string; + hideTreeRoot?: boolean; + foldersOnly?: boolean; + treeAlias: string; +} From f37c00f5ce6f0c8600141e00d77722e2212fda24 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 17 Jul 2024 11:09:42 +0100 Subject: [PATCH 3/7] Implements Media "Move to" entity bulk action as a `moveTo` kind. --- .../media/entity-bulk-actions/manifests.ts | 29 ++++----------- .../entity-bulk-actions/move-to/index.ts | 1 + .../entity-bulk-actions/move-to/manifests.ts | 36 +++++++++++++++++++ .../move-to/repository/constants.ts | 1 + .../move-to/repository/index.ts | 2 ++ .../move-to/repository/manifests.ts | 11 ++++++ .../move-to/repository/move-to.repository.ts | 36 +++++++++++++++++++ .../entity-bulk-actions/move/move.action.ts | 25 ------------- 8 files changed, 93 insertions(+), 48 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/move-to.repository.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move/move.action.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/manifests.ts index 5690bb37a7..98f2769681 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/manifests.ts @@ -1,12 +1,13 @@ import { UMB_MEDIA_COLLECTION_ALIAS } from '../collection/index.js'; -import type { UmbCollectionBulkActionPermissions } from '@umbraco-cms/backoffice/collection'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import { manifests as moveToManifests } from './move-to/manifests.js'; import { UMB_COLLECTION_ALIAS_CONDITION, UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION, } from '@umbraco-cms/backoffice/collection'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbCollectionBulkActionPermissions } from '@umbraco-cms/backoffice/collection'; -export const manifests: Array = [ +const entityBulkActions: Array = [ { type: 'entityBulkAction', alias: 'Umb.EntityBulkAction.Media.Duplicate', @@ -27,26 +28,6 @@ export const manifests: Array = [ }, ], }, - { - type: 'entityBulkAction', - alias: 'Umb.EntityBulkAction.Media.MoveTo', - name: 'Move Media Entity Bulk Action', - weight: 20, - api: () => import('./move/move.action.js'), - meta: { - label: 'Move', - }, - conditions: [ - { - alias: UMB_COLLECTION_ALIAS_CONDITION, - match: UMB_MEDIA_COLLECTION_ALIAS, - }, - { - alias: UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION, - match: (permissions: UmbCollectionBulkActionPermissions) => permissions.allowBulkMove, - }, - ], - }, { type: 'entityBulkAction', alias: 'Umb.EntityBulkAction.Media.Delete', @@ -68,3 +49,5 @@ export const manifests: Array = [ ], }, ]; + +export const manifests: Array = [...entityBulkActions, ...moveToManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/index.ts new file mode 100644 index 0000000000..7897faf401 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/index.ts @@ -0,0 +1 @@ +export { UmbBulkMoveToMediaRepository, UMB_BULK_MOVE_MEDIA_REPOSITORY_ALIAS } from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/manifests.ts new file mode 100644 index 0000000000..a482026403 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/manifests.ts @@ -0,0 +1,36 @@ +import { UMB_MEDIA_COLLECTION_ALIAS } from '../../collection/index.js'; +import { UMB_MEDIA_ENTITY_TYPE } from '../../entity.js'; +import { UMB_MEDIA_TREE_ALIAS } from '../../tree/constants.js'; +import { UMB_BULK_MOVE_MEDIA_REPOSITORY_ALIAS } from './repository/constants.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import { + UMB_COLLECTION_ALIAS_CONDITION, + UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION, +} from '@umbraco-cms/backoffice/collection'; +import type { UmbCollectionBulkActionPermissions } from '@umbraco-cms/backoffice/collection'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +const bulkMoveAction: ManifestTypes = { + type: 'entityBulkAction', + kind: 'moveTo', + alias: 'Umb.EntityBulkAction.Media.MoveTo', + name: 'Move Media Entity Bulk Action', + weight: 20, + forEntityTypes: [UMB_MEDIA_ENTITY_TYPE], + meta: { + bulkMoveRepositoryAlias: UMB_BULK_MOVE_MEDIA_REPOSITORY_ALIAS, + treeAlias: UMB_MEDIA_TREE_ALIAS, + }, + conditions: [ + { + alias: UMB_COLLECTION_ALIAS_CONDITION, + match: UMB_MEDIA_COLLECTION_ALIAS, + }, + { + alias: UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION, + match: (permissions: UmbCollectionBulkActionPermissions) => permissions.allowBulkMove, + }, + ], +}; + +export const manifests: Array = [bulkMoveAction, ...repositoryManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/constants.ts new file mode 100644 index 0000000000..4037b48892 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/constants.ts @@ -0,0 +1 @@ +export const UMB_BULK_MOVE_MEDIA_REPOSITORY_ALIAS = 'Umb.Repository.Media.BulkMove'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/index.ts new file mode 100644 index 0000000000..55908dba95 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/index.ts @@ -0,0 +1,2 @@ +export { UmbBulkMoveToMediaRepository } from './move-to.repository.js'; +export { UMB_BULK_MOVE_MEDIA_REPOSITORY_ALIAS } from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/manifests.ts new file mode 100644 index 0000000000..7f5b2ddb41 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_BULK_MOVE_MEDIA_REPOSITORY_ALIAS } from './constants.js'; +import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +const bulkMoveRepository: ManifestRepository = { + type: 'repository', + alias: UMB_BULK_MOVE_MEDIA_REPOSITORY_ALIAS, + name: 'Bulk Move Media Repository', + api: () => import('./move-to.repository.js'), +}; + +export const manifests: Array = [bulkMoveRepository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/move-to.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/move-to.repository.ts new file mode 100644 index 0000000000..016ff9c665 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/move-to.repository.ts @@ -0,0 +1,36 @@ +import { UmbMoveMediaServerDataSource } from '../../../entity-actions/move-to/repository/media-move.server.data-source.js'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; +import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; +import type { UmbBulkMoveToRepository, UmbBulkMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-bulk-action'; +import type { UmbRepositoryErrorResponse } from '@umbraco-cms/backoffice/repository'; + +export class UmbBulkMoveToMediaRepository extends UmbRepositoryBase implements UmbBulkMoveToRepository { + #moveSource = new UmbMoveMediaServerDataSource(this); + + async requestBulkMoveTo(args: UmbBulkMoveToRequestArgs): Promise { + let count = 0; + + const destination = args.destination; + for (const unique of args.uniques) { + const { error } = await this.#moveSource.moveTo({ unique, destination }); + + if (error) { + const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT); + const notification = { data: { message: error.message } }; + notificationContext.peek('danger', notification); + } else { + count++; + } + } + + if (count > 0) { + const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT); + const notification = { data: { message: `Moved ${count} media items` } }; + notificationContext.peek('positive', notification); + } + + return {}; + } +} + +export { UmbBulkMoveToMediaRepository as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move/move.action.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move/move.action.ts deleted file mode 100644 index e3cf5b03ec..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move/move.action.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { UMB_MEDIA_TREE_PICKER_MODAL } from '../../tree/index.js'; -import { UmbEntityBulkActionBase } from '@umbraco-cms/backoffice/entity-bulk-action'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; - -export class UmbMediaMoveEntityBulkAction extends UmbEntityBulkActionBase { - async execute() { - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - // TODO: the picker should be single picker by default - const modalContext = modalManager.open(this, UMB_MEDIA_TREE_PICKER_MODAL, { - data: { - multiple: false, - }, - value: { - selection: [], - }, - }); - if (modalContext) { - //const { selection } = await modalContext.onSubmit(); - //const destination = selection[0]; - //await this.repository?.move(this.selection, destination); - } - } -} - -export { UmbMediaMoveEntityBulkAction as api }; From f367c565628a51c5fbfa6de5c1a5abf8e886a954 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 17 Jul 2024 11:11:26 +0100 Subject: [PATCH 4/7] Media Root: adds `UmbEntityContext` with a `unique` of `null`. This enables the Collection UI to refresh when entity bulk actions complete. --- .../media/section-view/media-section-view.element.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/section-view/media-section-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/section-view/media-section-view.element.ts index 8a1f3c6a11..c4effb5844 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/section-view/media-section-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/section-view/media-section-view.element.ts @@ -1,20 +1,23 @@ -import { UMB_MEDIA_COLLECTION_ALIAS } from '../collection/index.js'; import { UmbMediaCollectionRepository } from '../collection/repository/index.js'; +import { UMB_MEDIA_COLLECTION_ALIAS } from '../collection/index.js'; +import { UMB_MEDIA_ENTITY_TYPE } from '../entity.js'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbCollectionElement } from '@umbraco-cms/backoffice/collection'; import { UmbDataTypeDetailRepository } from '@umbraco-cms/backoffice/data-type'; +import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import type { UmbCollectionBulkActionPermissions, UmbCollectionConfiguration, } from '@umbraco-cms/backoffice/collection'; import type { UmbDataTypeDetailModel } from '@umbraco-cms/backoffice/data-type'; import type { UmbRoute } from '@umbraco-cms/backoffice/router'; -import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; @customElement('umb-media-section-view') export class UmbMediaSectionViewElement extends UmbLitElement { #dataTypeDetailRepository = new UmbDataTypeDetailRepository(this); + #entityContext = new UmbEntityContext(this); #mediaCollectionRepository = new UmbMediaCollectionRepository(this); @state() @@ -24,6 +27,9 @@ export class UmbMediaSectionViewElement extends UmbLitElement { super(); this.#defineRoutes(); + + this.#entityContext.setEntityType(UMB_MEDIA_ENTITY_TYPE); + this.#entityContext.setUnique(null); } async #defineRoutes() { From c6f3f24995d00a6d27581d43751e5493898e281b Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 17 Jul 2024 11:48:10 +0100 Subject: [PATCH 5/7] Refactored Media Bulk MoveTo repository notification context --- .../move-to/repository/move-to.repository.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/move-to.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/move-to.repository.ts index 016ff9c665..a8ea03a439 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/move-to.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/repository/move-to.repository.ts @@ -3,9 +3,19 @@ import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; import type { UmbBulkMoveToRepository, UmbBulkMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-bulk-action'; import type { UmbRepositoryErrorResponse } from '@umbraco-cms/backoffice/repository'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; export class UmbBulkMoveToMediaRepository extends UmbRepositoryBase implements UmbBulkMoveToRepository { #moveSource = new UmbMoveMediaServerDataSource(this); + #notificationContext?: typeof UMB_NOTIFICATION_CONTEXT.TYPE; + + constructor(host: UmbControllerHost) { + super(host); + + this.consumeContext(UMB_NOTIFICATION_CONTEXT, (notificationContext) => { + this.#notificationContext = notificationContext; + }); + } async requestBulkMoveTo(args: UmbBulkMoveToRequestArgs): Promise { let count = 0; @@ -15,18 +25,16 @@ export class UmbBulkMoveToMediaRepository extends UmbRepositoryBase implements U const { error } = await this.#moveSource.moveTo({ unique, destination }); if (error) { - const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT); const notification = { data: { message: error.message } }; - notificationContext.peek('danger', notification); + this.#notificationContext?.peek('danger', notification); } else { count++; } } if (count > 0) { - const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT); - const notification = { data: { message: `Moved ${count} media items` } }; - notificationContext.peek('positive', notification); + const notification = { data: { message: `Moved ${count} media ${count === 1 ? 'item' : 'items'}` } }; + this.#notificationContext?.peek('positive', notification); } return {}; From 47e2c41f9a5c4fa582efd89d6c4f288f08bdafba Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 17 Jul 2024 13:56:50 +0100 Subject: [PATCH 6/7] Corrects manifest type and includes missing property. --- .../packages/media/media/entity-bulk-actions/manifests.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/manifests.ts index 98f2769681..28c8b20dff 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/manifests.ts @@ -1,19 +1,21 @@ import { UMB_MEDIA_COLLECTION_ALIAS } from '../collection/index.js'; +import { UMB_MEDIA_ENTITY_TYPE } from '../entity.js'; import { manifests as moveToManifests } from './move-to/manifests.js'; import { UMB_COLLECTION_ALIAS_CONDITION, UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION, } from '@umbraco-cms/backoffice/collection'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestEntityBulkAction, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbCollectionBulkActionPermissions } from '@umbraco-cms/backoffice/collection'; -const entityBulkActions: Array = [ +const entityBulkActions: Array = [ { type: 'entityBulkAction', alias: 'Umb.EntityBulkAction.Media.Duplicate', name: 'Duplicate Media Entity Bulk Action', weight: 30, api: () => import('./duplicate/duplicate.action.js'), + forEntityTypes: [UMB_MEDIA_ENTITY_TYPE], meta: { label: 'Duplicate', }, @@ -34,6 +36,7 @@ const entityBulkActions: Array = [ name: 'Delete Media Entity Bulk Action', weight: 10, api: () => import('./delete/delete.action.js'), + forEntityTypes: [UMB_MEDIA_ENTITY_TYPE], meta: { label: 'Delete', }, From d505931970cfb042341ba167f15de3b30b0c2732 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 17 Jul 2024 13:57:24 +0100 Subject: [PATCH 7/7] `moveTo` kind, adds "reload structure" event --- .../common/move-to/move-to.action.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to.action.ts index a008d2c080..f248afe4e8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/common/move-to/move-to.action.ts @@ -1,7 +1,10 @@ import type { UmbBulkMoveToRepository } from './move-to-repository.interface.js'; import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; import { UmbEntityBulkActionBase } from '@umbraco-cms/backoffice/entity-bulk-action'; -import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { + UmbRequestReloadChildrenOfEntityEvent, + UmbRequestReloadStructureForEntityEvent, +} from '@umbraco-cms/backoffice/entity-action'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; @@ -46,8 +49,13 @@ export class UmbMediaMoveEntityBulkAction extends UmbEntityBulkActionBase