Merge branch 'main' into bugfix/workspace-create-routes
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type';
|
||||
import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type';
|
||||
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||
import {
|
||||
css,
|
||||
html,
|
||||
customElement,
|
||||
property,
|
||||
state,
|
||||
repeat,
|
||||
ifDefined,
|
||||
nothing,
|
||||
query,
|
||||
} from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UUIComboboxEvent, UUIComboboxElement } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UmbMediaTypeDetailRepository } from '@umbraco-cms/backoffice/media-type';
|
||||
import {
|
||||
UMB_DOCUMENT_TYPE_PICKER_MODAL,
|
||||
UMB_MEDIA_TYPE_PICKER_MODAL,
|
||||
UMB_MODAL_MANAGER_CONTEXT,
|
||||
type UmbModalManagerContext,
|
||||
} from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
interface FieldPickerValue {
|
||||
alias: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
enum FieldType {
|
||||
MEDIA_TYPE = 'media-type',
|
||||
DOCUMENT_TYPE = 'document-type',
|
||||
SYSTEM = 'system',
|
||||
}
|
||||
|
||||
@customElement('umb-field-dropdown-list')
|
||||
export class UmbFieldDropdownListElement extends UmbLitElement {
|
||||
@property({ type: Boolean, attribute: 'exclude-media-type', reflect: true })
|
||||
public excludeMediaType = false;
|
||||
|
||||
private _value: FieldPickerValue | undefined;
|
||||
@property({ type: Object })
|
||||
public get value(): FieldPickerValue | undefined {
|
||||
return this._value;
|
||||
}
|
||||
public set value(val: FieldPickerValue | undefined) {
|
||||
const oldVal = this._value;
|
||||
this._value = val;
|
||||
this.requestUpdate('value', oldVal);
|
||||
this.dispatchEvent(new UmbChangeEvent());
|
||||
}
|
||||
|
||||
@state()
|
||||
private _type?: FieldType;
|
||||
|
||||
@state()
|
||||
private _uniqueName?: string;
|
||||
|
||||
@state()
|
||||
private _unique?: string;
|
||||
|
||||
@query('#value')
|
||||
private _valueElement?: UUIComboboxElement;
|
||||
|
||||
#documentTypeDetailRepository = new UmbDocumentTypeDetailRepository(this);
|
||||
#mediaTypeDetailRepository = new UmbMediaTypeDetailRepository(this);
|
||||
#modalManager?: UmbModalManagerContext;
|
||||
|
||||
@state()
|
||||
private _customFields: Array<Partial<UmbPropertyTypeModel>> = [];
|
||||
|
||||
private _systemFields: Array<Partial<UmbPropertyTypeModel>> = [
|
||||
{ alias: 'sortOrder', name: this.localize.term('general_sort') },
|
||||
{ alias: 'updateDate', name: this.localize.term('content_updateDate') },
|
||||
{ alias: 'updater', name: this.localize.term('content_updatedBy') },
|
||||
{ alias: 'createDate', name: this.localize.term('content_createDate') },
|
||||
{ alias: 'owner', name: this.localize.term('content_createBy') },
|
||||
{ alias: 'published', name: this.localize.term('content_isPublished') },
|
||||
{ alias: 'contentTypeAlias', name: this.localize.term('content_documentType') },
|
||||
];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => {
|
||||
this.#modalManager = modalManager;
|
||||
});
|
||||
}
|
||||
|
||||
async #getDocumentTypeFields() {
|
||||
if (!this.#modalManager) return;
|
||||
const modalContext = this.#modalManager.open(UMB_DOCUMENT_TYPE_PICKER_MODAL, {
|
||||
data: {
|
||||
hideTreeRoot: true,
|
||||
multiple: false,
|
||||
},
|
||||
});
|
||||
|
||||
const modalValue = await modalContext.onSubmit();
|
||||
const unique = modalValue.selection[0] ?? '';
|
||||
|
||||
const { data } = await this.#documentTypeDetailRepository.requestByUnique(unique);
|
||||
if (!data) return;
|
||||
|
||||
this._unique = data.unique;
|
||||
this._uniqueName = data.name;
|
||||
this._customFields = data.properties;
|
||||
}
|
||||
|
||||
async #getMediaTypeFields() {
|
||||
if (!this.#modalManager) return;
|
||||
const modalContext = this.#modalManager.open(UMB_MEDIA_TYPE_PICKER_MODAL, {
|
||||
data: {
|
||||
hideTreeRoot: true,
|
||||
multiple: false,
|
||||
},
|
||||
});
|
||||
|
||||
const modalValue = await modalContext.onSubmit();
|
||||
const unique = modalValue.selection[0] ?? '';
|
||||
|
||||
const { data } = await this.#mediaTypeDetailRepository.requestByUnique(unique);
|
||||
if (!data) return;
|
||||
|
||||
this._unique = data.unique;
|
||||
this._uniqueName = data.name;
|
||||
this._customFields = data.properties;
|
||||
}
|
||||
|
||||
#onChange(e: UUIComboboxEvent) {
|
||||
this._type = (e.composedPath()[0] as UUIComboboxElement).value as FieldType;
|
||||
this.value = undefined;
|
||||
if (this._valueElement) this._valueElement.value = '';
|
||||
|
||||
switch (this._type) {
|
||||
case FieldType.DOCUMENT_TYPE:
|
||||
this.#getDocumentTypeFields();
|
||||
break;
|
||||
case FieldType.MEDIA_TYPE:
|
||||
this.#getMediaTypeFields();
|
||||
break;
|
||||
default:
|
||||
this._uniqueName = '';
|
||||
this._unique = '';
|
||||
this._customFields = this._systemFields;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#onChangeValue(e: UUIComboboxEvent) {
|
||||
e.stopPropagation();
|
||||
const alias = (e.composedPath()[0] as UUIComboboxElement).value as FieldType;
|
||||
this.value = this._customFields.find((field) => field.alias === alias) as FieldPickerValue;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<uui-combobox id="preview">
|
||||
<uui-combobox-list @change=${this.#onChange}>
|
||||
<uui-combobox-list-option value="system">
|
||||
<strong>${this.localize.term('formSettings_systemFields')}</strong>
|
||||
</uui-combobox-list-option>
|
||||
<uui-combobox-list-option value="document-type" display-value=${this.localize.term('content_documentType')}>
|
||||
<strong> ${this.localize.term('content_documentType')} </strong>
|
||||
${this.localize.term('defaultdialogs_treepicker')}
|
||||
</uui-combobox-list-option>
|
||||
${!this.excludeMediaType
|
||||
? html`<uui-combobox-list-option
|
||||
value="media-type"
|
||||
display-value=${this.localize.term('content_mediatype')}>
|
||||
<strong> ${this.localize.term('content_mediatype')} </strong>
|
||||
${this.localize.term('defaultdialogs_treepicker')}
|
||||
</uui-combobox-list-option>`
|
||||
: nothing}
|
||||
</uui-combobox-list>
|
||||
</uui-combobox>
|
||||
${this.#renderAliasDropdown()}
|
||||
`;
|
||||
}
|
||||
|
||||
#renderAliasDropdown() {
|
||||
if (this._type !== FieldType.SYSTEM && !this._unique) return;
|
||||
return html`<strong>${this._uniqueName}</strong>
|
||||
<uui-combobox id="value" value=${ifDefined(this.value?.alias)}>
|
||||
<uui-combobox-list @change=${this.#onChangeValue}>
|
||||
${repeat(
|
||||
this._customFields,
|
||||
(field) => field.alias,
|
||||
(field) =>
|
||||
html`<uui-combobox-list-option value=${ifDefined(field.alias)}>${field.alias}</uui-combobox-list-option>`,
|
||||
)}
|
||||
</uui-combobox-list>
|
||||
</uui-combobox>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
css`
|
||||
uui-combobox {
|
||||
width: 100%;
|
||||
}
|
||||
strong {
|
||||
display: block;
|
||||
}
|
||||
uui-combobox-list-option {
|
||||
padding: calc(var(--uui-size-2, 6px) + 1px);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export default UmbFieldDropdownListElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-field-dropdown-list': UmbFieldDropdownListElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { Meta, StoryObj } from '@storybook/web-components';
|
||||
import './field-dropdown-list.element.js';
|
||||
import type { UmbFieldDropdownListElement } from './field-dropdown-list.element.js';
|
||||
|
||||
const meta: Meta<UmbFieldDropdownListElement> = {
|
||||
title: 'Components/Inputs/Field Dropdown List',
|
||||
component: 'umb-field-dropdown-list',
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<UmbFieldDropdownListElement>;
|
||||
|
||||
export const Overview: Story = {
|
||||
args: {
|
||||
excludeMediaType: false,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import { expect, fixture, html } from '@open-wc/testing';
|
||||
import { UmbFieldDropdownListElement } from './field-dropdown-list.element.js';
|
||||
import { type UmbTestRunnerWindow, defaultA11yConfig } from '@umbraco-cms/internal/test-utils';
|
||||
describe('UmbInputDateElement', () => {
|
||||
let element: UmbFieldDropdownListElement;
|
||||
|
||||
beforeEach(async () => {
|
||||
element = await fixture(html` <umb-field-dropdown-list></umb-field-dropdown-list> `);
|
||||
});
|
||||
|
||||
it('is defined with its own instance', () => {
|
||||
expect(element).to.be.instanceOf(UmbFieldDropdownListElement);
|
||||
});
|
||||
|
||||
if ((window as UmbTestRunnerWindow).__UMBRACO_TEST_RUN_A11Y_TEST) {
|
||||
it('passes the a11y audit', async () => {
|
||||
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
export * from './field-dropdown-list.element.js';
|
||||
@@ -7,6 +7,7 @@ export * from './code-block/index.js';
|
||||
export * from './dropdown/index.js';
|
||||
export * from './entity-actions-bundle/index.js';
|
||||
export * from './extension-slot/index.js';
|
||||
export * from './field-dropdown-list/index.js';
|
||||
export * from './footer-layout/index.js';
|
||||
export * from './header-app/index.js';
|
||||
export * from './history/index.js';
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { umbPickDocumentVariantModal } from '../modals/pick-document-variant-modal.controller.js';
|
||||
import { type UmbDocumentDetailRepository, UmbDocumentPublishingRepository } from '../repository/index.js';
|
||||
import { UmbDocumentDetailRepository, UmbDocumentPublishingRepository } from '../repository/index.js';
|
||||
import { UmbDocumentVariantState } from '../types.js';
|
||||
import { UmbLanguageCollectionRepository } from '@umbraco-cms/backoffice/language';
|
||||
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
||||
|
||||
export class UmbPublishDocumentEntityAction extends UmbEntityActionBase<UmbDocumentDetailRepository> {
|
||||
export class UmbPublishDocumentEntityAction extends UmbEntityActionBase<unknown> {
|
||||
async execute() {
|
||||
if (!this.repository) throw new Error('Document repository not set');
|
||||
|
||||
const languageRepository = new UmbLanguageCollectionRepository(this._host);
|
||||
const { data: languageData } = await languageRepository.requestCollection({});
|
||||
const { data: documentData } = await this.repository.requestByUnique(this.unique);
|
||||
|
||||
const documentRepository = new UmbDocumentDetailRepository(this._host);
|
||||
const { data: documentData } = await documentRepository.requestByUnique(this.unique);
|
||||
|
||||
if (!documentData) throw new Error('The document was not found');
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { umbPickDocumentVariantModal } from '../modals/pick-document-variant-modal.controller.js';
|
||||
import { type UmbDocumentDetailRepository, UmbDocumentPublishingRepository } from '../repository/index.js';
|
||||
import { UmbDocumentDetailRepository, UmbDocumentPublishingRepository } from '../repository/index.js';
|
||||
import { UmbDocumentVariantState } from '../types.js';
|
||||
import { UmbLanguageCollectionRepository } from '@umbraco-cms/backoffice/language';
|
||||
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
||||
|
||||
export class UmbUnpublishDocumentEntityAction extends UmbEntityActionBase<UmbDocumentDetailRepository> {
|
||||
export class UmbUnpublishDocumentEntityAction extends UmbEntityActionBase<unknown> {
|
||||
async execute() {
|
||||
if (!this.repository) throw new Error('Document repository not set');
|
||||
|
||||
const languageRepository = new UmbLanguageCollectionRepository(this._host);
|
||||
const { data: languageData } = await languageRepository.requestCollection({});
|
||||
const { data: documentData } = await this.repository.requestByUnique(this.unique);
|
||||
|
||||
const documentRepository = new UmbDocumentDetailRepository(this._host);
|
||||
const { data: documentData } = await documentRepository.requestByUnique(this.unique);
|
||||
|
||||
if (!documentData) throw new Error('The document was not found');
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UmbCollectionBulkActionPermissions } from '../../../core/collection/types.js';
|
||||
import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS } from '../repository/index.js';
|
||||
import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, UMB_DOCUMENT_PUBLISHING_REPOSITORY_ALIAS } from '../repository/index.js';
|
||||
import { UMB_DOCUMENT_COLLECTION_ALIAS } from '../collection/index.js';
|
||||
import { UmbDocumentCopyEntityBulkAction } from './copy/copy.action.js';
|
||||
import { UmbDocumentDeleteEntityBulkAction } from './delete/delete.action.js';
|
||||
@@ -21,7 +21,7 @@ export const manifests: Array<ManifestEntityBulkAction> = [
|
||||
api: UmbDocumentPublishEntityBulkAction,
|
||||
meta: {
|
||||
label: 'Publish',
|
||||
repositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
|
||||
repositoryAlias: UMB_DOCUMENT_PUBLISHING_REPOSITORY_ALIAS,
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
@@ -42,7 +42,7 @@ export const manifests: Array<ManifestEntityBulkAction> = [
|
||||
api: UmbDocumentUnpublishEntityBulkAction,
|
||||
meta: {
|
||||
label: 'Unpublish',
|
||||
repositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS,
|
||||
repositoryAlias: UMB_DOCUMENT_PUBLISHING_REPOSITORY_ALIAS,
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
|
||||
@@ -1,14 +1,36 @@
|
||||
import type { UmbDocumentDetailRepository } from '../../repository/index.js';
|
||||
import type { UmbDocumentPublishingRepository } from '../../repository/index.js';
|
||||
import { UmbPublishDocumentEntityAction } from '../../entity-actions/publish.action.js';
|
||||
import type { UmbDocumentVariantOptionModel } from '../../types.js';
|
||||
import { umbPickDocumentVariantModal } from '../../modals/index.js';
|
||||
import { UmbEntityBulkActionBase } from '@umbraco-cms/backoffice/entity-bulk-action';
|
||||
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbDocumentPublishEntityBulkAction extends UmbEntityBulkActionBase<UmbDocumentDetailRepository> {
|
||||
constructor(host: UmbControllerHostElement, repositoryAlias: string, selection: Array<string>) {
|
||||
super(host, repositoryAlias, selection);
|
||||
}
|
||||
import { UmbLanguageCollectionRepository } from '@umbraco-cms/backoffice/language';
|
||||
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
||||
|
||||
export class UmbDocumentPublishEntityBulkAction extends UmbEntityBulkActionBase<UmbDocumentPublishingRepository> {
|
||||
async execute() {
|
||||
console.log(`execute publish for: ${this.selection}`);
|
||||
//await this.repository?.publish();
|
||||
// If there is only one selection, we can refer to the regular publish entity action:
|
||||
if (this.selection.length === 1) {
|
||||
const action = new UmbPublishDocumentEntityAction(this._host, '', this.selection[0], '');
|
||||
await action.execute();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.repository) throw new Error('Document publishing repository not set');
|
||||
|
||||
const languageRepository = new UmbLanguageCollectionRepository(this._host);
|
||||
const { data: languageData } = await languageRepository.requestCollection({});
|
||||
|
||||
const options: UmbDocumentVariantOptionModel[] = (languageData?.items ?? []).map((language) => ({
|
||||
language,
|
||||
unique: new UmbVariantId(language.unique, null).toString(),
|
||||
}));
|
||||
|
||||
const selectedVariants = await umbPickDocumentVariantModal(this, { type: 'publish', options });
|
||||
|
||||
if (selectedVariants.length) {
|
||||
for (const unique of this.selection) {
|
||||
await this.repository.publish(unique, selectedVariants);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,36 @@
|
||||
import type { UmbDocumentDetailRepository } from '../../repository/index.js';
|
||||
import { UmbUnpublishDocumentEntityAction } from '../../entity-actions/unpublish.action.js';
|
||||
import { umbPickDocumentVariantModal } from '../../modals/index.js';
|
||||
import type { UmbDocumentPublishingRepository } from '../../repository/index.js';
|
||||
import type { UmbDocumentVariantOptionModel } from '../../types.js';
|
||||
import { UmbEntityBulkActionBase } from '@umbraco-cms/backoffice/entity-bulk-action';
|
||||
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbDocumentUnpublishEntityBulkAction extends UmbEntityBulkActionBase<UmbDocumentDetailRepository> {
|
||||
constructor(host: UmbControllerHostElement, repositoryAlias: string, selection: Array<string>) {
|
||||
super(host, repositoryAlias, selection);
|
||||
}
|
||||
import { UmbLanguageCollectionRepository } from '@umbraco-cms/backoffice/language';
|
||||
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
||||
|
||||
export class UmbDocumentUnpublishEntityBulkAction extends UmbEntityBulkActionBase<UmbDocumentPublishingRepository> {
|
||||
async execute() {
|
||||
console.log(`execute unpublish for: ${this.selection}`);
|
||||
//await this.repository?.unpublish();
|
||||
// If there is only one selection, we can refer to the regular publish entity action:
|
||||
if (this.selection.length === 1) {
|
||||
const action = new UmbUnpublishDocumentEntityAction(this._host, '', this.selection[0], '');
|
||||
await action.execute();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.repository) throw new Error('Document publishing repository not set');
|
||||
|
||||
const languageRepository = new UmbLanguageCollectionRepository(this._host);
|
||||
const { data: languageData } = await languageRepository.requestCollection({});
|
||||
|
||||
const options: UmbDocumentVariantOptionModel[] = (languageData?.items ?? []).map((language) => ({
|
||||
language,
|
||||
unique: new UmbVariantId(language.unique, null).toString(),
|
||||
}));
|
||||
|
||||
const selectedVariants = await umbPickDocumentVariantModal(this, { type: 'unpublish', options });
|
||||
|
||||
if (selectedVariants.length) {
|
||||
for (const unique of this.selection) {
|
||||
await this.repository.unpublish(unique, selectedVariants);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import type {
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
|
||||
import type { UmbFieldDropdownListElement } from '@umbraco-cms/backoffice/components';
|
||||
|
||||
@customElement('umb-templating-page-field-builder-modal')
|
||||
export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseElement<
|
||||
@@ -36,6 +37,10 @@ export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseEleme
|
||||
|
||||
/** TODO: Implement "Choose field" */
|
||||
|
||||
#onChangeFieldValue(e: Event) {
|
||||
this._field = (e.target as UmbFieldDropdownListElement).value?.alias;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<umb-body-layout headline=${this.localize.term('template_insert')}>
|
||||
@@ -44,7 +49,7 @@ export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseEleme
|
||||
<uui-label for="page-field-value">
|
||||
<umb-localize key="templateEditor_chooseField">Choose field</umb-localize>
|
||||
</uui-label>
|
||||
(Not implemented yet)
|
||||
<umb-field-dropdown-list @change=${this.#onChangeFieldValue} exclude-media-type></umb-field-dropdown-list>
|
||||
|
||||
<uui-label for="page-field-default-value">
|
||||
<umb-localize key="templateEditor_defaultValue">Default value</umb-localize>
|
||||
|
||||
Reference in New Issue
Block a user