Upload field Property Editor: Fix resetting value to undefined when empty (#20134)
* set value to undefined when empty * fix nullable checks * ensure promise rejection when validation fails * avoid js error when detailStore is not present * implement editor as form control * remove unused --------- Co-authored-by: Mads Rasmussen <madsr@hey.com>
This commit is contained in:
@@ -821,7 +821,7 @@ export abstract class UmbContentDetailWorkspaceContextBase<
|
||||
* Request a submit of the workspace, in the case of Document Workspaces the validation does not need to be valid for this to be submitted.
|
||||
* @returns {Promise<void>} a promise which resolves once it has been completed.
|
||||
*/
|
||||
public override requestSubmit() {
|
||||
public override requestSubmit(): Promise<void> {
|
||||
return this._handleSubmit();
|
||||
}
|
||||
|
||||
@@ -831,7 +831,7 @@ export abstract class UmbContentDetailWorkspaceContextBase<
|
||||
|
||||
/**
|
||||
* Request a save of the workspace, in the case of Document Workspaces the validation does not need to be valid for this to be saved.
|
||||
* @returns {Promise<void>} a promise which resolves once it has been completed.
|
||||
* @returns {Promise<void>} A promise which resolves once it has been completed.
|
||||
*/
|
||||
public requestSave() {
|
||||
return this._handleSave();
|
||||
@@ -847,11 +847,11 @@ export abstract class UmbContentDetailWorkspaceContextBase<
|
||||
return this._data.constructData(variantIds);
|
||||
}
|
||||
|
||||
protected async _handleSubmit() {
|
||||
protected async _handleSubmit(): Promise<void> {
|
||||
await this._handleSave();
|
||||
this._closeModal();
|
||||
}
|
||||
protected async _handleSave() {
|
||||
protected async _handleSave(): Promise<void> {
|
||||
const data = this.getData();
|
||||
if (!data) {
|
||||
throw new Error('Data is missing');
|
||||
@@ -877,7 +877,9 @@ export abstract class UmbContentDetailWorkspaceContextBase<
|
||||
value: { selection: selected },
|
||||
}).catch(() => undefined);
|
||||
|
||||
if (!result?.selection.length) return;
|
||||
if (!result?.selection.length) {
|
||||
return Promise.reject('Cannot save without selecting at least one variant.');
|
||||
}
|
||||
|
||||
variantIds = result?.selection.map((x) => UmbVariantId.FromString(x)) ?? [];
|
||||
} else {
|
||||
@@ -897,7 +899,9 @@ export abstract class UmbContentDetailWorkspaceContextBase<
|
||||
() => false,
|
||||
);
|
||||
if (valid || this.#ignoreValidationResultOnSubmit) {
|
||||
return this.performCreateOrUpdate(variantIds, saveData);
|
||||
await this.performCreateOrUpdate(variantIds, saveData);
|
||||
} else {
|
||||
return Promise.reject('Validation issues prevent saving');
|
||||
}
|
||||
} else {
|
||||
await this.performCreateOrUpdate(variantIds, saveData);
|
||||
|
||||
@@ -263,6 +263,14 @@ export function UmbFormControlMixin<
|
||||
* @returns {void}
|
||||
*/
|
||||
protected addFormControlElement(element: UmbNativeFormControlElement) {
|
||||
if (!element) {
|
||||
throw new Error('Element is null or undefined');
|
||||
}
|
||||
if (!element.validity) {
|
||||
console.log(element);
|
||||
throw new Error('Element is not a Form Control');
|
||||
}
|
||||
if (this.#formCtrlElements.includes(element)) return;
|
||||
this.#formCtrlElements.push(element);
|
||||
element.addEventListener(UmbValidationInvalidEvent.TYPE, this.#runValidatorsCallback);
|
||||
element.addEventListener(UmbValidationValidEvent.TYPE, this.#runValidatorsCallback);
|
||||
|
||||
@@ -49,6 +49,6 @@ export class UmbSaveWorkspaceAction<
|
||||
|
||||
override async execute() {
|
||||
await this._retrieveWorkspaceContext;
|
||||
return await this._workspaceContext?.requestSave();
|
||||
await this._workspaceContext?.requestSave();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,19 +16,26 @@ import type {
|
||||
} from '@umbraco-cms/backoffice/dropzone';
|
||||
import type { UmbTemporaryFileModel } from '@umbraco-cms/backoffice/temporary-file';
|
||||
import { UMB_SERVER_CONTEXT } from '@umbraco-cms/backoffice/server';
|
||||
import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
|
||||
|
||||
@customElement('umb-input-upload-field')
|
||||
export class UmbInputUploadFieldElement extends UmbLitElement {
|
||||
export class UmbInputUploadFieldElement extends UmbFormControlMixin<UmbMediaValueType, typeof UmbLitElement>(
|
||||
UmbLitElement,
|
||||
) {
|
||||
@property({ type: Object, attribute: false })
|
||||
set value(value: UmbMediaValueType) {
|
||||
override set value(value: UmbMediaValueType | undefined) {
|
||||
super.value = value;
|
||||
this.#src = value?.src ?? '';
|
||||
this.#setPreviewAlias();
|
||||
}
|
||||
get value(): UmbMediaValueType {
|
||||
return {
|
||||
src: this.#src,
|
||||
temporaryFileId: this.temporaryFile?.temporaryUnique,
|
||||
};
|
||||
override get value(): UmbMediaValueType | undefined {
|
||||
if (this.#src || this.temporaryFile?.temporaryUnique) {
|
||||
return {
|
||||
src: this.#src,
|
||||
temporaryFileId: this.temporaryFile?.temporaryUnique,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
#src = '';
|
||||
|
||||
@@ -86,7 +93,7 @@ export class UmbInputUploadFieldElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
async #getPreviewElementAlias() {
|
||||
if (!this.value.src) return;
|
||||
if (!this.value?.src) return;
|
||||
const manifests = await this.#getManifests();
|
||||
const fallbackAlias = manifests.find((manifest) =>
|
||||
stringOrStringArrayContains(manifest.forMimeTypes, '*/*'),
|
||||
@@ -158,7 +165,7 @@ export class UmbInputUploadFieldElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
override render() {
|
||||
if (!this.temporaryFile && !this.value.src) {
|
||||
if (!this.temporaryFile && !this.value?.src) {
|
||||
return this.#renderDropzone();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
import type { UmbInputUploadFieldElement } from '../../components/input-upload-field/input-upload-field.element.js';
|
||||
import type { UmbMediaValueType } from './types.js';
|
||||
import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type {
|
||||
UmbPropertyEditorUiElement,
|
||||
UmbPropertyEditorConfigCollection,
|
||||
} from '@umbraco-cms/backoffice/property-editor';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||
import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
|
||||
|
||||
import '../../components/input-upload-field/input-upload-field.element.js';
|
||||
|
||||
/**
|
||||
* @element umb-property-editor-ui-upload-field
|
||||
*/
|
||||
@customElement('umb-property-editor-ui-upload-field')
|
||||
export class UmbPropertyEditorUIUploadFieldElement extends UmbLitElement implements UmbPropertyEditorUiElement {
|
||||
@property({ type: Object })
|
||||
value: UmbMediaValueType = {};
|
||||
|
||||
export class UmbPropertyEditorUIUploadFieldElement
|
||||
extends UmbFormControlMixin<UmbMediaValueType, typeof UmbLitElement>(UmbLitElement)
|
||||
implements UmbPropertyEditorUiElement
|
||||
{
|
||||
@state()
|
||||
private _fileExtensions?: Array<string>;
|
||||
|
||||
@@ -29,6 +32,10 @@ export class UmbPropertyEditorUIUploadFieldElement extends UmbLitElement impleme
|
||||
}
|
||||
}
|
||||
|
||||
override firstUpdated() {
|
||||
this.addFormControlElement(this.shadowRoot!.querySelector('umb-input-upload-field')!);
|
||||
}
|
||||
|
||||
#onChange(event: CustomEvent) {
|
||||
this.value = (event.target as UmbInputUploadFieldElement).value;
|
||||
this.dispatchEvent(new UmbChangeEvent());
|
||||
|
||||
@@ -49,6 +49,9 @@ export class UmbMediaValidationServerDataSource {
|
||||
MediaService.postMediaValidate({
|
||||
body,
|
||||
}),
|
||||
{
|
||||
disableNotifications: true,
|
||||
},
|
||||
);
|
||||
|
||||
if (data && typeof data === 'string') {
|
||||
@@ -86,6 +89,9 @@ export class UmbMediaValidationServerDataSource {
|
||||
path: { id: model.unique },
|
||||
body,
|
||||
}),
|
||||
{
|
||||
disableNotifications: true,
|
||||
},
|
||||
);
|
||||
|
||||
if (data && typeof data === 'string') {
|
||||
|
||||
@@ -19,7 +19,7 @@ export class UmbMemberCollectionRepository extends UmbMemberRepositoryBase imple
|
||||
const { data, error } = await this.#collectionSource.getCollection(filter);
|
||||
|
||||
if (data) {
|
||||
this.detailStore!.appendItems(data.items);
|
||||
this.detailStore?.appendItems(data.items);
|
||||
}
|
||||
|
||||
return { data, error, asObservable: () => this.detailStore!.all() };
|
||||
|
||||
@@ -19,7 +19,7 @@ export class UmbUserCollectionRepository extends UmbUserRepositoryBase implement
|
||||
const { data, error } = await this.#collectionSource.getCollection(filter);
|
||||
|
||||
if (data) {
|
||||
this.detailStore!.appendItems(data.items);
|
||||
this.detailStore?.appendItems(data.items);
|
||||
}
|
||||
|
||||
return { data, error, asObservable: () => this.detailStore!.all() };
|
||||
|
||||
Reference in New Issue
Block a user