Merge remote-tracking branch 'origin/main' into feature/easy-way-to-produce-a-set-of-properties

This commit is contained in:
Niels Lyngsø
2023-12-07 13:34:37 +01:00
18 changed files with 616 additions and 65 deletions

View File

@@ -33,3 +33,4 @@ export * from './tooltip-menu/index.js';
export * from './variant-selector/index.js';
export * from './popover-layout/index.js';
export * from './multiple-text-string-input/index.js';
export * from './multiple-color-picker-input/index.js';

View File

@@ -13,9 +13,9 @@ import {
@customElement('umb-image-cropper-focus-setter')
export class UmbImageCropperFocusSetterElement extends LitElement {
@query('#image') imageElement!: HTMLImageElement;
@query('#wrapper') wrapperElement!: HTMLImageElement;
@query('#focal-point') focalPointElement!: HTMLImageElement;
@query('#image') imageElement?: HTMLImageElement;
@query('#wrapper') wrapperElement?: HTMLImageElement;
@query('#focal-point') focalPointElement?: HTMLImageElement;
@property({ type: String }) src?: string;
@property({ attribute: false }) focalPoint: UmbImageCropperFocalPoint = { left: 0.5, top: 0.5 };
@@ -35,7 +35,7 @@ export class UmbImageCropperFocusSetterElement extends LitElement {
protected updated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
super.updated(_changedProperties);
if (_changedProperties.has('focalPoint')) {
if (_changedProperties.has('focalPoint') && this.focalPointElement) {
this.focalPointElement.style.left = `calc(${this.focalPoint.left * 100}% - ${this.#DOT_RADIUS}px)`;
this.focalPointElement.style.top = `calc(${this.focalPoint.top * 100}% - ${this.#DOT_RADIUS}px)`;
}
@@ -45,23 +45,28 @@ export class UmbImageCropperFocusSetterElement extends LitElement {
super.firstUpdated(_changedProperties);
this.style.setProperty('--dot-radius', `${this.#DOT_RADIUS}px`);
this.focalPointElement.style.left = `calc(${this.focalPoint.left * 100}% - ${this.#DOT_RADIUS}px)`;
this.focalPointElement.style.top = `calc(${this.focalPoint.top * 100}% - ${this.#DOT_RADIUS}px)`;
this.imageElement.onload = () => {
const imageAspectRatio = this.imageElement.naturalWidth / this.imageElement.naturalHeight;
if (this.focalPointElement) {
this.focalPointElement.style.left = `calc(${this.focalPoint.left * 100}% - ${this.#DOT_RADIUS}px)`;
this.focalPointElement.style.top = `calc(${this.focalPoint.top * 100}% - ${this.#DOT_RADIUS}px)`;
}
if (this.imageElement) {
this.imageElement.onload = () => {
if (!this.imageElement || !this.wrapperElement) return;
const imageAspectRatio = this.imageElement.naturalWidth / this.imageElement.naturalHeight;
if (imageAspectRatio > 1) {
this.imageElement.style.width = '100%';
this.wrapperElement.style.width = '100%';
} else {
this.imageElement.style.height = '100%';
this.wrapperElement.style.height = '100%';
}
if (imageAspectRatio > 1) {
this.imageElement.style.width = '100%';
this.wrapperElement.style.width = '100%';
} else {
this.imageElement.style.height = '100%';
this.wrapperElement.style.height = '100%';
}
this.imageElement.style.aspectRatio = `${imageAspectRatio}`;
this.wrapperElement.style.aspectRatio = `${imageAspectRatio}`;
};
this.imageElement.style.aspectRatio = `${imageAspectRatio}`;
this.wrapperElement.style.aspectRatio = `${imageAspectRatio}`;
};
}
}
async #addEventListeners() {
@@ -92,6 +97,7 @@ export class UmbImageCropperFocusSetterElement extends LitElement {
#onSetFocalPoint(event: MouseEvent) {
event.preventDefault();
if (!this.focalPointElement || !this.imageElement) return;
const image = this.imageElement.getBoundingClientRect();

View File

@@ -109,8 +109,8 @@ export class UmbInputImageCropperElement extends LitElement {
.focalPoint=${this.focalPoint}
.src=${this.src}></umb-image-cropper-focus-setter>
<div id="actions">
<uui-button>Remove files (NOT IMPLEMENTED YET)</uui-button>
<uui-button @click=${this.#onResetFocalPoint}>Reset focal point</uui-button>
<uui-button label="Remove files">Remove files (NOT IMPLEMENTED YET)</uui-button>
<uui-button label="Reset focal point" @click=${this.#onResetFocalPoint}>Reset focal point</uui-button>
</div> `;
}

View File

@@ -0,0 +1,2 @@
export * from './multiple-color-picker-input.element.js';
export * from './multiple-color-picker-item-input.element.js';

View File

@@ -0,0 +1,254 @@
import { UMB_DATA_TYPE_WORKSPACE_CONTEXT } from '../../data-type/workspace/data-type-workspace.context.js';
import { UmbMultipleColorPickerItemInputElement } from './multiple-color-picker-item-input.element.js';
import type { UmbSwatchDetails } from '@umbraco-cms/backoffice/models';
import {
css,
html,
nothing,
repeat,
customElement,
property,
state,
ifDefined,
} from '@umbraco-cms/backoffice/external/lit';
import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui';
import { UmbInputEvent, UmbChangeEvent, UmbDeleteEvent } from '@umbraco-cms/backoffice/event';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UmbSorterConfig, UmbSorterController } from '@umbraco-cms/backoffice/sorter';
const SORTER_CONFIG: UmbSorterConfig<UmbSwatchDetails> = {
compareElementToModel: (element: HTMLElement, model: UmbSwatchDetails) => {
return element.getAttribute('data-sort-entry-id') === model.value;
},
querySelectModelToElement: (container: HTMLElement, modelEntry: UmbSwatchDetails) => {
return container.querySelector('data-sort-entry-id=[' + modelEntry.value + ']');
},
identifier: 'Umb.SorterIdentifier.ColorEditor',
itemSelector: 'umb-multiple-color-picker-item-input',
containerSelector: '#sorter-wrapper',
};
/**
* @element umb-multiple-color-picker-input
*/
@customElement('umb-multiple-color-picker-input')
export class UmbMultipleColorPickerInputElement extends FormControlMixin(UmbLitElement) {
#prevalueSorter = new UmbSorterController(this, {
...SORTER_CONFIG,
performItemInsert: (args) => {
const frozenArray = [...this.items];
const indexToMove = frozenArray.findIndex((x) => x.value === args.item.value);
frozenArray.splice(indexToMove, 1);
frozenArray.splice(args.newIndex, 0, args.item);
this.items = frozenArray;
this.dispatchEvent(new UmbChangeEvent());
return true;
},
performItemRemove: (args) => {
return true;
},
});
/**
* This is a minimum amount of selected items in this input.
* @type {number}
* @attr
* @default undefined
*/
@property({ type: Number })
min?: number;
/**
* Min validation message.
* @type {boolean}
* @attr
* @default
*/
@property({ type: String, attribute: 'min-message' })
minMessage = 'This field need more items';
/**
* This is a maximum amount of selected items in this input.
* @type {number}
* @attr
* @default undefined
*/
@property({ type: Number })
max?: number;
/**
* Max validation message.
* @type {boolean}
* @attr
* @default
*/
@property({ type: String, attribute: 'min-message' })
maxMessage = 'This field exceeds the allowed amount of items';
/**
* Disables the input
* @type {boolean}
* @attr
* @default false
*/
@property({ type: Boolean, reflect: true })
disabled = false;
/**
* Makes the input readonly
* @type {boolean}
* @attr
* @default false
*/
@property({ type: Boolean, reflect: true })
readonly = false;
@property({ type: Boolean })
showLabels = true;
constructor() {
super();
this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, (instance) => {
const workspace = instance;
this.observe(workspace.data, (data) => {
const property = data?.values.find((setting) => setting.alias === 'useLabel');
if (property) this.showLabels = property.value as boolean;
});
});
this.addValidator(
'rangeUnderflow',
() => this.minMessage,
() => !!this.min && this._items.length < this.min,
);
this.addValidator(
'rangeOverflow',
() => this.maxMessage,
() => !!this.max && this._items.length > this.max,
);
}
@state()
private _items: Array<UmbSwatchDetails> = [];
@property({ type: Array })
public get items(): Array<UmbSwatchDetails> {
return this._items;
}
public set items(items: Array<UmbSwatchDetails>) {
this._items = items ?? [];
this.#prevalueSorter.setModel(this.items);
}
#onAdd() {
this._items = [...this._items, { value: '', label: '' }];
this.pristine = false;
this.dispatchEvent(new UmbChangeEvent());
this.#focusNewItem();
}
#onChange(event: UmbInputEvent, currentIndex: number) {
event.stopPropagation();
const target = event.currentTarget as UmbMultipleColorPickerItemInputElement;
const value = target.value as string;
const label = target.label as string;
this.items = this._items.map((item, index) => (index === currentIndex ? { value, label } : item));
this.dispatchEvent(new UmbChangeEvent());
}
async #focusNewItem() {
await this.updateComplete;
const items = this.shadowRoot?.querySelectorAll(
'umb-multiple-color-picker-item-input',
) as NodeListOf<UmbMultipleColorPickerItemInputElement>;
const newItem = items[items.length - 1];
newItem.focus();
}
#deleteItem(event: UmbDeleteEvent, itemIndex: number) {
event.stopPropagation();
this._items = this._items.filter((item, index) => index !== itemIndex);
this.pristine = false;
this.dispatchEvent(new UmbChangeEvent());
}
protected getFormElement() {
return undefined;
}
render() {
return html`<div id="sorter-wrapper">${this.#renderItems()}</div>
${this.#renderAddButton()} `;
}
#renderItems() {
return html`
${repeat(
this._items,
(item) => item.value,
(item, index) =>
html` <umb-multiple-color-picker-item-input
?showLabels=${this.showLabels}
value=${item.value}
data-sort-entry-id=${item.value}
label=${ifDefined(item.label)}
name="item-${index}"
@change=${(event: UmbChangeEvent) => this.#onChange(event, index)}
@delete="${(event: UmbDeleteEvent) => this.#deleteItem(event, index)}"
?disabled=${this.disabled}
?readonly=${this.readonly}
required
required-message="Item ${index + 1} is missing a value"></umb-multiple-color-picker-item-input>`,
)}
`;
}
#renderAddButton() {
return html`
${this.disabled || this.readonly
? nothing
: html`<uui-button
id="action"
label=${this.localize.term('general_add')}
look="placeholder"
color="default"
@click="${this.#onAdd}"
?disabled=${this.disabled}></uui-button>`}
`;
}
static styles = [
css`
#action {
display: block;
}
.--umb-sorter-placeholder {
position: relative;
visibility: hidden;
}
.--umb-sorter-placeholder::after {
content: '';
position: absolute;
inset: 0px;
border-radius: var(--uui-border-radius);
border: 1px dashed var(--uui-color-divider-emphasis);
}
`,
];
}
export default UmbMultipleColorPickerInputElement;
declare global {
interface HTMLElementTagNameMap {
'umb-multiple-color-picker-input': UmbMultipleColorPickerInputElement;
}
}

View File

@@ -0,0 +1,231 @@
import { css, html, nothing, customElement, property, query, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import {
FormControlMixin,
UUIColorPickerElement,
UUIInputElement,
UUIInputEvent,
} from '@umbraco-cms/backoffice/external/uui';
import {
UmbModalManagerContext,
UMB_MODAL_MANAGER_CONTEXT_TOKEN,
UMB_CONFIRM_MODAL,
} from '@umbraco-cms/backoffice/modal';
import { UmbChangeEvent, UmbInputEvent, UmbDeleteEvent } from '@umbraco-cms/backoffice/event';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
/**
* @element umb-multiple-color-picker-item-input
*/
@customElement('umb-multiple-color-picker-item-input')
export class UmbMultipleColorPickerItemInputElement extends FormControlMixin(UmbLitElement) {
/**
* Disables the input
* @type {boolean}
* @attr
* @default false
*/
@property({ type: Boolean, reflect: true })
disabled = false;
/**
* Disables the input
* @type {boolean}
* @attr
* @default false
*/
@property({ type: Boolean, reflect: true })
readonly = false;
@property({ type: String })
label?: string;
@query('#input')
protected _input?: UUIInputElement;
@query('#color')
protected _colorPicker!: UUIColorPickerElement;
private _modalContext?: UmbModalManagerContext;
@property({ type: Boolean })
showLabels = true;
constructor() {
super();
this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => {
this._modalContext = instance;
});
}
#onDelete() {
const modalContext = this._modalContext?.open(UMB_CONFIRM_MODAL, {
data: {
headline: `${this.localize.term('actions_delete')} ${this.value || ''}`,
content: this.localize.term('content_nestedContentDeleteItem'),
color: 'danger',
confirmLabel: this.localize.term('actions_delete'),
}
});
modalContext?.onSubmit().then(() => {
this.dispatchEvent(new UmbDeleteEvent());
});
}
#onLabelInput(event: UUIInputEvent) {
event.stopPropagation();
this.label = event.target.value as string;
this.dispatchEvent(new UmbInputEvent());
}
#onLabelChange(event: UUIInputEvent) {
event.stopPropagation();
this.label = event.target.value as string;
this.dispatchEvent(new UmbChangeEvent());
}
#onValueChange(event: UUIInputEvent) {
event.stopPropagation();
this.value = event.target.value;
this.dispatchEvent(new UmbChangeEvent());
}
#onValueInput(event: UUIInputEvent) {
event.stopPropagation();
this.value = event.target.value;
this.dispatchEvent(new UmbInputEvent());
}
#onColorInput(event: InputEvent) {
event.stopPropagation();
this.value = this._colorPicker.value;
this.dispatchEvent(new UmbChangeEvent());
}
// Prevent valid events from bubbling outside the message element
#onValid(event: any) {
event.stopPropagation();
}
// Prevent invalid events from bubbling outside the message element
#onInvalid(event: any) {
event.stopPropagation();
}
public async focus() {
await this.updateComplete;
this._input?.focus();
}
protected getFormElement() {
return undefined;
}
#onColorClick() {
this._colorPicker.click();
}
render() {
//TODO: Using native input=color element instead of uui-color-picker due to its huge size and bad adaptability as a pop up
return html`
<uui-form-validation-message id="validation-message" @invalid=${this.#onInvalid} @valid=${this.#onValid}>
<div id="item">
${this.disabled || this.readonly ? nothing : html`<uui-icon name="icon-navigation"></uui-icon>`}
<div class="color-wrapper">
<uui-input
id="input"
value=${this.value}
label=${this.localize.term('general_value')}
placeholder=${this.localize.term('general_value')}
@input="${this.#onValueInput}"
@change="${this.#onValueChange}"
required="${this.required}"
required-message="Value is missing">
<uui-color-swatch
slot="prepend"
label=${this.value}
value="${this.value}"
@click=${this.#onColorClick}></uui-color-swatch>
</uui-input>
<input aria-hidden="${true}" type="color" id="color" value=${this.value} @input=${this.#onColorInput} />
</div>
${this.showLabels
? html` <uui-input
label=${this.localize.term('placeholders_label')}
placeholder=${this.localize.term('placeholders_label')}
value=${ifDefined(this.label)}
@input="${this.#onLabelInput}"
@change="${this.#onLabelChange}"
?disabled=${this.disabled}
?readonly=${this.readonly}></uui-input>`
: nothing}
${this.readonly
? nothing
: html`<uui-button
label="${this.localize.term('actions_delete')} ${this.value}"
look="primary"
color="danger"
@click="${this.#onDelete}"
?disabled=${this.disabled}
compact>
<uui-icon name="icon-trash"></uui-icon>
</uui-button>`}
</div>
</uui-form-validation-message>
`;
}
static styles = [
css`
:host {
display: flex;
align-items: center;
margin-bottom: var(--uui-size-space-3);
gap: var(--uui-size-space-3);
}
#item {
position: relative;
display: flex;
gap: var(--uui-size-1);
align-items: center;
}
uui-input {
flex: 1;
}
uui-color-swatch {
padding: var(--uui-size-1);
}
.color-wrapper {
position: relative;
flex: 1;
display: flex;
flex-direction: column;
}
uui-input,
#validation-message {
flex: 1;
}
input[type='color'] {
visibility: hidden;
width: 0px;
padding: 0;
margin: 0;
position: absolute;
}
`,
];
}
export default UmbMultipleColorPickerItemInputElement;
declare global {
interface HTMLElementTagNameMap {
'umb-multiple-color-picker-item-input': UmbMultipleColorPickerItemInputElement;
}
}

