Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e3ff8689d | ||
|
|
d7410a08e1 | ||
|
|
6463334c2f | ||
|
|
aa8bbead4f | ||
|
|
2b0ceabf0b | ||
|
|
cc94607a27 | ||
|
|
32c3d17c48 | ||
|
|
9b070c0659 | ||
|
|
9b1534ff86 | ||
|
|
a92ea32d8a | ||
|
|
3e067495c1 | ||
|
|
608b1038c8 | ||
|
|
8dd829384d | ||
|
|
6dcc897986 | ||
|
|
c17d1983f2 | ||
|
|
7559785b3f | ||
|
|
3d6be7ada4 | ||
|
|
a63bdcd2f4 | ||
|
|
aafc107364 | ||
|
|
a17842499f | ||
|
|
7655089109 | ||
|
|
cbd7ea4938 | ||
|
|
c37302ee16 | ||
|
|
1f264f6cd3 | ||
|
|
e0eca329bb | ||
|
|
2823164bbb | ||
|
|
0e206b685d | ||
|
|
6815160683 | ||
|
|
1443b9cda2 | ||
|
|
f83ee80bcf | ||
|
|
5a38296153 | ||
|
|
8dd474d547 | ||
|
|
0a62426515 | ||
|
|
2cbe1efecd | ||
|
|
ac8955e84d | ||
|
|
edefa42f94 | ||
|
|
1c5aedfc73 | ||
|
|
2d3ca2928d | ||
|
|
11b3e04501 | ||
|
|
46b050a05b | ||
|
|
ece64d9b98 | ||
|
|
c18e8e7fd6 | ||
|
|
9e273f9c4c | ||
|
|
1e084b4d15 | ||
|
|
e31186772e | ||
|
|
d3e2db5859 | ||
|
|
dcc9b3d6e9 | ||
|
|
541753c9e4 | ||
|
|
a8324b6ba5 | ||
|
|
161c9d5ef5 | ||
|
|
b518e789a7 | ||
|
|
6b1891e48c | ||
|
|
23fd63d7fd | ||
|
|
83cf3c25ab | ||
|
|
c401187f95 | ||
|
|
ddbec2a14a | ||
|
|
a73116021c | ||
|
|
5f9d9d41da | ||
|
|
57b11457e1 | ||
|
|
193d93a41b | ||
|
|
bbc5fee737 | ||
|
|
54814c19bf | ||
|
|
934e03b345 | ||
|
|
81a0805e92 | ||
|
|
575f3b22c1 | ||
|
|
63e03ace30 | ||
|
|
75face7e78 | ||
|
|
fbf9f2f867 | ||
|
|
bb039685f2 | ||
|
|
f43e32e59a | ||
|
|
870cd86788 | ||
|
|
9f62268601 | ||
|
|
ec95d71ea7 | ||
|
|
bafd96bd93 | ||
|
|
1c8432ae4b | ||
|
|
f1dc763fb6 | ||
|
|
6dea5f0d73 | ||
|
|
1b04ec779d | ||
|
|
cf34d1972f | ||
|
|
c075debaa8 | ||
|
|
9b3f45d65a | ||
|
|
41a0c11285 | ||
|
|
a1444b5b2e | ||
|
|
dc1b5ce930 | ||
|
|
f218486ca6 | ||
|
|
dbb744dda5 | ||
|
|
d43c6cbeef | ||
|
|
9b478241ee | ||
|
|
fe1fbea8bb | ||
|
|
ff164c7235 | ||
|
|
f6ac0e45ac | ||
|
|
cdcbf3197d | ||
|
|
029cc3cfa6 | ||
|
|
ef1638b853 | ||
|
|
6f7cc8e7c0 | ||
|
|
0ae2420efa | ||
|
|
2b0ae998e1 | ||
|
|
f45ae29d25 | ||
|
|
e47217e25c | ||
|
|
9be6d8196c | ||
|
|
212ae20ed7 | ||
|
|
cb4df7584b | ||
|
|
e8ad351133 | ||
|
|
7fe30d7c75 | ||
|
|
0c15b411be | ||
|
|
2cb20c8f10 | ||
|
|
08d3add9af | ||
|
|
80b144ea0f | ||
|
|
4988c80f0c | ||
|
|
b52175078f | ||
|
|
3c67f00448 | ||
|
|
494fcbe025 | ||
|
|
13d5feaf30 | ||
|
|
0f727288bc | ||
|
|
ed0deb6284 | ||
|
|
a76b30a93a | ||
|
|
fa491109f1 | ||
|
|
4ffa3d6130 | ||
|
|
4394db3cce | ||
|
|
e446c42bae | ||
|
|
0afe46c04d | ||
|
|
e940f6ebdf | ||
|
|
dbd27cc0b6 | ||
|
|
93aa0ea16f | ||
|
|
c1276e478f | ||
|
|
dea4393b12 | ||
|
|
95c12ec778 | ||
|
|
33f37591d8 | ||
|
|
efe75be3d7 | ||
|
|
726d07dc59 | ||
|
|
914953b3ee | ||
|
|
d70fb9581a | ||
|
|
1088b04948 | ||
|
|
db9b9d3441 | ||
|
|
1adf436e5c | ||
|
|
f4547b5d3f | ||
|
|
3aba5686cb | ||
|
|
a98e3db4f0 | ||
|
|
b986ebd618 | ||
|
|
e1cbf73887 | ||
|
|
964e86ca77 | ||
|
|
d073ab50ed | ||
|
|
5b0444ffa2 | ||
|
|
5901d4a156 | ||
|
|
0731f66f66 | ||
|
|
977b047d8e | ||
|
|
fd06887aa1 | ||
|
|
62f1bd7d43 | ||
|
|
edb6a7c40f | ||
|
|
e7348f56eb | ||
|
|
f99562a47c | ||
|
|
9ccb58acca | ||
|
|
01516bb142 |
@@ -510,6 +510,7 @@ export default {
|
||||
confirmremoveusageof: 'Are you sure you want to remove the usage of <strong>%0%</strong>',
|
||||
confirmlogout: 'Are you sure?',
|
||||
confirmSure: 'Are you sure?',
|
||||
confirmTrash: (name: string) => `Are you sure you want to move <strong>${name}</strong> to the Recycle Bin?`,
|
||||
cut: 'Cut',
|
||||
editDictionary: 'Edit dictionary item',
|
||||
editLanguage: 'Edit language',
|
||||
|
||||
@@ -5,17 +5,19 @@ import { UUIRefNodeElement } from '@umbraco-cms/backoffice/external/uui';
|
||||
@customElement('umb-ref-item')
|
||||
export class UmbRefItemElement extends UmbElementMixin(UUIRefNodeElement) {
|
||||
@property({ type: String })
|
||||
icon = '';
|
||||
icon? = '';
|
||||
|
||||
#iconElement = document.createElement('umb-icon');
|
||||
|
||||
protected override firstUpdated(_changedProperties: PropertyValues): void {
|
||||
super.firstUpdated(_changedProperties);
|
||||
|
||||
// Temporary fix for the icon appending, this could in the future be changed to override a renderIcon method, or other ways to make this happen without appending children.
|
||||
this.#iconElement.setAttribute('slot', 'icon');
|
||||
this.#iconElement.setAttribute('name', this.icon);
|
||||
this.appendChild(this.#iconElement);
|
||||
if (this.icon) {
|
||||
// Temporary fix for the icon appending, this could in the future be changed to override a renderIcon method, or other ways to make this happen without appending children.
|
||||
this.#iconElement.setAttribute('slot', 'icon');
|
||||
this.#iconElement.setAttribute('name', this.icon);
|
||||
this.appendChild(this.#iconElement);
|
||||
}
|
||||
}
|
||||
|
||||
static override styles = [
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export * from './create/constants.js';
|
||||
export * from './delete/constants.js';
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { UMB_ENTITY_ACTION_DELETE_KIND_MANIFEST } from './delete.action.kind.js';
|
||||
+3
-1
@@ -1,7 +1,7 @@
|
||||
import { UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST } from '../../default/default.action.kind.js';
|
||||
import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifest: UmbExtensionManifestKind = {
|
||||
export const UMB_ENTITY_ACTION_DELETE_KIND_MANIFEST: UmbExtensionManifestKind = {
|
||||
type: 'kind',
|
||||
alias: 'Umb.Kind.EntityAction.Delete',
|
||||
matchKind: 'delete',
|
||||
@@ -22,3 +22,5 @@ export const manifest: UmbExtensionManifestKind = {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const manifest = UMB_ENTITY_ACTION_DELETE_KIND_MANIFEST;
|
||||
|
||||
+37
-17
@@ -7,13 +7,45 @@ import type { UmbDetailRepository, UmbItemRepository } from '@umbraco-cms/backof
|
||||
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
|
||||
import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api';
|
||||
|
||||
export class UmbDeleteEntityAction extends UmbEntityActionBase<MetaEntityActionDeleteKind> {
|
||||
export class UmbDeleteEntityAction<
|
||||
MetaKind extends MetaEntityActionDeleteKind = MetaEntityActionDeleteKind,
|
||||
> extends UmbEntityActionBase<MetaKind> {
|
||||
// TODO: make base type for item and detail models
|
||||
#localize = new UmbLocalizationController(this);
|
||||
|
||||
override async execute() {
|
||||
if (!this.args.unique) throw new Error('Cannot delete an item without a unique identifier.');
|
||||
|
||||
const item = await this.#requestItem();
|
||||
|
||||
await this._confirmDelete(item);
|
||||
|
||||
const detailRepository = await createExtensionApiByAlias<UmbDetailRepository<any>>(
|
||||
this,
|
||||
this.args.meta.detailRepositoryAlias,
|
||||
);
|
||||
|
||||
await detailRepository.delete(this.args.unique);
|
||||
|
||||
await this.#notify();
|
||||
}
|
||||
|
||||
async _confirmDelete(item: any) {
|
||||
const headline = this.args.meta.confirm?.headline ?? '#actions_delete';
|
||||
const message = this.args.meta.confirm?.message ?? '#defaultdialogs_confirmdelete';
|
||||
|
||||
// TODO: handle items with variants
|
||||
await umbConfirmModal(this._host, {
|
||||
headline,
|
||||
content: this.#localize.string(message, item.name),
|
||||
color: 'danger',
|
||||
confirmLabel: '#general_delete',
|
||||
});
|
||||
}
|
||||
|
||||
async #requestItem() {
|
||||
if (!this.args.unique) throw new Error('Cannot delete an item without a unique identifier.');
|
||||
|
||||
const itemRepository = await createExtensionApiByAlias<UmbItemRepository<any>>(
|
||||
this,
|
||||
this.args.meta.itemRepositoryAlias,
|
||||
@@ -23,24 +55,12 @@ export class UmbDeleteEntityAction extends UmbEntityActionBase<MetaEntityActionD
|
||||
const item = data?.[0];
|
||||
if (!item) throw new Error('Item not found.');
|
||||
|
||||
const headline = this.args.meta.confirm?.headline ?? '#actions_delete';
|
||||
const message = this.args.meta.confirm?.message ?? '#defaultdialogs_confirmdelete';
|
||||
|
||||
// TODO: handle items with variants
|
||||
await umbConfirmModal(this._host, {
|
||||
headline,
|
||||
content: this.#localize.string(message, item.name),
|
||||
color: 'danger',
|
||||
confirmLabel: '#general_delete',
|
||||
});
|
||||
|
||||
const detailRepository = await createExtensionApiByAlias<UmbDetailRepository<any>>(
|
||||
this,
|
||||
this.args.meta.detailRepositoryAlias,
|
||||
);
|
||||
await detailRepository.delete(this.args.unique);
|
||||
return item;
|
||||
}
|
||||
|
||||
async #notify() {
|
||||
const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT);
|
||||
|
||||
const event = new UmbRequestReloadStructureForEntityEvent({
|
||||
unique: this.args.unique,
|
||||
entityType: this.args.entityType,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export type * from './delete/types.js';
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
|
||||
|
||||
export type * from './common/types.js';
|
||||
export type * from './default/types.js';
|
||||
export type * from './entity-action-element.interface.js';
|
||||
export type * from './entity-action.extension.js';
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export * from './restore-from-recycle-bin/constants.js';
|
||||
export * from './trash/constants.js';
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
export { UMB_ENTITY_ACTION_TRASH_KIND_MANIFEST } from './trash.action.kind.js';
|
||||
+3
-4
@@ -1,7 +1,7 @@
|
||||
import { UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST } from '../../../entity-action/default/default.action.kind.js';
|
||||
import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifest: UmbExtensionManifestKind = {
|
||||
export const UMB_ENTITY_ACTION_TRASH_KIND_MANIFEST: UmbExtensionManifestKind = {
|
||||
type: 'kind',
|
||||
alias: 'Umb.Kind.EntityAction.Trash',
|
||||
matchKind: 'trash',
|
||||
@@ -12,13 +12,12 @@ export const manifest: UmbExtensionManifestKind = {
|
||||
kind: 'trash',
|
||||
api: () => import('./trash.action.js'),
|
||||
weight: 1150,
|
||||
forEntityTypes: [],
|
||||
meta: {
|
||||
icon: 'icon-trash',
|
||||
label: '#actions_trash',
|
||||
itemRepositoryAlias: '',
|
||||
recycleBinRepositoryAlias: '',
|
||||
additionalOptions: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const manifest = UMB_ENTITY_ACTION_TRASH_KIND_MANIFEST;
|
||||
|
||||
+39
-20
@@ -1,19 +1,23 @@
|
||||
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 './types.js';
|
||||
import { UmbEntityTrashedEvent } from './trash.event.js';
|
||||
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';
|
||||
import type { UmbItemRepository } from '@umbraco-cms/backoffice/repository';
|
||||
import { UmbEntityActionBase, UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api';
|
||||
|
||||
/**
|
||||
* Entity action for trashing an item.
|
||||
* @class UmbTrashEntityAction
|
||||
* @augments {UmbEntityActionBase<MetaEntityActionTrashKind>}
|
||||
*/
|
||||
export class UmbTrashEntityAction extends UmbEntityActionBase<MetaEntityActionTrashKind> {
|
||||
export class UmbTrashEntityAction<
|
||||
MetaKindType extends MetaEntityActionTrashKind = MetaEntityActionTrashKind,
|
||||
> extends UmbEntityActionBase<MetaKindType> {
|
||||
#localize = new UmbLocalizationController(this);
|
||||
|
||||
/**
|
||||
* Executes the action.
|
||||
* @memberof UmbTrashEntityAction
|
||||
@@ -21,6 +25,36 @@ export class UmbTrashEntityAction extends UmbEntityActionBase<MetaEntityActionTr
|
||||
override async execute() {
|
||||
if (!this.args.unique) throw new Error('Cannot trash an item without a unique identifier.');
|
||||
|
||||
const item = await this.#requestItem();
|
||||
|
||||
await this._confirmTrash(item);
|
||||
|
||||
const recycleBinRepository = await createExtensionApiByAlias<UmbRecycleBinRepository>(
|
||||
this,
|
||||
this.args.meta.recycleBinRepositoryAlias,
|
||||
);
|
||||
|
||||
await recycleBinRepository.requestTrash({ unique: this.args.unique });
|
||||
|
||||
this.#notify();
|
||||
}
|
||||
|
||||
protected async _confirmTrash(item: any) {
|
||||
const headline = '#actions_trash';
|
||||
const message = '#defaultdialogs_confirmTrash';
|
||||
|
||||
// TODO: handle items with variants
|
||||
await umbConfirmModal(this._host, {
|
||||
headline,
|
||||
content: this.#localize.string(message, item.name),
|
||||
color: 'danger',
|
||||
confirmLabel: '#actions_trash',
|
||||
});
|
||||
}
|
||||
|
||||
async #requestItem() {
|
||||
if (!this.args.unique) throw new Error('Cannot trash an item without a unique identifier.');
|
||||
|
||||
const itemRepository = await createExtensionApiByAlias<UmbItemRepository<any>>(
|
||||
this,
|
||||
this.args.meta.itemRepositoryAlias,
|
||||
@@ -29,22 +63,7 @@ export class UmbTrashEntityAction extends UmbEntityActionBase<MetaEntityActionTr
|
||||
const { data } = await itemRepository.requestItems([this.args.unique]);
|
||||
const item = data?.[0];
|
||||
if (!item) throw new Error('Item not found.');
|
||||
|
||||
// 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',
|
||||
});
|
||||
|
||||
const recycleBinRepository = await createExtensionApiByAlias<UmbRecycleBinRepository>(
|
||||
this,
|
||||
this.args.meta.recycleBinRepositoryAlias,
|
||||
);
|
||||
await recycleBinRepository.requestTrash({ unique: this.args.unique });
|
||||
|
||||
this.#notify();
|
||||
return item;
|
||||
}
|
||||
|
||||
async #notify() {
|
||||
|
||||
+3
-1
@@ -2,6 +2,7 @@ import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS } from '../repository/index.js';
|
||||
import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../item/constants.js';
|
||||
import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js';
|
||||
import { UMB_USER_PERMISSION_DOCUMENT_DELETE } from '../user-permissions/constants.js';
|
||||
import { UMB_DOCUMENT_REFERENCE_REPOSITORY_ALIAS } from '../reference/constants.js';
|
||||
import { manifests as createBlueprintManifests } from './create-blueprint/manifests.js';
|
||||
import { manifests as createManifests } from './create/manifests.js';
|
||||
import { manifests as cultureAndHostnamesManifests } from './culture-and-hostnames/manifests.js';
|
||||
@@ -15,13 +16,14 @@ import { UMB_ENTITY_IS_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/r
|
||||
const entityActions: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'entityAction',
|
||||
kind: 'delete',
|
||||
kind: 'deleteWithRelation',
|
||||
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,
|
||||
referenceRepositoryAlias: UMB_DOCUMENT_REFERENCE_REPOSITORY_ALIAS,
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
|
||||
+3
-1
@@ -5,6 +5,7 @@ import {
|
||||
UMB_USER_PERMISSION_DOCUMENT_DELETE,
|
||||
UMB_USER_PERMISSION_DOCUMENT_MOVE,
|
||||
} from '../../constants.js';
|
||||
import { UMB_DOCUMENT_REFERENCE_REPOSITORY_ALIAS } from '../../reference/constants.js';
|
||||
import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../item/constants.js';
|
||||
import {
|
||||
UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS,
|
||||
@@ -14,13 +15,14 @@ import {
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'entityAction',
|
||||
kind: 'trash',
|
||||
kind: 'trashWithRelation',
|
||||
alias: 'Umb.EntityAction.Document.RecycleBin.Trash',
|
||||
name: 'Trash Document Entity Action',
|
||||
forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE],
|
||||
meta: {
|
||||
itemRepositoryAlias: UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS,
|
||||
recycleBinRepositoryAlias: UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
|
||||
referenceRepositoryAlias: UMB_DOCUMENT_REFERENCE_REPOSITORY_ALIAS,
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
|
||||
+2
-1
@@ -44,7 +44,8 @@ export class UmbDocumentReferenceTableElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
if (!data) return;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
this._items = data.items;
|
||||
this._hasMoreReferences = data.total > this.#pageSize ? data.total - this.#pageSize : 0;
|
||||
}
|
||||
|
||||
+7
-1
@@ -1,8 +1,9 @@
|
||||
import { UmbDocumentReferenceServerDataSource } from './document-reference.server.data.js';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbEntityReferenceRepository } from '@umbraco-cms/backoffice/relations';
|
||||
|
||||
export class UmbDocumentReferenceRepository extends UmbControllerBase {
|
||||
export class UmbDocumentReferenceRepository extends UmbControllerBase implements UmbEntityReferenceRepository {
|
||||
#referenceSource: UmbDocumentReferenceServerDataSource;
|
||||
|
||||
constructor(host: UmbControllerHost) {
|
||||
@@ -14,6 +15,11 @@ export class UmbDocumentReferenceRepository extends UmbControllerBase {
|
||||
if (!unique) throw new Error(`unique is required`);
|
||||
return this.#referenceSource.getReferencedBy(unique, skip, take);
|
||||
}
|
||||
|
||||
async requestDescendantsWithReferences(unique: string, skip = 0, take = 20) {
|
||||
if (!unique) throw new Error(`unique is required`);
|
||||
return this.#referenceSource.getReferencedDescendants(unique, skip, take);
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbDocumentReferenceRepository;
|
||||
|
||||
+45
-3
@@ -1,22 +1,32 @@
|
||||
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
|
||||
import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
|
||||
import type { UmbEntityReferenceDataSource, UmbReferenceItemModel } from '@umbraco-cms/backoffice/relations';
|
||||
import type { UmbPagedModel, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';
|
||||
import { UmbManagementApiDataMapper } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
/**
|
||||
* @class UmbDocumentReferenceServerDataSource
|
||||
* @implements {RepositoryDetailDataSource}
|
||||
*/
|
||||
export class UmbDocumentReferenceServerDataSource extends UmbControllerBase {
|
||||
export class UmbDocumentReferenceServerDataSource extends UmbControllerBase implements UmbEntityReferenceDataSource {
|
||||
#dataMapper = new UmbManagementApiDataMapper(this);
|
||||
|
||||
/**
|
||||
* Fetches the item for the given unique from the server
|
||||
* @param {string} unique - The unique identifier of the item to fetch
|
||||
* @returns {*}
|
||||
* @param {number} skip - The number of items to skip
|
||||
* @param {number} take - The number of items to take
|
||||
* @returns {Promise<UmbDataSourceResponse<UmbPagedModel<UmbReferenceItemModel>>>} - Items that are referenced by the given unique
|
||||
* @memberof UmbDocumentReferenceServerDataSource
|
||||
*/
|
||||
async getReferencedBy(unique: string, skip = 0, take = 20) {
|
||||
async getReferencedBy(
|
||||
unique: string,
|
||||
skip = 0,
|
||||
take = 20,
|
||||
): Promise<UmbDataSourceResponse<UmbPagedModel<UmbReferenceItemModel>>> {
|
||||
const { data, error } = await tryExecuteAndNotify(
|
||||
this,
|
||||
DocumentService.getDocumentByIdReferencedBy({ id: unique, skip, take }),
|
||||
@@ -44,4 +54,36 @@ export class UmbDocumentReferenceServerDataSource extends UmbControllerBase {
|
||||
|
||||
return { data, error };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any descendants of the given unique that is referenced by other items
|
||||
* @param {string} unique - The unique identifier of the item to fetch descendants for
|
||||
* @param {number} skip - The number of items to skip
|
||||
* @param {number} take - The number of items to take
|
||||
* @returns {Promise<UmbDataSourceResponse<UmbPagedModel<UmbEntityModel>>>} - Any descendants of the given unique that is referenced by other items
|
||||
* @memberof UmbDocumentReferenceServerDataSource
|
||||
*/
|
||||
async getReferencedDescendants(
|
||||
unique: string,
|
||||
skip: number = 0,
|
||||
take: number = 20,
|
||||
): Promise<UmbDataSourceResponse<UmbPagedModel<UmbEntityModel>>> {
|
||||
const { data, error } = await tryExecuteAndNotify(
|
||||
this,
|
||||
DocumentService.getDocumentByIdReferencedDescendants({ id: unique, skip, take }),
|
||||
);
|
||||
|
||||
if (data) {
|
||||
const items: Array<UmbEntityModel> = data.items.map((item) => {
|
||||
return {
|
||||
unique: item.id,
|
||||
entityType: UMB_DOCUMENT_ENTITY_TYPE,
|
||||
};
|
||||
});
|
||||
|
||||
return { data: { items, total: data.total } };
|
||||
}
|
||||
|
||||
return { data, error };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { UMB_MEDIA_DETAIL_REPOSITORY_ALIAS, UMB_MEDIA_ITEM_REPOSITORY_ALIAS } from '../constants.js';
|
||||
import {
|
||||
UMB_MEDIA_DETAIL_REPOSITORY_ALIAS,
|
||||
UMB_MEDIA_ITEM_REPOSITORY_ALIAS,
|
||||
UMB_MEDIA_REFERENCE_REPOSITORY_ALIAS,
|
||||
} from '../constants.js';
|
||||
import { UMB_MEDIA_ENTITY_TYPE } from '../entity.js';
|
||||
import { manifests as createManifests } from './create/manifests.js';
|
||||
import { manifests as moveManifests } from './move-to/manifests.js';
|
||||
@@ -11,11 +15,12 @@ export const manifests: Array<UmbExtensionManifest> = [
|
||||
type: 'entityAction',
|
||||
alias: 'Umb.EntityAction.Media.Delete',
|
||||
name: 'Delete Media Entity Action ',
|
||||
kind: 'delete',
|
||||
kind: 'deleteWithRelation',
|
||||
forEntityTypes: [UMB_MEDIA_ENTITY_TYPE],
|
||||
meta: {
|
||||
itemRepositoryAlias: UMB_MEDIA_ITEM_REPOSITORY_ALIAS,
|
||||
detailRepositoryAlias: UMB_MEDIA_DETAIL_REPOSITORY_ALIAS,
|
||||
referenceRepositoryAlias: UMB_MEDIA_REFERENCE_REPOSITORY_ALIAS,
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@ export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'entityItemRef',
|
||||
alias: 'Umb.EntityItemRef.Media',
|
||||
name: 'Member Entity Item Reference',
|
||||
name: 'Media Entity Item Reference',
|
||||
element: () => import('./media-item-ref.element.js'),
|
||||
forEntityTypes: [UMB_MEDIA_ENTITY_TYPE],
|
||||
},
|
||||
|
||||
+3
-1
@@ -4,6 +4,7 @@ import {
|
||||
UMB_MEDIA_ENTITY_TYPE,
|
||||
} from '../../constants.js';
|
||||
import { UMB_MEDIA_RECYCLE_BIN_ROOT_ENTITY_TYPE, UMB_MEDIA_RECYCLE_BIN_REPOSITORY_ALIAS } from '../constants.js';
|
||||
import { UMB_MEDIA_REFERENCE_REPOSITORY_ALIAS } from '../../reference/constants.js';
|
||||
import {
|
||||
UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS,
|
||||
UMB_ENTITY_IS_TRASHED_CONDITION_ALIAS,
|
||||
@@ -12,13 +13,14 @@ import {
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'entityAction',
|
||||
kind: 'trash',
|
||||
kind: 'trashWithRelation',
|
||||
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,
|
||||
referenceRepositoryAlias: UMB_MEDIA_REFERENCE_REPOSITORY_ALIAS,
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
|
||||
+7
-1
@@ -1,8 +1,9 @@
|
||||
import { UmbMediaReferenceServerDataSource } from './media-reference.server.data.js';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbEntityReferenceRepository } from '@umbraco-cms/backoffice/relations';
|
||||
|
||||
export class UmbMediaReferenceRepository extends UmbControllerBase {
|
||||
export class UmbMediaReferenceRepository extends UmbControllerBase implements UmbEntityReferenceRepository {
|
||||
#referenceSource: UmbMediaReferenceServerDataSource;
|
||||
|
||||
constructor(host: UmbControllerHost) {
|
||||
@@ -14,6 +15,11 @@ export class UmbMediaReferenceRepository extends UmbControllerBase {
|
||||
if (!unique) throw new Error(`unique is required`);
|
||||
return this.#referenceSource.getReferencedBy(unique, skip, take);
|
||||
}
|
||||
|
||||
async requestDescendantsWithReferences(unique: string, skip = 0, take = 20) {
|
||||
if (!unique) throw new Error(`unique is required`);
|
||||
return this.#referenceSource.getReferencedDescendants(unique, skip, take);
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbMediaReferenceRepository;
|
||||
|
||||
+47
-5
@@ -1,22 +1,32 @@
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import { UMB_MEDIA_ENTITY_TYPE } from '../../entity.js';
|
||||
import { MediaService } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { UmbManagementApiDataMapper } from '@umbraco-cms/backoffice/repository';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
|
||||
import type { UmbEntityReferenceDataSource, UmbReferenceItemModel } from '@umbraco-cms/backoffice/relations';
|
||||
import type { UmbPagedModel, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
/**
|
||||
* @class UmbMediaReferenceServerDataSource
|
||||
* @implements {RepositoryDetailDataSource}
|
||||
*/
|
||||
export class UmbMediaReferenceServerDataSource extends UmbControllerBase {
|
||||
export class UmbMediaReferenceServerDataSource extends UmbControllerBase implements UmbEntityReferenceDataSource {
|
||||
#dataMapper = new UmbManagementApiDataMapper(this);
|
||||
|
||||
/**
|
||||
* Fetches the item for the given id from the server
|
||||
* Fetches the item for the given unique from the server
|
||||
* @param {string} unique - The unique identifier of the item to fetch
|
||||
* @returns {*}
|
||||
* @param {number} skip - The number of items to skip
|
||||
* @param {number} take - The number of items to take
|
||||
* @returns {Promise<UmbDataSourceResponse<UmbPagedModel<UmbReferenceItemModel>>>} - Items that are referenced by the given unique
|
||||
* @memberof UmbMediaReferenceServerDataSource
|
||||
*/
|
||||
async getReferencedBy(unique: string, skip = 0, take = 20) {
|
||||
async getReferencedBy(
|
||||
unique: string,
|
||||
skip: number = 0,
|
||||
take: number = 20,
|
||||
): Promise<UmbDataSourceResponse<UmbPagedModel<UmbReferenceItemModel>>> {
|
||||
const { data, error } = await tryExecuteAndNotify(
|
||||
this,
|
||||
MediaService.getMediaByIdReferencedBy({ id: unique, skip, take }),
|
||||
@@ -44,4 +54,36 @@ export class UmbMediaReferenceServerDataSource extends UmbControllerBase {
|
||||
|
||||
return { data, error };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any descendants of the given unique that is referenced by other items
|
||||
* @param {string} unique - The unique identifier of the item to fetch descendants for
|
||||
* @param {number} skip - The number of items to skip
|
||||
* @param {number} take - The number of items to take
|
||||
* @returns {Promise<UmbDataSourceResponse<UmbPagedModel<UmbEntityModel>>>} - Any descendants of the given unique that is referenced by other items
|
||||
* @memberof UmbMediaReferenceServerDataSource
|
||||
*/
|
||||
async getReferencedDescendants(
|
||||
unique: string,
|
||||
skip: number = 0,
|
||||
take: number = 20,
|
||||
): Promise<UmbDataSourceResponse<UmbPagedModel<UmbEntityModel>>> {
|
||||
const { data, error } = await tryExecuteAndNotify(
|
||||
this,
|
||||
MediaService.getMediaByIdReferencedDescendants({ id: unique, skip, take }),
|
||||
);
|
||||
|
||||
if (data) {
|
||||
const items: Array<UmbEntityModel> = data.items.map((item) => {
|
||||
return {
|
||||
unique: item.id,
|
||||
entityType: UMB_MEDIA_ENTITY_TYPE,
|
||||
};
|
||||
});
|
||||
|
||||
return { data: { items, total: data.total } };
|
||||
}
|
||||
|
||||
return { data, error };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@ import { manifests as menuManifests } from './menu/manifests.js';
|
||||
import { manifests as relationManifests } from './relations/manifests.js';
|
||||
import { manifests as relationTypeManifests } from './relation-types/manifests.js';
|
||||
import { manifests as workspaceManifests } from './workspace/manifests.js';
|
||||
import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
export const manifests: Array<UmbExtensionManifest | UmbExtensionManifestKind> = [
|
||||
...menuManifests,
|
||||
...relationManifests,
|
||||
...relationTypeManifests,
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
export * from './collection/constants.js';
|
||||
export { UMB_RELATION_ENTITY_TYPE } from './entity.js';
|
||||
export * from './collection/constants.js';
|
||||
export * from './entity-actions/delete/constants.js';
|
||||
export * from './entity-actions/trash/constants.js';
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
export * from './modal/constants.js';
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { UMB_ENTITY_ACTION_DELETE_KIND_MANIFEST } from '@umbraco-cms/backoffice/entity-action';
|
||||
|
||||
export const manifest: UmbExtensionManifestKind = {
|
||||
type: 'kind',
|
||||
alias: 'Umb.Kind.EntityAction.DeleteWithRelation',
|
||||
matchKind: 'deleteWithRelation',
|
||||
matchType: 'entityAction',
|
||||
manifest: {
|
||||
...UMB_ENTITY_ACTION_DELETE_KIND_MANIFEST.manifest,
|
||||
type: 'entityAction',
|
||||
kind: 'deleteWithRelation',
|
||||
api: () => import('./delete-with-relation.action.js'),
|
||||
},
|
||||
};
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import type { MetaEntityActionDeleteWithRelationKind } from './types.js';
|
||||
import { UMB_DELETE_WITH_RELATION_CONFIRM_MODAL } from './modal/constants.js';
|
||||
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
|
||||
import { UmbDeleteEntityAction } from '@umbraco-cms/backoffice/entity-action';
|
||||
|
||||
/**
|
||||
* Entity action for deleting an item with relations.
|
||||
* @class UmbDeleteWithRelationEntityAction
|
||||
* @augments {UmbEntityActionBase<MetaEntityActionDeleteWithRelationKind>}
|
||||
*/
|
||||
export class UmbDeleteWithRelationEntityAction extends UmbDeleteEntityAction<MetaEntityActionDeleteWithRelationKind> {
|
||||
override async _confirmDelete() {
|
||||
if (!this.args.unique) throw new Error('Cannot delete an item without a unique identifier.');
|
||||
|
||||
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
|
||||
|
||||
const modal = modalManager.open(this, UMB_DELETE_WITH_RELATION_CONFIRM_MODAL, {
|
||||
data: {
|
||||
unique: this.args.unique,
|
||||
entityType: this.args.entityType,
|
||||
itemRepositoryAlias: this.args.meta.itemRepositoryAlias,
|
||||
referenceRepositoryAlias: this.args.meta.referenceRepositoryAlias,
|
||||
},
|
||||
});
|
||||
|
||||
await modal.onSubmit();
|
||||
}
|
||||
}
|
||||
|
||||
export { UmbDeleteWithRelationEntityAction as api };
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export * from './delete-with-relation.action.js';
|
||||
export type * from './types.js';
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { manifest as deleteKindManifest } from './delete-with-relation.action.kind.js';
|
||||
import { manifests as modalManifests } from './modal/manifests.js';
|
||||
|
||||
import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest | UmbExtensionManifestKind> = [
|
||||
deleteKindManifest,
|
||||
...modalManifests,
|
||||
];
|
||||
+1
@@ -0,0 +1 @@
|
||||
export * from './delete-with-relation-modal.token.js';
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
import type {
|
||||
UmbDeleteWithRelationConfirmModalData,
|
||||
UmbDeleteWithRelationConfirmModalValue,
|
||||
} from './delete-with-relation-modal.token.js';
|
||||
import {
|
||||
html,
|
||||
customElement,
|
||||
css,
|
||||
state,
|
||||
type PropertyValues,
|
||||
nothing,
|
||||
unsafeHTML,
|
||||
} from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
|
||||
import { umbFocus } from '@umbraco-cms/backoffice/lit-element';
|
||||
import type { UmbItemRepository } from '@umbraco-cms/backoffice/repository';
|
||||
import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
import '../../local-components/confirm-action-entity-references.element.js';
|
||||
|
||||
@customElement('umb-delete-with-relation-confirm-modal')
|
||||
export class UmbDeleteWithRelationConfirmModalElement extends UmbModalBaseElement<
|
||||
UmbDeleteWithRelationConfirmModalData,
|
||||
UmbDeleteWithRelationConfirmModalValue
|
||||
> {
|
||||
@state()
|
||||
_name?: string;
|
||||
|
||||
@state()
|
||||
_referencesConfig?: any;
|
||||
|
||||
#itemRepository?: UmbItemRepository<any>;
|
||||
|
||||
protected override firstUpdated(_changedProperties: PropertyValues): void {
|
||||
super.firstUpdated(_changedProperties);
|
||||
this.#initData();
|
||||
}
|
||||
|
||||
async #initData() {
|
||||
if (!this.data) {
|
||||
this.#itemRepository?.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
this.#itemRepository = await createExtensionApiByAlias<UmbItemRepository<any>>(this, this.data.itemRepositoryAlias);
|
||||
|
||||
const { data } = await this.#itemRepository.requestItems([this.data.unique]);
|
||||
const item = data?.[0];
|
||||
if (!item) throw new Error('Item not found.');
|
||||
|
||||
this._name = item.name;
|
||||
|
||||
this._referencesConfig = {
|
||||
unique: this.data.unique,
|
||||
itemRepositoryAlias: this.data.itemRepositoryAlias,
|
||||
referenceRepositoryAlias: this.data.referenceRepositoryAlias,
|
||||
};
|
||||
}
|
||||
|
||||
override render() {
|
||||
const headline = this.localize.string('#actions_delete');
|
||||
const content = this.localize.string('#defaultdialogs_confirmdelete', this._name);
|
||||
|
||||
return html`
|
||||
<uui-dialog-layout class="uui-text" headline=${headline}>
|
||||
<p>${unsafeHTML(content)}</p>
|
||||
${this._referencesConfig
|
||||
? html`<umb-confirm-action-modal-entity-references
|
||||
.config=${this._referencesConfig}></umb-confirm-action-modal-entity-references>`
|
||||
: nothing}
|
||||
|
||||
<uui-button
|
||||
slot="actions"
|
||||
id="cancel"
|
||||
label=${this.localize.term('general_cancel')}
|
||||
@click=${this._rejectModal}></uui-button>
|
||||
|
||||
<uui-button
|
||||
slot="actions"
|
||||
id="confirm"
|
||||
color="danger"
|
||||
look="primary"
|
||||
label=${this.localize.term('general_delete')}
|
||||
@click=${this._submitModal}
|
||||
${umbFocus()}></uui-button>
|
||||
</uui-dialog-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static override styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
uui-dialog-layout {
|
||||
max-inline-size: 60ch;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export { UmbDeleteWithRelationConfirmModalElement as element };
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-delete-with-relation-confirm-modal': UmbDeleteWithRelationConfirmModalElement;
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
export interface UmbDeleteWithRelationConfirmModalData {
|
||||
unique: string;
|
||||
entityType: string;
|
||||
itemRepositoryAlias: string;
|
||||
referenceRepositoryAlias: string;
|
||||
}
|
||||
|
||||
export type UmbDeleteWithRelationConfirmModalValue = undefined;
|
||||
|
||||
export const UMB_DELETE_WITH_RELATION_CONFIRM_MODAL = new UmbModalToken<
|
||||
UmbDeleteWithRelationConfirmModalData,
|
||||
UmbDeleteWithRelationConfirmModalValue
|
||||
>('Umb.Modal.DeleteWithRelation', {
|
||||
modal: {
|
||||
type: 'dialog',
|
||||
},
|
||||
});
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'modal',
|
||||
alias: 'Umb.Modal.DeleteWithRelation',
|
||||
name: 'Delete With Relation Modal',
|
||||
element: () => import('./delete-with-relation-modal.element.js'),
|
||||
},
|
||||
];
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import type { ManifestEntityAction, MetaEntityActionDeleteKind } from '@umbraco-cms/backoffice/entity-action';
|
||||
|
||||
export interface ManifestEntityActionDeleteWithRelationKind
|
||||
extends ManifestEntityAction<MetaEntityActionDeleteWithRelationKind> {
|
||||
type: 'entityAction';
|
||||
kind: 'deleteWithRelation';
|
||||
}
|
||||
|
||||
export interface MetaEntityActionDeleteWithRelationKind extends MetaEntityActionDeleteKind {
|
||||
referenceRepositoryAlias: string;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface UmbExtensionManifestMap {
|
||||
umbManifestEntityActionDeleteWithRelationKind: ManifestEntityActionDeleteWithRelationKind;
|
||||
}
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
import type { UmbEntityReferenceRepository, UmbReferenceItemModel } from '../../reference/types.js';
|
||||
import {
|
||||
html,
|
||||
customElement,
|
||||
css,
|
||||
state,
|
||||
nothing,
|
||||
type PropertyValues,
|
||||
property,
|
||||
} from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import type { UmbItemRepository } from '@umbraco-cms/backoffice/repository';
|
||||
import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
|
||||
@customElement('umb-confirm-action-modal-entity-references')
|
||||
export class UmbConfirmActionModalEntityReferencesElement extends UmbLitElement {
|
||||
@property({ type: Object, attribute: false })
|
||||
config?: {
|
||||
itemRepositoryAlias: string;
|
||||
referenceRepositoryAlias: string;
|
||||
entityType: string;
|
||||
unique: string;
|
||||
};
|
||||
|
||||
@state()
|
||||
_referencedByItems: Array<UmbReferenceItemModel> = [];
|
||||
|
||||
@state()
|
||||
_totalReferencedByItems: number = 0;
|
||||
|
||||
@state()
|
||||
_totalDescendantsWithReferences: number = 0;
|
||||
|
||||
@state()
|
||||
_descendantsWithReferences: Array<any> = [];
|
||||
|
||||
#itemRepository?: UmbItemRepository<any>;
|
||||
#referenceRepository?: UmbEntityReferenceRepository;
|
||||
|
||||
#limitItems = 3;
|
||||
|
||||
protected override firstUpdated(_changedProperties: PropertyValues): void {
|
||||
super.firstUpdated(_changedProperties);
|
||||
this.#initData();
|
||||
}
|
||||
|
||||
async #initData() {
|
||||
if (!this.config) {
|
||||
this.#itemRepository?.destroy();
|
||||
this.#referenceRepository?.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.config?.referenceRepositoryAlias) {
|
||||
throw new Error('Missing referenceRepositoryAlias in config.');
|
||||
}
|
||||
|
||||
this.#referenceRepository = await createExtensionApiByAlias<UmbEntityReferenceRepository>(
|
||||
this,
|
||||
this.config?.referenceRepositoryAlias,
|
||||
);
|
||||
|
||||
if (!this.config?.itemRepositoryAlias) {
|
||||
throw new Error('Missing itemRepositoryAlias in config.');
|
||||
}
|
||||
|
||||
this.#itemRepository = await createExtensionApiByAlias<UmbItemRepository<any>>(
|
||||
this,
|
||||
this.config.itemRepositoryAlias,
|
||||
);
|
||||
|
||||
this.#loadReferencedBy();
|
||||
this.#loadDescendantsWithReferences();
|
||||
}
|
||||
|
||||
async #loadReferencedBy() {
|
||||
if (!this.#referenceRepository) {
|
||||
throw new Error('Failed to create reference repository.');
|
||||
}
|
||||
|
||||
if (!this.config?.unique) {
|
||||
throw new Error('Missing unique in data.');
|
||||
}
|
||||
|
||||
const { data } = await this.#referenceRepository.requestReferencedBy(this.config.unique, 0, this.#limitItems);
|
||||
|
||||
if (data) {
|
||||
this._referencedByItems = [...data.items];
|
||||
this._totalReferencedByItems = data.total;
|
||||
}
|
||||
}
|
||||
|
||||
async #loadDescendantsWithReferences() {
|
||||
if (!this.#referenceRepository) {
|
||||
throw new Error('Failed to create reference repository.');
|
||||
}
|
||||
|
||||
if (!this.#itemRepository) {
|
||||
throw new Error('Failed to create item repository.');
|
||||
}
|
||||
|
||||
// If the repository does not have the method, we don't need to load the referenced descendants.
|
||||
if (!this.#referenceRepository.requestDescendantsWithReferences) return;
|
||||
|
||||
if (!this.config?.unique) {
|
||||
throw new Error('Missing unique in data.');
|
||||
}
|
||||
|
||||
const { data } = await this.#referenceRepository.requestDescendantsWithReferences(
|
||||
this.config.unique,
|
||||
0,
|
||||
this.#limitItems,
|
||||
);
|
||||
|
||||
if (data) {
|
||||
this._totalDescendantsWithReferences = data.total;
|
||||
const uniques = data.items.map((item) => item.unique).filter((unique) => unique) as Array<string>;
|
||||
const { data: items } = await this.#itemRepository.requestItems(uniques);
|
||||
this._descendantsWithReferences = items ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
${this.#renderItems('references_labelDependsOnThis', this._referencedByItems, this._totalReferencedByItems)}
|
||||
${this.#renderItems(
|
||||
'references_labelDependentDescendants',
|
||||
this._descendantsWithReferences,
|
||||
this._totalDescendantsWithReferences,
|
||||
)}
|
||||
`;
|
||||
}
|
||||
|
||||
#renderItems(headline: string, items: Array<UmbReferenceItemModel>, total: number) {
|
||||
if (total === 0) return nothing;
|
||||
|
||||
return html`
|
||||
<h5 class="uui-h5" id="reference-headline">${this.localize.term(headline)}</h5>
|
||||
<uui-ref-list>
|
||||
${items.map(
|
||||
(item) =>
|
||||
html`<umb-entity-item-ref .item=${item} readonly ?standalone=${total === 1}></umb-entity-item-ref> `,
|
||||
)}
|
||||
</uui-ref-list>
|
||||
${total > this.#limitItems
|
||||
? html`<span>${this.localize.term('references_labelMoreReferences', total - this.#limitItems)}</span>`
|
||||
: nothing}
|
||||
`;
|
||||
}
|
||||
|
||||
static override styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
#reference-headline {
|
||||
margin-bottom: var(--uui-size-3);
|
||||
}
|
||||
|
||||
uui-ref-list {
|
||||
margin-bottom: var(--uui-size-2);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export { UmbConfirmActionModalEntityReferencesElement as element };
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-confirm-action-modal-entity-references': UmbConfirmActionModalEntityReferencesElement;
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export * from './modal/constants.js';
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export * from './trash-with-relation.action.js';
|
||||
export type * from './types.js';
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import { manifest as trashKindManifest } from './trash-with-relation.action.kind.js';
|
||||
import { manifests as modalManifests } from './modal/manifests.js';
|
||||
|
||||
import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest | UmbExtensionManifestKind> = [trashKindManifest, ...modalManifests];
|
||||
+1
@@ -0,0 +1 @@
|
||||
export * from './trash-with-relation-modal.token.js';
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'modal',
|
||||
alias: 'Umb.Modal.TrashWithRelation',
|
||||
name: 'Trash With Relation Modal',
|
||||
element: () => import('./trash-with-relation-modal.element.js'),
|
||||
},
|
||||
];
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
import type {
|
||||
UmbTrashWithRelationConfirmModalData,
|
||||
UmbTrashWithRelationConfirmModalValue,
|
||||
} from './trash-with-relation-modal.token.js';
|
||||
import {
|
||||
html,
|
||||
customElement,
|
||||
css,
|
||||
state,
|
||||
type PropertyValues,
|
||||
nothing,
|
||||
unsafeHTML,
|
||||
} from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
|
||||
import { umbFocus } from '@umbraco-cms/backoffice/lit-element';
|
||||
import type { UmbItemRepository } from '@umbraco-cms/backoffice/repository';
|
||||
import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
// import of local component
|
||||
import '../../local-components/confirm-action-entity-references.element.js';
|
||||
|
||||
@customElement('umb-trash-with-relation-confirm-modal')
|
||||
export class UmbTrashWithRelationConfirmModalElement extends UmbModalBaseElement<
|
||||
UmbTrashWithRelationConfirmModalData,
|
||||
UmbTrashWithRelationConfirmModalValue
|
||||
> {
|
||||
@state()
|
||||
_name?: string;
|
||||
|
||||
@state()
|
||||
_referencesConfig?: any;
|
||||
|
||||
#itemRepository?: UmbItemRepository<any>;
|
||||
|
||||
protected override firstUpdated(_changedProperties: PropertyValues): void {
|
||||
super.firstUpdated(_changedProperties);
|
||||
this.#initData();
|
||||
}
|
||||
|
||||
async #initData() {
|
||||
if (!this.data) {
|
||||
this.#itemRepository?.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
this.#itemRepository = await createExtensionApiByAlias<UmbItemRepository<any>>(this, this.data.itemRepositoryAlias);
|
||||
|
||||
const { data } = await this.#itemRepository.requestItems([this.data.unique]);
|
||||
const item = data?.[0];
|
||||
if (!item) throw new Error('Item not found.');
|
||||
|
||||
this._name = item.name;
|
||||
|
||||
this._referencesConfig = {
|
||||
unique: this.data.unique,
|
||||
itemRepositoryAlias: this.data.itemRepositoryAlias,
|
||||
referenceRepositoryAlias: this.data.referenceRepositoryAlias,
|
||||
};
|
||||
}
|
||||
|
||||
override render() {
|
||||
const headline = this.localize.string('#actions_trash');
|
||||
const content = this.localize.string('#defaultdialogs_confirmTrash', this._name);
|
||||
|
||||
return html`
|
||||
<uui-dialog-layout class="uui-text" headline=${headline}>
|
||||
<p>${unsafeHTML(content)}</p>
|
||||
|
||||
${this._referencesConfig
|
||||
? html`<umb-confirm-action-modal-entity-references
|
||||
.config=${this._referencesConfig}></umb-confirm-action-modal-entity-references>`
|
||||
: nothing}
|
||||
|
||||
<uui-button slot="actions" id="cancel" label="Cancel" @click=${this._rejectModal}></uui-button>
|
||||
|
||||
<uui-button
|
||||
slot="actions"
|
||||
id="confirm"
|
||||
color="danger"
|
||||
look="primary"
|
||||
label=${this.localize.term('actions_trash')}
|
||||
@click=${this._submitModal}
|
||||
${umbFocus()}></uui-button>
|
||||
</uui-dialog-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static override styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
uui-dialog-layout {
|
||||
max-inline-size: 60ch;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export { UmbTrashWithRelationConfirmModalElement as element };
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-trash-with-relation-confirm-modal': UmbTrashWithRelationConfirmModalElement;
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
export interface UmbTrashWithRelationConfirmModalData {
|
||||
unique: string;
|
||||
entityType: string;
|
||||
itemRepositoryAlias: string;
|
||||
referenceRepositoryAlias: string;
|
||||
}
|
||||
|
||||
export type UmbTrashWithRelationConfirmModalValue = undefined;
|
||||
|
||||
export const UMB_TRASH_WITH_RELATION_CONFIRM_MODAL = new UmbModalToken<
|
||||
UmbTrashWithRelationConfirmModalData,
|
||||
UmbTrashWithRelationConfirmModalValue
|
||||
>('Umb.Modal.TrashWithRelation', {
|
||||
modal: {
|
||||
type: 'dialog',
|
||||
},
|
||||
});
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { UMB_ENTITY_ACTION_TRASH_KIND_MANIFEST } from '@umbraco-cms/backoffice/recycle-bin';
|
||||
|
||||
export const manifest: UmbExtensionManifestKind = {
|
||||
type: 'kind',
|
||||
alias: 'Umb.Kind.EntityAction.TrashWithRelation',
|
||||
matchKind: 'trashWithRelation',
|
||||
matchType: 'entityAction',
|
||||
manifest: {
|
||||
...UMB_ENTITY_ACTION_TRASH_KIND_MANIFEST.manifest,
|
||||
type: 'entityAction',
|
||||
kind: 'trashWithRelation',
|
||||
api: () => import('./trash-with-relation.action.js'),
|
||||
},
|
||||
};
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import type { MetaEntityActionTrashWithRelationKind } from './types.js';
|
||||
import { UMB_TRASH_WITH_RELATION_CONFIRM_MODAL } from './modal/constants.js';
|
||||
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
|
||||
import { UmbTrashEntityAction } from '@umbraco-cms/backoffice/recycle-bin';
|
||||
|
||||
/**
|
||||
* Entity action for trashing an item with relations.
|
||||
* @class UmbTrashWithRelationEntityAction
|
||||
* @augments {UmbEntityActionBase<MetaEntityActionTrashWithRelationKind>}
|
||||
*/
|
||||
export class UmbTrashWithRelationEntityAction extends UmbTrashEntityAction<MetaEntityActionTrashWithRelationKind> {
|
||||
override async _confirmTrash(item: any) {
|
||||
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
|
||||
|
||||
const modal = modalManager.open(this, UMB_TRASH_WITH_RELATION_CONFIRM_MODAL, {
|
||||
data: {
|
||||
unique: item.unique,
|
||||
entityType: item.entityType,
|
||||
itemRepositoryAlias: this.args.meta.itemRepositoryAlias,
|
||||
referenceRepositoryAlias: this.args.meta.referenceRepositoryAlias,
|
||||
},
|
||||
});
|
||||
|
||||
await modal.onSubmit();
|
||||
}
|
||||
}
|
||||
|
||||
export { UmbTrashWithRelationEntityAction as api };
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import type { ManifestEntityAction } from '@umbraco-cms/backoffice/entity-action';
|
||||
import type { MetaEntityActionTrashKind } from '@umbraco-cms/backoffice/recycle-bin';
|
||||
|
||||
export interface ManifestEntityActionTrashWithRelationKind
|
||||
extends ManifestEntityAction<MetaEntityActionTrashWithRelationKind> {
|
||||
type: 'entityAction';
|
||||
kind: 'trashWithRelation';
|
||||
}
|
||||
|
||||
export interface MetaEntityActionTrashWithRelationKind extends MetaEntityActionTrashKind {
|
||||
referenceRepositoryAlias: string;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface UmbExtensionManifestMap {
|
||||
umbManifestEntityActionTrashWithRelationKind: ManifestEntityActionTrashWithRelationKind;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,10 @@
|
||||
import { manifests as collectionManifests } from './collection/manifests.js';
|
||||
import { manifests as deleteManifests } from './entity-actions/delete/manifests.js';
|
||||
import { manifests as trashManifests } from './entity-actions/trash/manifests.js';
|
||||
import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest> = [...collectionManifests];
|
||||
export const manifests: Array<UmbExtensionManifest | UmbExtensionManifestKind> = [
|
||||
...collectionManifests,
|
||||
...deleteManifests,
|
||||
...trashManifests,
|
||||
];
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
|
||||
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
import type {
|
||||
DefaultReferenceResponseModel,
|
||||
DocumentReferenceResponseModel,
|
||||
MediaReferenceResponseModel,
|
||||
} from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type { UmbDataSourceResponse, UmbPagedModel, UmbRepositoryResponse } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
export interface UmbReferenceItemModel extends UmbEntityModel {}
|
||||
|
||||
export type UmbReferenceModel =
|
||||
| DefaultReferenceResponseModel
|
||||
| DocumentReferenceResponseModel
|
||||
| MediaReferenceResponseModel;
|
||||
|
||||
export interface UmbEntityReferenceRepository extends UmbApi {
|
||||
requestReferencedBy(
|
||||
unique: string,
|
||||
skip?: number,
|
||||
take?: number,
|
||||
): Promise<UmbRepositoryResponse<UmbPagedModel<UmbReferenceItemModel>>>;
|
||||
requestDescendantsWithReferences?(
|
||||
unique: string,
|
||||
skip?: number,
|
||||
take?: number,
|
||||
): Promise<UmbRepositoryResponse<UmbPagedModel<UmbEntityModel>>>;
|
||||
}
|
||||
|
||||
export interface UmbEntityReferenceDataSource {
|
||||
getReferencedBy(
|
||||
unique: string,
|
||||
skip?: number,
|
||||
take?: number,
|
||||
): Promise<UmbDataSourceResponse<UmbPagedModel<UmbReferenceItemModel>>>;
|
||||
getReferencedDescendants?(
|
||||
unique: string,
|
||||
skip?: number,
|
||||
take?: number,
|
||||
): Promise<UmbDataSourceResponse<UmbPagedModel<UmbEntityModel>>>;
|
||||
}
|
||||
@@ -1,10 +1,5 @@
|
||||
import type { UmbRelationEntityType } from './entity.js';
|
||||
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
|
||||
import type {
|
||||
DefaultReferenceResponseModel,
|
||||
DocumentReferenceResponseModel,
|
||||
MediaReferenceResponseModel,
|
||||
} from '@umbraco-cms/backoffice/external/backend-api';
|
||||
export type * from './reference/types.js';
|
||||
|
||||
export interface UmbRelationDetailModel {
|
||||
unique: string;
|
||||
@@ -23,11 +18,3 @@ export interface UmbRelationDetailModel {
|
||||
createDate: string;
|
||||
comment: string | null;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
export interface UmbReferenceItemModel extends UmbEntityModel {}
|
||||
|
||||
export type UmbReferenceModel =
|
||||
| DefaultReferenceResponseModel
|
||||
| DocumentReferenceResponseModel
|
||||
| MediaReferenceResponseModel;
|
||||
|
||||
Reference in New Issue
Block a user