Merge remote-tracking branch 'origin/main' into bugfix/content-type-design-editor-fixes-20240416

This commit is contained in:
Niels Lyngsø
2024-04-16 11:56:16 +02:00
6 changed files with 97 additions and 56 deletions

View File

@@ -1,6 +1,5 @@
import type { Meta, StoryObj } from '@storybook/web-components';
import type { UmbInputDateElement } from './input-date.element.js';
import { html } from '@umbraco-cms/backoffice/external/lit';
import './input-date.element.js';
const meta: Meta<UmbInputDateElement> = {
@@ -15,7 +14,6 @@ export const Overview: Story = {
args: {
type: 'datetime-local',
value: '2023-04-01T10:00:00Z',
offsetTime: true,
},
};
@@ -23,7 +21,6 @@ export const Date: Story = {
args: {
type: 'date',
value: '2023-04-01',
offsetTime: false,
},
};
@@ -31,36 +28,13 @@ export const Time: Story = {
args: {
type: 'time',
value: '10:00',
offsetTime: false,
},
};
export const DatetimelocalOffset: Story = {
args: {
type: 'datetime-local',
value: '2023-04-01T10:00:00',
offsetTime: true,
displayValue: '',
},
render: (args) =>
html`<umb-input-date
.type="${args.type}"
.value="${args.value}"
.offsetTime="${args.offsetTime}"
.displayValue="${args.displayValue}"></umb-input-date>`,
};
export const Datetimelocal: Story = {
args: {
type: 'datetime-local',
value: '2023-04-01T10:00:00',
offsetTime: false,
displayValue: '',
},
render: (args) =>
html`<umb-input-date
.type="${args.type}"
.value="${args.value}"
.offsetTime="${args.offsetTime}"
.displayValue="${args.displayValue}"></umb-input-date>`,
};

View File

@@ -45,7 +45,12 @@ export class UmbInputUploadFieldElement extends UUIFormControlMixin(UmbLitElemen
* @default undefined
*/
@property({ type: Array })
fileExtensions?: Array<string>;
set fileExtensions(value: Array<string>) {
this.#setExtensions(value);
}
get fileExtensions(): Array<string> | undefined {
return this.extensions;
}
/**
* @description Allows the user to upload multiple files.
@@ -104,11 +109,6 @@ export class UmbInputUploadFieldElement extends UUIFormControlMixin(UmbLitElemen
});
}
connectedCallback(): void {
super.connectedCallback();
this.#setExtensions();
}
async #setFilePaths() {
await this.#serverUrlPromise;
@@ -123,11 +123,9 @@ export class UmbInputUploadFieldElement extends UUIFormControlMixin(UmbLitElemen
});
}
#setExtensions() {
if (!this.fileExtensions?.length) return;
#setExtensions(value: Array<string>) {
// TODO: The dropzone uui component does not support file extensions without a dot. Remove this when it does.
this.extensions = this.fileExtensions.map((extension) => {
this.extensions = value.map((extension) => {
return `.${extension}`;
});
}

View File

@@ -15,9 +15,7 @@ export class UmbPropertyEditorUIUploadFieldElement extends UmbLitElement impleme
public set config(config: UmbPropertyEditorConfigCollection | undefined) {
if (!config) return;
this._fileExtensions = config
.getValueByAlias<{ id: number; value: string }[]>('fileExtensions')
?.map((ext) => ext.value);
this._fileExtensions = config.getValueByAlias<Array<string>>('fileExtensions');
this._multiple = config.getValueByAlias('multiple');
}

View File

@@ -85,7 +85,7 @@ export class UmbSectionSidebarContextMenuElement extends UmbLitElement {
#renderModal() {
return this._isOpen && this._unique !== undefined && this._entityType
? html`<div id="action-modal">
<h3>${this._headline}</h3>
${this._headline ? html`<h3>${this.localize.string(this._headline)}</h3>` : nothing}
<umb-entity-action-list
@action-executed=${this.#onActionExecuted}
.entityType=${this._entityType}

View File

@@ -40,7 +40,7 @@ export class UmbUserGroupServerDataSource implements UmbDetailDataSource<UmbUser
unique: UmbId.new(),
isSystemGroup: false,
name: '',
icon: null,
icon: 'icon-users',
sections: [],
languages: [],
hasAccessToAllLanguages: false,

View File

@@ -3,13 +3,14 @@ import { UMB_USER_GROUP_ENTITY_TYPE } from '../index.js';
import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from './user-group-workspace.context-token.js';
import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui';
import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { css, html, nothing, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import type { UmbInputDocumentElement } from '@umbraco-cms/backoffice/document';
import type { UmbInputSectionElement } from '@umbraco-cms/backoffice/section';
import type { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
import type { UmbInputMediaElement } from '@umbraco-cms/backoffice/media';
import { UMB_ICON_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import './components/user-group-entity-user-permission-list.element.js';
import './components/user-group-granular-permission-list.element.js';
@@ -17,7 +18,22 @@ import './components/user-group-granular-permission-list.element.js';
@customElement('umb-user-group-workspace-editor')
export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
@state()
private _userGroup?: UmbUserGroupDetailModel;
private _unique?: UmbUserGroupDetailModel['unique'];
@state()
private _name?: UmbUserGroupDetailModel['name'];
@state()
private _icon: UmbUserGroupDetailModel['icon'] = null;
@state()
private _sections: UmbUserGroupDetailModel['sections'] = [];
@state()
private _documentStartNode?: UmbUserGroupDetailModel['documentStartNode'];
@state()
private _mediaStartNode?: UmbUserGroupDetailModel['mediaStartNode'];
#workspaceContext?: typeof UMB_USER_GROUP_WORKSPACE_CONTEXT.TYPE;
@@ -26,10 +42,28 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
this.consumeContext(UMB_USER_GROUP_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance;
this.observe(this.#workspaceContext.data, (userGroup) => (this._userGroup = userGroup), 'umbUserGroupObserver');
this.#observeUserGroup();
});
}
#observeUserGroup() {
if (!this.#workspaceContext) return;
this.observe(this.#workspaceContext.unique, (value) => (this._unique = value), '_observeUnique');
this.observe(this.#workspaceContext.name, (value) => (this._name = value), '_observeName');
this.observe(this.#workspaceContext.icon, (value) => (this._icon = value), '_observeIcon');
this.observe(this.#workspaceContext.sections, (value) => (this._sections = value), '_observeSections');
this.observe(
this.#workspaceContext.documentStartNode,
(value) => (this._documentStartNode = value),
'_observeDocumentStartNode',
);
this.observe(
this.#workspaceContext.mediaStartNode,
(value) => (this._mediaStartNode = value),
'_observeDocumentStartNode',
);
}
#onSectionsChange(event: UmbChangeEvent) {
event.stopPropagation();
const target = event.target as UmbInputSectionElement;
@@ -59,7 +93,7 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
}
render() {
if (!this._userGroup) return nothing;
if (!this._unique) return nothing;
return html`
<umb-workspace-editor alias="Umb.Workspace.UserGroup" class="uui-text">
@@ -72,16 +106,40 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
`;
}
async #onIconClick() {
const [alias, color] = this._icon?.replace('color-', '')?.split(' ') ?? [];
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
const modalContext = modalManager.open(this, UMB_ICON_PICKER_MODAL, {
value: {
icon: alias,
color: color,
},
});
modalContext?.onSubmit().then((saved) => {
if (saved.icon && saved.color) {
this.#workspaceContext?.updateProperty('icon', `${saved.icon} color-${saved.color}`);
} else if (saved.icon) {
this.#workspaceContext?.updateProperty('icon', saved.icon);
}
});
}
#renderHeader() {
return html`
<div id="header" slot="header">
<a href="section/user-management/view/user-groups">
<uui-icon name="icon-arrow-left"></uui-icon>
</a>
<uui-button id="icon" @click=${this.#onIconClick} label="icon" compact>
<umb-icon name=${ifDefined(ifDefined(this._icon))}></umb-icon>
</uui-button>
<uui-input
id="name"
label=${this.localize.term('general_name')}
.value=${this._userGroup?.name ?? ''}
.value=${this._name}
@input="${this.#onNameChange}"
${umbFocus()}></uui-input>
</div>
@@ -89,7 +147,7 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
}
#renderLeftColumn() {
if (!this._userGroup) return nothing;
if (!this._unique) return nothing;
return html`
<uui-box>
@@ -99,7 +157,7 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
description=${this.localize.term('user_sectionsHelp')}>
<umb-input-section
slot="editor"
.selection=${this._userGroup.sections ?? []}
.selection=${this._sections}
@change=${this.#onSectionsChange}></umb-input-section>
</umb-property-layout>
<umb-property-layout
@@ -108,7 +166,7 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
<umb-input-document
slot="editor"
max="1"
.selection=${this._userGroup.documentStartNode?.unique ? [this._userGroup.documentStartNode.unique] : []}
.selection=${this._documentStartNode?.unique ? [this._documentStartNode.unique] : []}
@change=${this.#onDocumentStartNodeChange}></umb-input-document>
</umb-property-layout>
<umb-property-layout
@@ -117,7 +175,7 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
<umb-input-media
slot="editor"
max="1"
.selection=${this._userGroup.mediaStartNode?.unique ? [this._userGroup.mediaStartNode.unique] : []}
.selection=${this._mediaStartNode?.unique ? [this._mediaStartNode.unique] : []}
@change=${this.#onMediaStartNodeChange}></umb-input-media>
</umb-property-layout>
</uui-box>
@@ -139,9 +197,7 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
#renderRightColumn() {
return html` <uui-box headline="Actions">
<umb-entity-action-list
.entityType=${UMB_USER_GROUP_ENTITY_TYPE}
.unique=${this._userGroup?.unique}></umb-entity-action-list
<umb-entity-action-list .entityType=${UMB_USER_GROUP_ENTITY_TYPE} .unique=${this._unique}></umb-entity-action-list
></uui-box>`;
}
@@ -152,28 +208,43 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
display: block;
height: 100%;
}
#header {
width: 100%;
display: grid;
grid-template-columns: var(--uui-size-layout-1) 1fr;
display: flex;
flex: 1 1 auto;
gap: var(--uui-size-space-3);
}
#icon {
font-size: calc(var(--uui-size-layout-3) / 2);
}
#name {
width: 100%;
flex: 1 1 auto;
align-items: center;
}
#main {
display: grid;
grid-template-columns: 1fr 350px;
gap: var(--uui-size-layout-1);
padding: var(--uui-size-layout-1);
}
#left-column,
#right-column {
display: flex;
flex-direction: column;
gap: var(--uui-size-space-4);
}
#right-column > uui-box > div {
display: flex;
flex-direction: column;
gap: var(--uui-size-space-2);
}
uui-input {
width: 100%;
}