View File

@@ -19,7 +19,7 @@ export const manifest: ManifestPropertyEditorSchema = {
alias: 'items',
label: 'Colors',
description: 'Add, remove or sort colors',
propertyEditorUiAlias: 'Umb.PropertyEditorUi.ColorPicker',
propertyEditorUiAlias: 'Umb.PropertyEditorUi.ColorEditor',
},
],
},

View File

@@ -0,0 +1,13 @@
import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension-registry';
export const manifest: ManifestPropertyEditorUi = {
type: 'propertyEditorUi',
alias: 'Umb.PropertyEditorUi.ColorEditor',
name: 'Color Editor Property Editor UI',
js: () => import('./property-editor-ui-color-editor.element.js'),
meta: {
label: 'Color Editor',
icon: 'icon-page-add',
group: 'Umbraco.DropDown.Flexible',
},
};

View File

@@ -0,0 +1,46 @@
import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import type { UmbSwatchDetails } from '@umbraco-cms/backoffice/models';
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
import { UmbMultipleColorPickerInputElement } from '@umbraco-cms/backoffice/components';
/**
* @element umb-property-editor-ui-color-editor
*/
@customElement('umb-property-editor-ui-color-editor')
export class UmbPropertyEditorUIColorEditorElement extends UmbLitElement implements UmbPropertyEditorUiElement {
#defaultShowLabels = true;
@property({ type: Array })
value: Array<UmbSwatchDetails> = [];
@state()
private _showLabels = this.#defaultShowLabels;
@property({ attribute: false })
public set config(config: UmbPropertyEditorConfigCollection | undefined) {
this._showLabels = config?.getValueByAlias('useLabel') ?? this.#defaultShowLabels;
this.value = config?.getValueByAlias('items') ?? [];
}
#onChange(event: CustomEvent) {
this.value = (event.target as UmbMultipleColorPickerInputElement).items;
this.dispatchEvent(new CustomEvent('property-value-change'));
}
render() {
return html`<umb-multiple-color-picker-input
?showLabels=${this._showLabels}
.items="${this.value ?? []}"
@change=${this.#onChange}></umb-multiple-color-picker-input>`;
}
}
export default UmbPropertyEditorUIColorEditorElement;
declare global {
interface HTMLElementTagNameMap {
'umb-property-editor-ui-color-editor': UmbPropertyEditorUIColorEditorElement;
}
}

