Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class UmbCollectionActionButtonElement extends UmbLitElement {
async #createApi() {
if (!this._manifest) throw new Error('No manifest defined');
if (!this._manifest.api) return;
this.#api = await createExtensionApi<UmbCollectionAction>(this, this._manifest);
this.#api = await createExtensionApi<UmbCollectionAction>(this, this._manifest, [this._manifest]);

this._href = (await this.#api?.getHref?.()) ?? this.manifest?.meta.href;
this._additionalOptions = (await this.#api?.hasAddionalOptions?.()) ?? this.manifest?.meta.additionalOptions;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { UMB_COLLECTION_CONTEXT } from '../default/index.js';
import type { UmbCollectionHasItemsConditionConfig } from './types.js';
import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry';
import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';

export class UmbCollectionHasItemsCondition
extends UmbConditionBase<UmbCollectionHasItemsConditionConfig>
implements UmbExtensionCondition
{
constructor(host: UmbControllerHost, args: UmbConditionControllerArguments<UmbCollectionHasItemsConditionConfig>) {
super(host, args);

this.consumeContext(UMB_COLLECTION_CONTEXT, (context) => {
this.observe(context?.totalItems, (totalItems) => {
this.permitted = !!totalItems && totalItems > 0;
});
});
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const UMB_COLLECTION_ALIAS_CONDITION = 'Umb.Condition.CollectionAlias';
export const UMB_COLLECTION_HAS_ITEMS_CONDITION_ALIAS = 'Umb.Condition.CollectionHasItems';
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './collection-alias.condition.js';
export * from './collection-has-items.condition.js';
export * from './constants.js';
export type * from './types.js';
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import UmbCollectionAliasCondition from './collection-alias.condition.js';
import { UMB_COLLECTION_ALIAS_CONDITION } from './constants.js';
import { UmbCollectionHasItemsCondition } from './collection-has-items.condition.js';
import { UMB_COLLECTION_ALIAS_CONDITION, UMB_COLLECTION_HAS_ITEMS_CONDITION_ALIAS } from './constants.js';
import type { ManifestCondition } from '@umbraco-cms/backoffice/extension-api';

export const manifests: Array<ManifestCondition> = [
Expand All @@ -9,4 +10,10 @@ export const manifests: Array<ManifestCondition> = [
alias: UMB_COLLECTION_ALIAS_CONDITION,
api: UmbCollectionAliasCondition,
},
{
type: 'condition',
name: 'Collection Has Items Condition',
alias: UMB_COLLECTION_HAS_ITEMS_CONDITION_ALIAS,
api: UmbCollectionHasItemsCondition,
},
];
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { UMB_COLLECTION_ALIAS_CONDITION } from './constants.js';
import type { UMB_COLLECTION_ALIAS_CONDITION, UMB_COLLECTION_HAS_ITEMS_CONDITION_ALIAS } from './constants.js';
import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api';

// eslint-disable-next-line @typescript-eslint/naming-convention
Expand All @@ -11,8 +11,13 @@ export type CollectionAliasConditionConfig = UmbConditionConfigBase<typeof UMB_C
match: string;
};

// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UmbCollectionHasItemsConditionConfig
extends UmbConditionConfigBase<typeof UMB_COLLECTION_HAS_ITEMS_CONDITION_ALIAS> {}

declare global {
interface UmbExtensionConditionConfigMap {
CollectionAliasConditionConfig: CollectionAliasConditionConfig;
UmbCollectionHasItemsConditionConfig: UmbCollectionHasItemsConditionConfig;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';

export const manifest: UmbExtensionManifestKind = {
type: 'kind',
alias: 'Umb.Kind.CollectionAction.RecycleBin.Empty',
matchKind: 'emptyRecycleBin',
matchType: 'collectionAction',
manifest: {
type: 'collectionAction',
kind: 'emptyRecycleBin',
api: () => import('./empty-recycle-bin.collection-action.js'),
elementName: 'umb-collection-action-button',
weight: 100,
meta: {
label: '#actions_emptyrecyclebin',
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { UmbCollectionActionBase } from '../../../collection/action/collection-action-base.js';
import type { UmbRecycleBinRepository } from '../../recycle-bin-repository.interface.js';
import type { ManifestCollectionActionEmptyRecycleBinKind } from './types.js';
import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action';
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
import { UMB_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection';
import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';

/**
* Collection action for emptying the recycle bin.
* @class UmbEmptyRecycleBinCollectionAction
* @augments {UmbCollectionActionBase}
*/
export class UmbEmptyRecycleBinCollectionAction extends UmbCollectionActionBase {
#manifest: ManifestCollectionActionEmptyRecycleBinKind;

constructor(host: UmbControllerHost, manifest: ManifestCollectionActionEmptyRecycleBinKind) {
super(host);
this.#manifest = manifest;
}

/**
* Executes the action.
* @memberof UmbEmptyRecycleBinCollectionAction
*/
async execute() {
if (!this.#manifest.meta.recycleBinRepositoryAlias) {
throw new Error('Recycle Bin Repository Alias is not defined in the manifest meta');
}

await umbConfirmModal(this._host, {
headline: `#actions_emptyrecyclebin`,
content: `#defaultdialogs_recycleBinWarning`,
color: 'danger',
confirmLabel: `#actions_emptyrecyclebin`,
});

const recycleBinRepository = await createExtensionApiByAlias<UmbRecycleBinRepository>(
this,
this.#manifest.meta.recycleBinRepositoryAlias,
);

const { error } = await recycleBinRepository.requestEmpty();
if (error) {
throw error;
}

// Refresh the collection
const collectionContext = await this.getContext(UMB_COLLECTION_CONTEXT);
collectionContext?.loadCollection();

// Refresh the tree (if any)
await this.#reloadChildrenOfEntity();
}

/**
* Requests a reload of the children of the current entity in the tree.
* Silently returns if the required contexts are not available.
*/
async #reloadChildrenOfEntity() {
const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT);
if (!eventContext) return;

const entityContext = await this.getContext(UMB_ENTITY_CONTEXT);
if (!entityContext) return;

const entityType = entityContext.getEntityType();
if (!entityType) return;

const unique = entityContext.getUnique();

const event = new UmbRequestReloadChildrenOfEntityEvent({ entityType, unique });
eventContext.dispatchEvent(event);
}
}

export { UmbEmptyRecycleBinCollectionAction as api };
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type * from './types.js';
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { manifest as emptyRecycleBinKindManifest } from './empty-recycle-bin.collection-action.kind.js';
import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';

export const manifests: Array<UmbExtensionManifest | UmbExtensionManifestKind> = [emptyRecycleBinKindManifest];
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { ManifestCollectionAction, MetaCollectionAction } from '@umbraco-cms/backoffice/collection';

export interface ManifestCollectionActionEmptyRecycleBinKind extends ManifestCollectionAction {
type: 'collectionAction';
kind: 'emptyRecycleBin';
meta: MetaCollectionActionEmptyRecycleBinKind;
}

export interface MetaCollectionActionEmptyRecycleBinKind extends MetaCollectionAction {
recycleBinRepositoryAlias: string;
}

declare global {
interface UmbExtensionManifestMap {
umbEmptyRecycleBinCollectionActionKind: ManifestCollectionActionEmptyRecycleBinKind;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type * from './empty-recycle-bin/index.js';
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { manifests as emptyRecycleBinManifests } from './empty-recycle-bin/manifests.js';
import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';

export const manifests: Array<UmbExtensionManifest | UmbExtensionManifestKind> = [...emptyRecycleBinManifests];
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const manifest: UmbExtensionManifestKind = {
forEntityTypes: [],
meta: {
icon: 'icon-trash-empty',
label: 'Empty Recycle Bin',
label: '#actions_emptyrecyclebin',
additionalOptions: true,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ export class UmbEmptyRecycleBinEntityAction extends UmbEntityActionBase<MetaEnti
*/
override async execute() {
await umbConfirmModal(this._host, {
headline: `Empty Recycle Bin`,
content: `When items are deleted from the recycle bin, they will be gone forever.`,
headline: `#actions_emptyrecyclebin`,
content: `#defaultdialogs_recycleBinWarning`,
color: 'danger',
confirmLabel: 'Empty Recycle Bin',
confirmLabel: '#actions_emptyrecyclebin',
});

const recycleBinRepository = await createExtensionApiByAlias<UmbRecycleBinRepository>(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export * from './constants.js';
export * from './entity-action/index.js';
export * from './entity-bulk-action/index.js';
export type * from './types.js';

export { UmbRecycleBinRepositoryBase } from './recycle-bin-repository-base.js';
export { UmbIsTrashedEntityContext } from './contexts/is-trashed/index.js';

export type * from './collection-action/index.js';
export type * from './types.js';
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { manifests as collectionActionManifests } from './collection-action/manifests.js';
import { manifests as conditionManifests } from './conditions/manifests.js';
import { manifests as emptyRecycleBinEntityActionManifests } from './entity-action/empty-recycle-bin/manifests.js';
import { manifests as restoreFromRecycleBinEntityActionManifests } from './entity-action/restore-from-recycle-bin/manifests.js';
Expand All @@ -8,6 +9,7 @@ import { manifests as treeManifests } from './tree/manifests.js';
import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';

export const manifests: Array<UmbExtensionManifest | UmbExtensionManifestKind> = [
...collectionActionManifests,
...conditionManifests,
...emptyRecycleBinEntityActionManifests,
...restoreFromRecycleBinEntityActionManifests,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
UMB_DOCUMENT_RECYCLE_BIN_TREE_ITEM_CHILDREN_COLLECTION_ALIAS,
} from '../constants.js';
import {
UMB_COLLECTION_ALIAS_CONDITION,
UMB_COLLECTION_HAS_ITEMS_CONDITION_ALIAS,
} from '@umbraco-cms/backoffice/collection';

export const manifests: Array<UmbExtensionManifest> = [
{
type: 'collectionAction',
kind: 'emptyRecycleBin',
name: 'Document Collection Empty Recycle Bin Action',
alias: 'Umb.CollectionAction.Document.EmptyRecycleBin',
meta: {
label: '#actions_emptyrecyclebin',
recycleBinRepositoryAlias: UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
},
conditions: [
{
alias: UMB_COLLECTION_ALIAS_CONDITION,
match: UMB_DOCUMENT_RECYCLE_BIN_TREE_ITEM_CHILDREN_COLLECTION_ALIAS,
},
{
alias: UMB_COLLECTION_HAS_ITEMS_CONDITION_ALIAS,
},
],
},
];
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { UmbAllowDocumentRecycleBinCurrentUserCondition } from './allow-document-recycle-bin.condition.js';
import { manifests as collectionManifests } from './collection-action/manifests.js';
import { manifests as entityActionManifests } from './entity-action/manifests.js';
import { manifests as menuManifests } from './menu/manifests.js';
import { manifests as repositoryManifests } from './repository/manifests.js';
Expand All @@ -12,6 +13,7 @@ export const manifests: Array<UmbExtensionManifest> = [
alias: 'Umb.Condition.CurrentUser.AllowDocumentRecycleBin',
api: UmbAllowDocumentRecycleBinCurrentUserCondition,
},
...collectionManifests,
...entityActionManifests,
...menuManifests,
...repositoryManifests,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
UMB_MEDIA_RECYCLE_BIN_REPOSITORY_ALIAS,
UMB_MEDIA_RECYCLE_BIN_TREE_ITEM_CHILDREN_COLLECTION_ALIAS,
} from '../constants.js';
import {
UMB_COLLECTION_ALIAS_CONDITION,
UMB_COLLECTION_HAS_ITEMS_CONDITION_ALIAS,
} from '@umbraco-cms/backoffice/collection';

export const manifests: Array<UmbExtensionManifest> = [
{
type: 'collectionAction',
kind: 'emptyRecycleBin',
name: 'Media Collection Empty Recycle Bin Action',
alias: 'Umb.CollectionAction.Media.EmptyRecycleBin',
meta: {
label: '#actions_emptyrecyclebin',
recycleBinRepositoryAlias: UMB_MEDIA_RECYCLE_BIN_REPOSITORY_ALIAS,
},
conditions: [
{
alias: UMB_COLLECTION_ALIAS_CONDITION,
match: UMB_MEDIA_RECYCLE_BIN_TREE_ITEM_CHILDREN_COLLECTION_ALIAS,
},
{
alias: UMB_COLLECTION_HAS_ITEMS_CONDITION_ALIAS,
},
],
},
];
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { manifests as collectionManifests } from './collection-action/manifests.js';
import { manifests as entityActionManifests } from './entity-action/manifests.js';
import { manifests as menuManifests } from './menu/manifests.js';
import { manifests as repositoryManifests } from './repository/manifests.js';
Expand All @@ -11,6 +12,7 @@ export const manifests: Array<UmbExtensionManifest> = [
alias: 'Umb.Condition.CurrentUser.AllowMediaRecycleBin',
api: () => import('./allow-media-recycle-bin.condition.js'),
},
...collectionManifests,
...entityActionManifests,
...menuManifests,
...repositoryManifests,
Expand Down
Loading