V15: Document Type Create Options (#17669)
* Refactors `umb-ref-item` to inherit from `uui-ref-node` To extend, rather than reinvent the wheel. * Updates components using `umb-ref-item` with `select-only` attribute * Updates `umb-entity-create-option-action-list-modal` to use `umb-ref-item` instead of `uui-ref-node`, so we can use `umb-icon` (with color support) and UI consistency. * Adds `headline` property for Create Option modal * Changes 'Umb.EntityAction.DocumentType.Create' to use `kind: 'create'` Deprecates `umb-document-type-create-options-modal` and token. * Adds `entityCreateOptionAction` extensions for Document Types - Document Type (default) - Document Type with Template - Element Type - Folder * Tweaks Create Options modal to submit upon selection * corrections * remove headline option --------- Co-authored-by: Niels Lyngsø <nsl@umbraco.dk> Co-authored-by: Niels Lyngsø <niels.lyngso@gmail.com> Co-authored-by: Mads Rasmussen <madsr@hey.com>
This commit is contained in:
@@ -1,66 +1,29 @@
|
||||
import { html, customElement, css, property, when } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { customElement, css, property, type PropertyValues } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UUIRefElement, UUIRefEvent, UUIRefNodeElement } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UUIRefNodeElement } from '@umbraco-cms/backoffice/external/uui';
|
||||
|
||||
@customElement('umb-ref-item')
|
||||
export class UmbRefItemElement extends UmbElementMixin(UUIRefElement) {
|
||||
@property({ type: String })
|
||||
name = '';
|
||||
|
||||
@property({ type: String })
|
||||
detail = '';
|
||||
|
||||
export class UmbRefItemElement extends UmbElementMixin(UUIRefNodeElement) {
|
||||
@property({ type: String })
|
||||
icon = '';
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
#iconElement = document.createElement('umb-icon');
|
||||
|
||||
this.selectable = true;
|
||||
protected override firstUpdated(_changedProperties: PropertyValues): void {
|
||||
super.firstUpdated(_changedProperties);
|
||||
|
||||
this.addEventListener(UUIRefEvent.OPEN, () => this.dispatchEvent(new Event('click')));
|
||||
}
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
<button
|
||||
type="button"
|
||||
id="btn-item"
|
||||
tabindex="0"
|
||||
@click=${this.handleOpenClick}
|
||||
@keydown=${this.handleOpenKeydown}
|
||||
?disabled=${this.disabled}>
|
||||
${when(this.icon, () => html`<span id="icon"><umb-icon name=${this.icon ?? ''}></umb-icon></span>`)}
|
||||
<div id="info">
|
||||
<div id="name">${this.name}</div>
|
||||
<small id="detail">${this.detail}</small>
|
||||
</div>
|
||||
</button>
|
||||
<div id="select-border"></div>
|
||||
<slot></slot>
|
||||
`;
|
||||
// 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 = [
|
||||
...UUIRefElement.styles,
|
||||
...UUIRefNodeElement.styles,
|
||||
UmbTextStyles,
|
||||
css`
|
||||
:host {
|
||||
padding: calc(var(--uui-size-4) + 1px);
|
||||
}
|
||||
|
||||
#btn-item {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
align-self: stretch;
|
||||
line-height: normal;
|
||||
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
padding-top: var(--uui-size-3);
|
||||
padding-bottom: var(--uui-size-3);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@@ -18,8 +18,7 @@ import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
type ManifestType = ManifestEntityCreateOptionAction;
|
||||
|
||||
const elementName = 'umb-entity-create-option-action-list-modal';
|
||||
@customElement(elementName)
|
||||
@customElement('umb-entity-create-option-action-list-modal')
|
||||
export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseElement<
|
||||
UmbEntityCreateOptionActionListModalData,
|
||||
UmbEntityCreateOptionActionListModalValue
|
||||
@@ -71,6 +70,8 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle
|
||||
|
||||
if (!controller.api) throw new Error('No API found');
|
||||
await controller.api.execute();
|
||||
|
||||
this._submitModal();
|
||||
}
|
||||
|
||||
#getTarget(href?: string) {
|
||||
@@ -83,17 +84,19 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
<umb-body-layout headline="${this.localize.term('user_createUser')}">
|
||||
<umb-body-layout headline="${this.localize.term('general_create')}">
|
||||
<uui-box>
|
||||
${this._apiControllers.length === 0
|
||||
? html`<div>No create options available.</div>`
|
||||
: html`<uui-ref-list>
|
||||
${repeat(
|
||||
this._apiControllers,
|
||||
(controller) => controller.manifest?.alias,
|
||||
(controller, index) => this.#renderRefItem(controller, index),
|
||||
)}
|
||||
</uui-ref-list>`}
|
||||
: html`
|
||||
<uui-ref-list>
|
||||
${repeat(
|
||||
this._apiControllers,
|
||||
(controller) => controller.manifest?.alias,
|
||||
(controller, index) => this.#renderRefItem(controller, index),
|
||||
)}
|
||||
</uui-ref-list>
|
||||
`}
|
||||
</uui-box>
|
||||
<uui-button
|
||||
slot="actions"
|
||||
@@ -108,19 +111,18 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle
|
||||
if (!manifest) throw new Error('No manifest found');
|
||||
|
||||
const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.name;
|
||||
const description = manifest.meta.description ? this.localize.string(manifest.meta.description) : undefined;
|
||||
const href = this._hrefList[index];
|
||||
|
||||
return html`
|
||||
<uui-ref-node
|
||||
<umb-ref-item
|
||||
name=${label}
|
||||
detail=${ifDefined(manifest.meta.description)}
|
||||
@click=${(event: Event) => this.#onClick(event, controller, href)}
|
||||
detail=${ifDefined(description)}
|
||||
icon=${manifest.meta.icon}
|
||||
href=${ifDefined(href)}
|
||||
target=${this.#getTarget(href)}
|
||||
?selectable=${!href}
|
||||
?readonly=${!href}>
|
||||
<uui-icon slot="icon" name=${manifest.meta.icon}></uui-icon>
|
||||
</uui-ref-node>
|
||||
@open=${(event: Event) => this.#onClick(event, controller, href)}>
|
||||
</umb-ref-item>
|
||||
`;
|
||||
}
|
||||
}
|
||||
@@ -129,6 +131,6 @@ export { UmbEntityCreateOptionActionListModalElement as element };
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
[elementName]: UmbEntityCreateOptionActionListModalElement;
|
||||
'umb-entity-create-option-action-list-modal': UmbEntityCreateOptionActionListModalElement;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ export class UmbItemPickerModalElement extends UmbModalBaseElement<UmbItemPicker
|
||||
name=${this.localize.string(item.label)}
|
||||
detail=${ifDefined(item.description)}
|
||||
icon=${ifDefined(item.icon)}
|
||||
@click=${() => this.#submit(item)}>
|
||||
@open=${() => this.#submit(item)}>
|
||||
</umb-ref-item>
|
||||
`,
|
||||
)}
|
||||
|
||||
@@ -53,6 +53,7 @@ export class UmbDefaultPickerSearchResultItemElement extends UmbLitElement {
|
||||
name=${item.name}
|
||||
id=${item.unique}
|
||||
icon=${item.icon ?? 'icon-document'}
|
||||
select-only
|
||||
selectable
|
||||
@selected=${() => this.#pickerContext?.selection.select(item.unique)}
|
||||
@deselected=${() => this.#pickerContext?.selection.deselect(item.unique)}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN } from '../../../paths.js';
|
||||
import type { UmbDocumentTypeEntityTypeUnion } from '../../../entity.js';
|
||||
import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-create-option-action';
|
||||
import type { MetaEntityCreateOptionAction } from '@umbraco-cms/backoffice/entity-create-option-action';
|
||||
|
||||
export class UmbDefaultDocumentTypeCreateOptionAction extends UmbEntityCreateOptionActionBase<MetaEntityCreateOptionAction> {
|
||||
override async getHref() {
|
||||
const parentEntityType = this.args.entityType as UmbDocumentTypeEntityTypeUnion;
|
||||
if (!parentEntityType) throw new Error('Entity type is required to create a document type');
|
||||
|
||||
const parentUnique = this.args.unique ?? null;
|
||||
|
||||
return UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN.generateAbsolute({
|
||||
parentEntityType,
|
||||
parentUnique,
|
||||
presetAlias: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { UmbDefaultDocumentTypeCreateOptionAction as api };
|
||||
@@ -0,0 +1,24 @@
|
||||
import {
|
||||
UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN,
|
||||
UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_ELEMENT,
|
||||
} from '../../../paths.js';
|
||||
import type { UmbDocumentTypeEntityTypeUnion } from '../../../entity.js';
|
||||
import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-create-option-action';
|
||||
import type { MetaEntityCreateOptionAction } from '@umbraco-cms/backoffice/entity-create-option-action';
|
||||
|
||||
export class UmbElementTypeCreateOptionAction extends UmbEntityCreateOptionActionBase<MetaEntityCreateOptionAction> {
|
||||
override async getHref() {
|
||||
const parentEntityType = this.args.entityType as UmbDocumentTypeEntityTypeUnion;
|
||||
if (!parentEntityType) throw new Error('Entity type is required to create a document type');
|
||||
|
||||
const parentUnique = this.args.unique ?? null;
|
||||
|
||||
return UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN.generateAbsolute({
|
||||
parentEntityType,
|
||||
parentUnique,
|
||||
presetAlias: UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_ELEMENT,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { UmbElementTypeCreateOptionAction as api };
|
||||
@@ -0,0 +1,12 @@
|
||||
import { UMB_DOCUMENT_TYPE_FOLDER_REPOSITORY_ALIAS } from '../../../tree/folder/repository/constants.js';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbCreateFolderEntityAction, type MetaEntityActionFolderKind } from '@umbraco-cms/backoffice/tree';
|
||||
import type { UmbEntityActionArgs } from '@umbraco-cms/backoffice/entity-action';
|
||||
|
||||
export class UmbDocumentTypeFolderCreateOptionAction extends UmbCreateFolderEntityAction {
|
||||
constructor(host: UmbControllerHost, args: UmbEntityActionArgs<MetaEntityActionFolderKind>) {
|
||||
super(host, { ...args, meta: { ...args.meta, folderRepositoryAlias: UMB_DOCUMENT_TYPE_FOLDER_REPOSITORY_ALIAS } });
|
||||
}
|
||||
}
|
||||
|
||||
export { UmbDocumentTypeFolderCreateOptionAction as api };
|
||||
@@ -1,25 +1,83 @@
|
||||
import { UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE } from '../../entity.js';
|
||||
import { UMB_DOCUMENT_TYPE_ENTITY_TYPE, UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE } from '../../entity.js';
|
||||
import { UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE } from '../../tree/index.js';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'entityAction',
|
||||
kind: 'default',
|
||||
kind: 'create',
|
||||
alias: 'Umb.EntityAction.DocumentType.Create',
|
||||
name: 'Create Document Type Entity Action',
|
||||
weight: 1200,
|
||||
api: () => import('./create.action.js'),
|
||||
forEntityTypes: [UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE, UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE],
|
||||
meta: {
|
||||
icon: 'icon-add',
|
||||
label: '#actions_create',
|
||||
additionalOptions: true,
|
||||
headline: '#create_createUnder #treeHeaders_documentTypes',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'modal',
|
||||
alias: 'Umb.Modal.DocumentTypeCreateOptions',
|
||||
name: 'Document Type Create Options Modal',
|
||||
element: () => import('./modal/document-type-create-options-modal.element.js'),
|
||||
type: 'entityCreateOptionAction',
|
||||
alias: 'Umb.EntityCreateOptionAction.DocumentType.Default',
|
||||
name: 'Default Document Type Entity Create Option Action',
|
||||
weight: 100,
|
||||
api: () => import('./default/default-document-type-create-option-action.js'),
|
||||
forEntityTypes: [
|
||||
UMB_DOCUMENT_TYPE_ENTITY_TYPE,
|
||||
UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE,
|
||||
UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE,
|
||||
],
|
||||
meta: {
|
||||
icon: 'icon-document',
|
||||
label: '#create_documentType',
|
||||
description: '#create_documentTypeDescription',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'entityCreateOptionAction',
|
||||
alias: 'Umb.EntityCreateOptionAction.DocumentType.DocumentWithTemplate',
|
||||
name: 'Document Type with Template Document Type Entity Create Option Action',
|
||||
weight: 90,
|
||||
api: () => import('./template/document-type-with-template-create-option-action.js'),
|
||||
forEntityTypes: [
|
||||
UMB_DOCUMENT_TYPE_ENTITY_TYPE,
|
||||
UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE,
|
||||
UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE,
|
||||
],
|
||||
meta: {
|
||||
icon: 'icon-document-html',
|
||||
label: '#create_documentTypeWithTemplate',
|
||||
description: '#create_documentTypeWithTemplateDescription',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'entityCreateOptionAction',
|
||||
alias: 'Umb.EntityCreateOptionAction.DocumentType.ElementType',
|
||||
name: 'Element Type Document Type Entity Create Option Action',
|
||||
weight: 80,
|
||||
api: () => import('./element/element-type-create-option-action.js'),
|
||||
forEntityTypes: [
|
||||
UMB_DOCUMENT_TYPE_ENTITY_TYPE,
|
||||
UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE,
|
||||
UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE,
|
||||
],
|
||||
meta: {
|
||||
icon: 'icon-plugin',
|
||||
label: '#create_elementType',
|
||||
description: '#create_elementTypeDescription',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'entityCreateOptionAction',
|
||||
alias: 'Umb.EntityCreateOptionAction.DocumentType.Folder',
|
||||
name: 'Folder Document Type Entity Create Option Action',
|
||||
weight: 70,
|
||||
api: () => import('./folder/document-type-folder-create-option-action.js'),
|
||||
forEntityTypes: [UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE, UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE],
|
||||
meta: {
|
||||
icon: 'icon-folder',
|
||||
label: '#create_folder',
|
||||
description: '#create_folderDescription',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
|
||||
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
/** @deprecated No longer used internally. This will be removed in Umbraco 17. [LK] */
|
||||
export interface UmbDocumentTypeCreateOptionsModalData {
|
||||
parent: UmbEntityModel;
|
||||
}
|
||||
|
||||
/** @deprecated No longer used internally. This will be removed in Umbraco 17. [LK] */
|
||||
export const UMB_DOCUMENT_TYPE_CREATE_OPTIONS_MODAL = new UmbModalToken<UmbDocumentTypeCreateOptionsModalData>(
|
||||
'Umb.Modal.DocumentTypeCreateOptions',
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ import { UmbCreateFolderEntityAction } from '@umbraco-cms/backoffice/tree';
|
||||
// Include the types from the DocumentTypeWorkspacePresetType + folder.
|
||||
type OptionsPresetType = UmbCreateDocumentTypeWorkspacePresetType | 'folder' | null;
|
||||
|
||||
/** @deprecated No longer used internally. This will be removed in Umbraco 17. [LK] */
|
||||
@customElement('umb-document-type-create-options-modal')
|
||||
export class UmbDataTypeCreateOptionsModalElement extends UmbModalBaseElement<UmbDocumentTypeCreateOptionsModalData> {
|
||||
#createFolderAction?: UmbCreateFolderEntityAction;
|
||||
@@ -110,7 +111,7 @@ export class UmbDataTypeCreateOptionsModalElement extends UmbModalBaseElement<Um
|
||||
name=${item.label}
|
||||
detail=${item.description}
|
||||
icon=${item.icon}
|
||||
@click=${() => this.#onClick(item.preset)}></umb-ref-item>
|
||||
@open=${() => this.#onClick(item.preset)}></umb-ref-item>
|
||||
`,
|
||||
)}
|
||||
</uui-ref-list>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import {
|
||||
UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN,
|
||||
UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_TEMPLATE,
|
||||
} from '../../../paths.js';
|
||||
import type { UmbDocumentTypeEntityTypeUnion } from '../../../entity.js';
|
||||
import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-create-option-action';
|
||||
import type { MetaEntityCreateOptionAction } from '@umbraco-cms/backoffice/entity-create-option-action';
|
||||
|
||||
export class UmbDocumentTypeWithTemplateCreateOptionAction extends UmbEntityCreateOptionActionBase<MetaEntityCreateOptionAction> {
|
||||
override async getHref() {
|
||||
const parentEntityType = this.args.entityType as UmbDocumentTypeEntityTypeUnion;
|
||||
if (!parentEntityType) throw new Error('Entity type is required to create a document type');
|
||||
|
||||
const parentUnique = this.args.unique ?? null;
|
||||
|
||||
return UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN.generateAbsolute({
|
||||
parentEntityType,
|
||||
parentUnique,
|
||||
presetAlias: UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_TEMPLATE,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { UmbDocumentTypeWithTemplateCreateOptionAction as api };
|
||||
@@ -76,7 +76,7 @@ export class UmbDynamicRootOriginPickerModalModalElement extends UmbModalBaseEle
|
||||
name=${ifDefined(item.meta.label)}
|
||||
detail=${ifDefined(item.meta.description)}
|
||||
icon=${ifDefined(item.meta.icon)}
|
||||
@click=${() => this.#choose(item)}></umb-ref-item>
|
||||
@open=${() => this.#choose(item)}></umb-ref-item>
|
||||
`,
|
||||
)}
|
||||
</uui-ref-list>
|
||||
|
||||
@@ -63,7 +63,7 @@ export class UmbDynamicRootQueryStepPickerModalModalElement extends UmbModalBase
|
||||
name=${ifDefined(item.meta.label)}
|
||||
detail=${ifDefined(item.meta.description)}
|
||||
icon=${ifDefined(item.meta.icon)}
|
||||
@click=${() => this.#choose(item)}></umb-ref-item>
|
||||
@open=${() => this.#choose(item)}></umb-ref-item>
|
||||
`,
|
||||
)}
|
||||
</uui-ref-list>
|
||||
|
||||
Reference in New Issue
Block a user