View File

@@ -103,17 +103,17 @@ export class UmbPropertyEditorUIImageCropsConfigurationElement
<form @submit=${this.#onSubmit}>
<div class="input">
<uui-label for="alias">Alias</uui-label>
<uui-input id="alias" name="alias" type="text" autocomplete="false" value=""></uui-input>
<uui-input label="Alias" id="alias" name="alias" type="text" autocomplete="false" value=""></uui-input>
</div>
<div class="input">
<uui-label for="width">Width</uui-label>
<uui-input id="width" name="width" type="number" autocomplete="false" value="">
<uui-input label="Width" id="width" name="width" type="number" autocomplete="false" value="">
<span class="append" slot="append">px</span>
</uui-input>
</div>
<div class="input">
<uui-label for="height">Height</uui-label>
<uui-input id="height" name="height" type="number" autocomplete="false" value="">
<uui-input label="Height" id="height" name="height" type="number" autocomplete="false" value="">
<span class="append" slot="append">px</span>
</uui-input>
</div>
@@ -130,8 +130,8 @@ export class UmbPropertyEditorUIImageCropsConfigurationElement
<span class="crop-alias">${item.alias}</span>
<span class="crop-size">(${item.width} x ${item.height}px)</span>
<div class="crop-actions">
<uui-button @click=${() => this.#onEdit(item)}>Edit</uui-button>
<uui-button color="danger" @click=${() => this.#onRemove(item.alias)}>Remove</uui-button>
<uui-button label="Edit" @click=${() => this.#onEdit(item)}>Edit</uui-button>
<uui-button label="Remove" color="danger" @click=${() => this.#onRemove(item.alias)}>Remove</uui-button>
</div>
</div>
`,

View File

@@ -1,4 +1,5 @@
import { manifest as colorPicker } from './color-picker/manifests.js';
import { manifest as colorEditor } from './color-editor/manifests.js';
import { manifest as datePicker } from './date-picker/manifests.js';
import { manifest as eyeDropper } from './eye-dropper/manifests.js';
import { manifest as multiUrlPicker } from './multi-url-picker/manifests.js';
@@ -34,6 +35,7 @@ import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension
export const manifests: Array<ManifestPropertyEditorUi> = [
colorPicker,
colorEditor,
datePicker,
eyeDropper,
multiUrlPicker,

View File

@@ -15,7 +15,7 @@ export class UmbPropertyEditorUITinyMceMaxImageSizeConfigurationElement
value: number = 0;
render() {
return html`<uui-input type="number" placeholder="Max size" .value=${this.value}></uui-input>`;
return html`<uui-input label="Max size" type="number" placeholder="Max size" .value=${this.value}></uui-input>`;
}
static styles = [UmbTextStyles];

View File

@@ -691,6 +691,7 @@ export class UmbSorterController<T> implements UmbController {
if (movingItemIndex !== -1 && movingItemIndex <= movingItemIndex) {
newIndex--;
}
if (nextEl) {
// We had a reference element, we want to get the index of it.
// This is might a problem if a item is being moved forward? (was also like this in the AngularJS version...)

View File

@@ -39,6 +39,14 @@ export class UmbVariantId {
return this.segment || '';
}
public isCultureInvariant(): boolean {
return this.culture === null;
}
public isSegmentInvariant(): boolean {
return this.segment === null;
}
public isInvariant(): boolean {
return this.culture === null && this.segment === null;
}

View File

@@ -219,31 +219,12 @@ export class UmbDocumentRepository
return { error };
}
async saveAndPublish(id: string, item: UpdateDocumentRequestModel, variantIds: Array<UmbVariantId>) {
if (!id) throw new Error('id is missing');
if (!variantIds) throw new Error('variant IDs are missing');
//await this.#init;
await this.save(id, item);
const { error } = await this.#detailDataSource.saveAndPublish(id, variantIds);
if (!error) {
// TODO: Update other stores based on above effect.
const notification = { data: { message: `Document saved and published` } };
this.#notificationContext?.peek('positive', notification);
}
return { error };
}
async publish(id: string, variantIds: Array<UmbVariantId>) {
if (!id) throw new Error('id is missing');
if (!variantIds) throw new Error('variant IDs are missing');
await this.#init;
const { error } = await this.#detailDataSource.saveAndPublish(id, variantIds);
const { error } = await this.#detailDataSource.publish(id, variantIds);
if (!error) {
// TODO: Update other stores based on above effect.

View File

@@ -124,12 +124,14 @@ export class UmbDocumentServerDataSource
* @return {*}
* @memberof UmbDocumentServerDataSource
*/
async saveAndPublish(id: string, variantIds: Array<UmbVariantId>) {
async publish(id: string, variantIds: Array<UmbVariantId>) {
if (!id) throw new Error('Id is missing');
// TODO: THIS DOES NOT TAKE SEGMENTS INTO ACCOUNT!!!!!!
const requestBody: PublishDocumentRequestModel = {
cultures: variantIds.map((variant) => variant.toCultureString()),
cultures: variantIds
.map((variant) => (variant.isCultureInvariant() ? null : variant.toCultureString()))
.filter((x) => x !== null) as Array<string>,
};
return tryExecuteAndNotify(this.#host, DocumentResource.putDocumentByIdPublish({ id, requestBody }));

View File

@@ -14,6 +14,6 @@ export class UmbDocumentSaveAndPublishWorkspaceAction extends UmbWorkspaceAction
//const document = this.workspaceContext.getData();
// TODO: handle errors
//if (!document) return;
this.workspaceContext.publish();
this.workspaceContext.saveAndPublish();
}
}

View File

@@ -187,9 +187,8 @@ export class UmbDocumentWorkspaceContext
}
}
async save() {
if (!this.#currentData.value) return;
if (!this.#currentData.value.id) return;
async #createOrSave() {
if (!this.#currentData.value?.id) throw new Error('Id is missing');
if (this.getIsNew()) {
// TODO: typescript hack until we get the create type
@@ -200,6 +199,10 @@ export class UmbDocumentWorkspaceContext
} else {
await this.repository.save(this.#currentData.value.id, this.#currentData.value);
}
}
async save() {
await this.#createOrSave();
this.saveComplete(this.getData());
}
@@ -211,6 +214,19 @@ export class UmbDocumentWorkspaceContext
}
}
public async saveAndPublish() {
await this.#createOrSave();
// TODO: This might be right to publish all, but we need a method that just saves and publishes a declared range of variants.
const currentData = this.#currentData.value;
if (currentData) {
const variantIds = currentData.variants?.map((x) => UmbVariantId.Create(x));
const id = currentData.id;
if (variantIds && id) {
await this.repository.publish(id, variantIds);
}
}
}
public async publish() {
// TODO: This might be right to publish all, but we need a method that just publishes a declared range of variants.
const currentData = this.#currentData.value;
@@ -223,18 +239,6 @@ export class UmbDocumentWorkspaceContext
}
}
public async saveAndPublish() {
// TODO: This might be right to publish all, but we need a method that just saves and publishes a declared range of variants.
const currentData = this.#currentData.value;
if (currentData) {
const variantIds = currentData.variants?.map((x) => UmbVariantId.Create(x));
const id = currentData.id;
if (variantIds && id) {
await this.repository.saveAndPublish(id, currentData, variantIds);
}
}
}
public async unpublish() {
// TODO: This might be right to unpublish all, but we need a method that just publishes a declared range of variants.
const currentData = this.#currentData.value;