Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ import { UmbMemberGroupPickerInputContext } from './input-member-group.context.j
import { css, customElement, html, nothing, property, repeat, state, when } from '@umbraco-cms/backoffice/external/lit';
import { splitStringToArray } from '@umbraco-cms/backoffice/utils';
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router';
import { UmbSorterController } from '@umbraco-cms/backoffice/sorter';
import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace';
import { UMB_VALIDATION_EMPTY_LOCALIZATION_KEY, UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
import type { UmbRepositoryItemsStatus } from '@umbraco-cms/backoffice/repository';

import '@umbraco-cms/backoffice/entity-item';

@customElement('umb-input-member-group')
export class UmbInputMemberGroupElement extends UmbFormControlMixin<string | undefined, typeof UmbLitElement>(
export class UmbInputMemberGroupElement extends UmbFormControlMixin<string, typeof UmbLitElement>(
UmbLitElement,
undefined,
) {
#sorter = new UmbSorterController<string>(this, {
getUniqueOfElement: (element) => {
Expand Down Expand Up @@ -53,7 +53,7 @@ export class UmbInputMemberGroupElement extends UmbFormControlMixin<string | und
* @default
*/
@property({ type: String, attribute: 'min-message' })
minMessage = 'This field need more items';
minMessage = 'This field needs more items';

/**
* This is a maximum amount of selected items in this input.
Expand All @@ -75,7 +75,7 @@ export class UmbInputMemberGroupElement extends UmbFormControlMixin<string | und
* @attr
* @default
*/
@property({ type: String, attribute: 'min-message' })
@property({ type: String, attribute: 'max-message' })
maxMessage = 'This field exceeds the allowed amount of items';

public set selection(ids: Array<string>) {
Expand All @@ -92,6 +92,7 @@ export class UmbInputMemberGroupElement extends UmbFormControlMixin<string | und
@property({ type: String })
public override set value(selectionString: string | undefined) {
this.selection = splitStringToArray(selectionString);
super.value = selectionString;
}
public override get value(): string | undefined {
return this.selection.length > 0 ? this.selection.join(',') : undefined;
Expand Down Expand Up @@ -121,6 +122,15 @@ export class UmbInputMemberGroupElement extends UmbFormControlMixin<string | und
}
#readonly = false;

/**
* Sets the input to required, meaning validation will fail if the value is empty.
* @type {boolean}
*/
@property({ type: Boolean })
required?: boolean;
@property({ type: String })
requiredMessage?: string;

@state()
private _editMemberGroupPath = '';

Expand All @@ -144,6 +154,12 @@ export class UmbInputMemberGroupElement extends UmbFormControlMixin<string | und
this._editMemberGroupPath = routeBuilder({});
});

this.addValidator(
'valueMissing',
() => this.requiredMessage ?? UMB_VALIDATION_EMPTY_LOCALIZATION_KEY,
() => !this.readonly && !!this.required && (this.value === undefined || this.value === null || this.value === ''),
);

this.addValidator(
'rangeUnderflow',
() => this.minMessage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ import type {
UmbPropertyEditorUiElement,
} from '@umbraco-cms/backoffice/property-editor';
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
import { UMB_VALIDATION_EMPTY_LOCALIZATION_KEY, UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';

/**
* @element umb-property-editor-ui-member-group-picker
*/
@customElement('umb-property-editor-ui-member-group-picker')
export class UmbPropertyEditorUIMemberGroupPickerElement extends UmbLitElement implements UmbPropertyEditorUiElement {
@property()
public value?: string;

export class UmbPropertyEditorUIMemberGroupPickerElement
extends UmbFormControlMixin<string, typeof UmbLitElement, undefined>(UmbLitElement, undefined)
implements UmbPropertyEditorUiElement
{
public set config(config: UmbPropertyEditorConfigCollection | undefined) {
if (!config) return;

Expand All @@ -32,6 +33,14 @@ export class UmbPropertyEditorUIMemberGroupPickerElement extends UmbLitElement i
*/
@property({ type: Boolean, reflect: true })
readonly = false;
@property({ type: Boolean })
mandatory?: boolean;
@property({ type: String })
mandatoryMessage = UMB_VALIDATION_EMPTY_LOCALIZATION_KEY;

protected override firstUpdated() {
this.addFormControlElement(this.shadowRoot!.querySelector('umb-input-member-group')!);
}

@state()
private _min = 0;
Expand All @@ -51,6 +60,8 @@ export class UmbPropertyEditorUIMemberGroupPickerElement extends UmbLitElement i
.max=${this._max}
.value=${this.value}
@change=${this.#onChange}
?required=${this.mandatory}
.requiredMessage=${this.mandatoryMessage}
?readonly=${this.readonly}></umb-input-member-group>
`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ import { UmbMemberPickerInputContext } from './input-member.context.js';
import { css, customElement, html, nothing, property, repeat, state, when } from '@umbraco-cms/backoffice/external/lit';
import { splitStringToArray } from '@umbraco-cms/backoffice/utils';
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
import { UMB_VALIDATION_EMPTY_LOCALIZATION_KEY, UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbSorterController } from '@umbraco-cms/backoffice/sorter';
import { UMB_MEMBER_TYPE_ENTITY_TYPE } from '@umbraco-cms/backoffice/member-type';
import type { UmbRepositoryItemsStatus } from '@umbraco-cms/backoffice/repository';

@customElement('umb-input-member')
export class UmbInputMemberElement extends UmbFormControlMixin<string | undefined, typeof UmbLitElement>(
export class UmbInputMemberElement extends UmbFormControlMixin<string, typeof UmbLitElement, undefined>(
UmbLitElement,
undefined,
) {
#sorter = new UmbSorterController<string>(this, {
getUniqueOfElement: (element) => {
Expand Down Expand Up @@ -50,7 +51,7 @@ export class UmbInputMemberElement extends UmbFormControlMixin<string | undefine
* @default
*/
@property({ type: String, attribute: 'min-message' })
minMessage = 'This field need more items';
minMessage = 'This field needs more items';

/**
* This is a maximum amount of selected items in this input.
Expand Down Expand Up @@ -119,6 +120,15 @@ export class UmbInputMemberElement extends UmbFormControlMixin<string | undefine
}
#readonly = false;

/**
* Sets the input to required, meaning validation will fail if the value is empty.
* @type {boolean}
*/
@property({ type: Boolean })
required?: boolean;
@property({ type: String })
requiredMessage?: string;

@state()
private _items?: Array<UmbMemberItemModel>;

Expand All @@ -130,6 +140,12 @@ export class UmbInputMemberElement extends UmbFormControlMixin<string | undefine
constructor() {
super();

this.addValidator(
'valueMissing',
() => this.requiredMessage ?? UMB_VALIDATION_EMPTY_LOCALIZATION_KEY,
() => !this.readonly && !!this.required && (this.value === undefined || this.value === null || this.value === ''),
);

this.addValidator(
'rangeUnderflow',
() => this.minMessage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ import type {
UmbPropertyEditorUiElement,
} from '@umbraco-cms/backoffice/property-editor';
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
import { UMB_VALIDATION_EMPTY_LOCALIZATION_KEY, UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';

/**
* @element umb-property-editor-ui-member-picker
*/
@customElement('umb-property-editor-ui-member-picker')
export class UmbPropertyEditorUIMemberPickerElement extends UmbLitElement implements UmbPropertyEditorUiElement {
@property()
public value?: string;

export class UmbPropertyEditorUIMemberPickerElement
extends UmbFormControlMixin<string, typeof UmbLitElement, undefined>(UmbLitElement, undefined)
implements UmbPropertyEditorUiElement
{
@property({ attribute: false })
public config?: UmbPropertyEditorConfigCollection;

Expand All @@ -26,6 +27,14 @@ export class UmbPropertyEditorUIMemberPickerElement extends UmbLitElement implem
*/
@property({ type: Boolean, reflect: true })
readonly = false;
@property({ type: Boolean })
mandatory?: boolean;
@property({ type: String })
mandatoryMessage = UMB_VALIDATION_EMPTY_LOCALIZATION_KEY;

protected override firstUpdated() {
this.addFormControlElement(this.shadowRoot!.querySelector('umb-input-member')!);
}

#onChange(event: CustomEvent & { target: UmbInputMemberElement }) {
this.value = event.target.value;
Expand All @@ -38,6 +47,8 @@ export class UmbPropertyEditorUIMemberPickerElement extends UmbLitElement implem
max="1"
.value=${this.value}
@change=${this.#onChange}
?required=${this.mandatory}
.requiredMessage=${this.mandatoryMessage}
?readonly=${this.readonly}></umb-input-member>`;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import { splitStringToArray } from '@umbraco-cms/backoffice/utils';
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbSorterController } from '@umbraco-cms/backoffice/sorter';
import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui';
import { UMB_VALIDATION_EMPTY_LOCALIZATION_KEY, UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
import type { UmbRepositoryItemsStatus } from '@umbraco-cms/backoffice/repository';

// TODO: Shall we rename to 'umb-input-user'? [LK]
@customElement('umb-user-input')
export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '') {
export class UmbUserInputElement extends UmbFormControlMixin<string, typeof UmbLitElement, undefined>(
UmbLitElement,
undefined,
) {
#sorter = new UmbSorterController<string>(this, {
getUniqueOfElement: (element) => {
return element.id;
Expand All @@ -27,6 +30,25 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '')
},
});

/**
* Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content.
* @type {boolean}
* @attr
* @default false
*/
@property({ type: Boolean, reflect: true })
readonly = false;

/**
* Sets the input to required, meaning validation will fail if the value is empty.
* @type {boolean}
*/
@property({ type: Boolean })
required?: boolean;

@property({ type: String })
requiredMessage?: string;

/**
* This is a minimum amount of selected items in this input.
* @type {number}
Expand All @@ -48,7 +70,7 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '')
* @default
*/
@property({ type: String, attribute: 'min-message' })
minMessage = 'This field need more items';
minMessage = 'This field needs more items';

/**
* This is a maximum amount of selected items in this input.
Expand All @@ -70,7 +92,7 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '')
* @attr
* @default
*/
@property({ type: String, attribute: 'min-message' })
@property({ type: String, attribute: 'max-message' })
maxMessage = 'This field exceeds the allowed amount of items';

@property({ type: Array })
Expand All @@ -83,10 +105,10 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '')
}

@property()
public override set value(uniques: string) {
public override set value(uniques: string | undefined) {
this.selection = splitStringToArray(uniques);
}
public override get value(): string {
public override get value(): string | undefined {
return this.selection.join(',');
}

Expand All @@ -101,6 +123,12 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '')
constructor() {
super();

this.addValidator(
'valueMissing',
() => this.requiredMessage ?? UMB_VALIDATION_EMPTY_LOCALIZATION_KEY,
() => !this.readonly && !!this.required && (this.value === undefined || this.value === null || this.value === ''),
);

this.addValidator(
'rangeUnderflow',
() => this.minMessage,
Expand Down Expand Up @@ -141,7 +169,8 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '')
id="btn-add"
look="placeholder"
label=${this.localize.term('general_choose')}
@click=${this.#openPicker}></uui-button>
@click=${this.#openPicker}
?disabled=${this.readonly}></uui-button>
`;
}

Expand All @@ -163,19 +192,20 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '')
const item = this._items?.find((x) => x.unique === unique);
const isError = status.state.type === 'error';
return html`
<umb-entity-item-ref
id=${unique}
.item=${item}
?error=${isError}
.errorMessage=${status.state.error}
.errorDetail=${isError ? unique : undefined}
?standalone=${this.max === 1}>
<uui-action-bar slot="actions">
<uui-button
label=${this.localize.term('general_remove')}
@click=${() => this.#removeItem(unique)}></uui-button>
</uui-action-bar>
</umb-entity-item-ref>
<umb-entity-item-ref
id=${unique}
.item=${item}
?error=${isError}
.errorMessage=${status.state.error}
.errorDetail=${isError ? unique : undefined}
?standalone=${this.max === 1}
?readonly=${this.readonly}>
<uui-action-bar slot="actions">
<uui-button
label=${this.localize.term('general_remove')}
@click=${() => this.#removeItem(unique)}></uui-button>
</uui-action-bar>
</umb-entity-item-ref>
`;
}

Expand Down
Loading
Loading