types, sending data

This commit is contained in:
Lone Iversen
2024-05-22 14:31:37 +02:00
parent 9ca1540e10
commit f2da2c7186
8 changed files with 76 additions and 62 deletions

View File

@@ -1 +1,8 @@
import type { UmbMediaCardItemModel } from '../../modals/index.js';
import type { UmbMediaPickerPropertyValue } from '../../property-editors/index.js';
export * from './input-rich-media.element.js';
export interface UmbRichMediaItemModel extends UmbMediaCardItemModel, UmbMediaPickerPropertyValue {
src: string;
}

View File

@@ -1,32 +1,27 @@
import { UMB_MEDIA_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
import type { UmbCropModel } from '../../property-editors/index.js';
import { UMB_MEDIA_ITEM_REPOSITORY_ALIAS, type UmbMediaItemModel } from '../../repository/index.js';
import type { UmbCropModel, UmbMediaPickerPropertyValue } from '../../property-editors/index.js';
import {
UMB_MEDIA_PICKER_MODAL,
type UmbMediaCardItemModel,
type UmbMediaPickerModalData,
type UmbMediaPickerModalValue,
} from '../../modals/index.js';
import type { UmbImageCropperCrop, UmbImageCropperCrops } from '../input-image-cropper/types.js';
import type { UmbRichMediaItemModel } from './index.js';
import { UmbPickerInputContext } from '@umbraco-cms/backoffice/picker-input';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbArrayState, UmbBooleanState } from '@umbraco-cms/backoffice/observable-api';
import { UmbImagingRepository } from '@umbraco-cms/backoffice/imaging';
import { ImageCropModeModel } from '@umbraco-cms/backoffice/external/backend-api';
interface UmbRichMediaItemModel extends UmbMediaCardItemModel {
crops: UmbImageCropperCrops;
focalPoint?: { left: number; top: number };
}
export class UmbRichMediaPickerContext extends UmbPickerInputContext<
UmbRichMediaItemModel,
UmbRichMediaItemModel,
UmbMediaPickerModalData<UmbRichMediaItemModel>,
UmbMediaItemModel,
UmbMediaItemModel,
UmbMediaPickerModalData<UmbMediaItemModel>,
UmbMediaPickerModalValue
> {
#imagingRepository: UmbImagingRepository;
#selectedRichItems = new UmbArrayState<UmbRichMediaItemModel>([], (x) => x.unique);
#selectedRichItems = new UmbArrayState<UmbRichMediaItemModel>([], (x) => x.key);
readonly richItems = this.#selectedRichItems.asObservable();
#preselectedCrops = new UmbArrayState<UmbCropModel>([], (x) => x.alias);
@@ -35,8 +30,12 @@ export class UmbRichMediaPickerContext extends UmbPickerInputContext<
#focalPointEnabled = new UmbBooleanState<boolean>(false);
readonly focalPointEnabled = this.#focalPointEnabled.asObservable();
#mediaPickerValue = new UmbArrayState<UmbMediaPickerPropertyValue>([], (x) => x.key);
readonly mediaPickerValue = this.#mediaPickerValue.asObservable();
constructor(host: UmbControllerHost) {
super(host, UMB_MEDIA_ITEM_REPOSITORY_ALIAS, UMB_MEDIA_PICKER_MODAL);
this.#imagingRepository = new UmbImagingRepository(host);
this.observe(this.selectedItems, async (selectedItems) => {
@@ -59,9 +58,9 @@ export class UmbRichMediaPickerContext extends UmbPickerInputContext<
return {
...item,
url: url ?? '',
src: url ?? '',
crops: previous?.crops ?? [],
focalPoint: previous?.focalPoint,
focalPoint: previous?.focalPoint ?? null,
};
});
@@ -85,15 +84,15 @@ export class UmbRichMediaPickerContext extends UmbPickerInputContext<
return this.#preselectedCrops.getValue();
}
updateFocalPointOfSelectedRichItem(unique: string, focalPoint: { left: number; top: number }) {
updateFocalPointOf(unique: string, focalPoint: { left: number; top: number }) {
this.#selectedRichItems.updateOne(unique, { focalPoint });
}
updateCropsOfSelectedRichItem(unique: string, crops: UmbImageCropperCrops) {
updateCropsOf(unique: string, crops: UmbImageCropperCrops) {
this.#selectedRichItems.updateOne(unique, { crops });
}
updateOneCropOfSelectedRichItem(unique: string, alias: string, newCrop: UmbImageCropperCrop) {
updateOneCropOf(unique: string, alias: string, newCrop: UmbImageCropperCrop) {
const item = this.#selectedRichItems.getValue().find((item) => item.unique);
if (!item) return;

View File

@@ -1,10 +1,13 @@
import type { UmbCropModel, UmbFocalPointModel, UmbMediaPickerPropertyValue } from '../../property-editors/index.js';
import type { UmbCropModel, UmbMediaPickerPropertyValue } from '../../property-editors/index.js';
import { UMB_IMAGE_CROPPER_EDITOR_MODAL, type UmbMediaCardItemModel } from '../../modals/index.js';
import { UmbRichMediaPickerContext } from './input-rich-media.context.js';
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
import { customElement, html, ifDefined, property, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbInputMediaElement } from '@umbraco-cms/backoffice/media';
import type { UmbUploadableFileModel } from '@umbraco-cms/backoffice/media';
import {
UmbInputMediaElement,
type UmbRichMediaItemModel,
type UmbUploadableFileModel,
} from '@umbraco-cms/backoffice/media';
import { type UmbModalRouteBuilder, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal';
import type { UmbVariantId } from '@umbraco-cms/backoffice/variant';
@@ -15,13 +18,15 @@ export class UmbInputRichMediaElement extends UmbInputMediaElement {
#modal: UmbModalRouteRegistrationController;
#pickerContext = new UmbRichMediaPickerContext(this);
private _value: Array<UmbMediaPickerPropertyValue> = [];
@property()
public set value(value: any) {
this._value = value as Array<UmbMediaPickerPropertyValue>;
@state()
private _items: Array<UmbRichMediaItemModel> = [];
@property({ type: Array })
public set richValue(value: Array<UmbMediaPickerPropertyValue>) {
this.#pickerContext.setSelection(value);
}
public get value() {
return this._value;
public get richValue(): Array<UmbMediaPickerPropertyValue> {
return this.#pickerContext.getSelection();
}
@property({ type: Array })
@@ -40,9 +45,6 @@ export class UmbInputRichMediaElement extends UmbInputMediaElement {
return this.#pickerContext.getFocalPointEnabled();
}
@state()
private _modalRoute?: UmbModalRouteBuilder;
@property()
public set alias(value: string | undefined) {
this.#modal.setUniquePathValue('propertyAlias', value);
@@ -59,6 +61,8 @@ export class UmbInputRichMediaElement extends UmbInputMediaElement {
return this.#modal.getUniquePathValue('variantId');
}
@state()
private _modalRoute?: UmbModalRouteBuilder;
constructor() {
super();
this.#modal = new UmbModalRouteRegistrationController(this, UMB_IMAGE_CROPPER_EDITOR_MODAL)
@@ -75,11 +79,13 @@ export class UmbInputRichMediaElement extends UmbInputMediaElement {
return {
data: { cropOptions: this.preselectedCrops, focalPointEnabled: this.focalPointEnabled, unique },
value: { crops: [], focalPoint: { left: 0.5, top: 0.5 }, src: '' },
value: { crops: [], focalPoint: { left: 0.5, top: 0.5 }, src: '', unique: unique },
};
})
.onSubmit((value) => {
console.log('callback', value);
this.#pickerContext.updateFocalPointOf(value.unique, value.focalPoint);
this.#pickerContext.updateCropsOf(value.unique, value.crops);
this.dispatchEvent(new UmbChangeEvent());
})
.observeRouteBuilder((routeBuilder) => {
this._modalRoute = routeBuilder;
@@ -89,6 +95,10 @@ export class UmbInputRichMediaElement extends UmbInputMediaElement {
this.addValidators();
}
connectedCallback(): void {
super.connectedCallback();
}
async #onUploadCompleted(e: CustomEvent) {
const completed = e.detail?.completed as Array<UmbUploadableFileModel>;
const uploaded = completed.map((file) => file.unique);
@@ -113,8 +123,8 @@ export class UmbInputRichMediaElement extends UmbInputMediaElement {
name=${ifDefined(item.name === null ? undefined : item.name)}
detail=${ifDefined(item.unique)}
.href=${href}>
${item.url
? html`<img src=${item.url} alt=${item.name} />`
${item.src
? html`<img src=${item.src} alt=${item.name} />`
: html`<umb-icon name=${ifDefined(item.mediaType.icon)}></umb-icon>`}
${this.renderIsTrashed(item)}
<uui-action-bar slot="actions">

View File

@@ -1,5 +1,5 @@
import type { UmbInputImageCropperFieldElement } from '../../components/input-image-cropper/image-cropper-field.element.js';
import type { UmbImageCropperPropertyEditorValue } from '../../components/index.js';
import type { UmbImagingModel } from '../../../../core/imaging/types.js';
import { UmbMediaUrlRepository } from '../../repository/index.js';
import type { UmbCropModel } from '../../property-editors/index.js';
import type {
@@ -8,8 +8,6 @@ import type {
} from './image-cropper-editor-modal.token.js';
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbImagingRepository } from '@umbraco-cms/backoffice/imaging';
import { ImageCropModeModel } from '@umbraco-cms/backoffice/external/backend-api';
/** TODO Make some of the components from property editor image cropper reuseable for this modal... */
@@ -28,6 +26,7 @@ export class UmbImageCropperEditorModalElement extends UmbModalBaseElement<
@state()
private _focalPointEnabled = false;
/** TODO allow to enable/disable focalpoint */
@state()
private _crops: Array<UmbCropModel> = [];
@@ -56,10 +55,17 @@ export class UmbImageCropperEditorModalElement extends UmbModalBaseElement<
this._imageCropperValue = value;
}
#onChange(e: CustomEvent) {
const value = (e.target as UmbInputImageCropperFieldElement).value;
if (!value) return;
this.value = { unique: this._unique, crops: value.crops, focalPoint: value.focalPoint };
}
render() {
return html`
<umb-body-layout headline=${this.localize.term('defaultdialogs_selectMedia')}>
<umb-image-cropper-field .value=${this._imageCropperValue}></umb-image-cropper-field>
<umb-image-cropper-field @change=${this.#onChange} .value=${this._imageCropperValue}></umb-image-cropper-field>
<div slot="actions">
<uui-button label=${this.localize.term('general_close')} @click=${this._rejectModal}></uui-button>
<uui-button

View File

@@ -9,6 +9,7 @@ export interface UmbImageCropperEditorModalData {
}
export interface UmbImageCropperEditorModalValue {
unique: string;
crops: Array<UmbImageCropperCrop>;
focalPoint: { left: number; top: number };
}

View File

@@ -2,7 +2,7 @@ import type { UmbMediaItemModel } from '../../repository/index.js';
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
export interface UmbMediaCardItemModel extends UmbMediaItemModel {
url?: string;
src?: string;
}
export interface UmbMediaPathModel extends UmbEntityModel {

View File

@@ -8,7 +8,19 @@ export type UmbMediaPickerPropertyValue = {
crops: Array<UmbCropModel>;
};
export interface UmbCropModel {
export type UmbCropModel = {
alias: string;
height: number;
width: number;
coordinates?: {
x1: number;
x2: number;
y1: number;
y2: number;
};
};
export interface UmbConfiguredCropModel {
label: string;
alias: string;
width: number;

View File

@@ -1,8 +1,6 @@
import type { UmbInputRichMediaElement } from '../../components/input-rich-media/input-rich-media.element.js';
import type { UmbCropModel, UmbMediaPickerPropertyValue } from './index.js';
import { customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbId } from '@umbraco-cms/backoffice/id';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor';
import type { NumberRangeValueType } from '@umbraco-cms/backoffice/models';
@@ -23,9 +21,7 @@ export class UmbPropertyEditorUIMediaPickerElement extends UmbLitElement impleme
@property({ attribute: false })
public set value(value: Array<UmbMediaPickerPropertyValue>) {
this.#value = value;
this._items = this.value ? this.value.map((x) => x.mediaKey) : [];
}
//TODO: Add support for document specific crops. The server side already supports this.
public get value() {
return this.#value;
}
@@ -64,9 +60,6 @@ export class UmbPropertyEditorUIMediaPickerElement extends UmbLitElement impleme
@state()
private _multiple: boolean = false;
@state()
_items: Array<string> = [];
@state()
private _limitMin: number = 0;
@@ -89,20 +82,7 @@ export class UmbPropertyEditorUIMediaPickerElement extends UmbLitElement impleme
}
#onChange(event: CustomEvent & { target: UmbInputRichMediaElement }) {
const selection = event.target.selection;
const result = selection.map((mediaKey) => {
return {
key: UmbId.new(),
mediaKey,
mediaTypeAlias: '',
focalPoint: null,
crops: [],
};
});
this.value = result;
this._items = this.value ? this.value.map((x) => x.mediaKey) : [];
this.value = event.target.richValue;
this.dispatchEvent(new UmbPropertyValueChangeEvent());
}
@@ -111,14 +91,13 @@ export class UmbPropertyEditorUIMediaPickerElement extends UmbLitElement impleme
<umb-input-rich-media
@change=${this.#onChange}
?multiple=${this._multiple}
.value=${this.value}
.richValue=${this.value}
.variantId=${this._variantId}
.alias=${this._alias}
.allowedContentTypeIds=${this._allowedMediaTypes}
.startNode=${this._startNode}
.focalPointEnabled=${this._focalPointEnabled}
.preselectedCrops=${this._preselectedCrops}
.selection=${this._items}
.min=${this._limitMin}
.max=${this._limitMax}>
</umb-input-rich-media>