Skip to content

Commit cee7305

Browse files
committed
Merge branch 'main' into v17/dev
# Conflicts: # src/Umbraco.Web.UI.Client/src/packages/content/property-type/workspace/views/settings/property-workspace-view-settings.element.ts
2 parents d9cdf03 + f33eb3f commit cee7305

File tree

6 files changed

+71
-23
lines changed

6 files changed

+71
-23
lines changed

.github/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ Some important documentation links to get you started:
3838
- [Getting to know Umbraco](https://docs.umbraco.com/umbraco-cms/fundamentals/get-to-know-umbraco)
3939
- [Tutorials for creating a basic website and customizing the editing experience](https://docs.umbraco.com/umbraco-cms/tutorials/overview)
4040

41+
## Backoffice Preview
42+
43+
Want to see the latest backoffice UI in action? Check out our live preview:
44+
45+
**[backofficepreview.umbraco.com](https://backofficepreview.umbraco.com/)**
46+
47+
This preview is automatically deployed from the main branch and showcases the latest backoffice features and improvements. It runs from mock data and persistent edits are not supported.
48+
4149
## Get help
4250

4351
If you need a bit of feedback while building your Umbraco projects, we are [chatty on Discord](https://discord.umbraco.com). Our Discord server serves as a social space for all Umbracians. If you have any questions or need some help with a problem, head over to our [dedicated forum](https://forum.umbraco.com/) where the Umbraco Community will be happy to help.

src/Umbraco.Core/Services/ContentTypeEditing/MediaTypeEditingService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ private async Task<IDictionary<IMediaType, IEnumerable<string>>> FetchAllowedFil
175175
continue;
176176
}
177177

178-
allowedFileExtensionsByMediaType[mediaType] = fileUploadConfiguration.FileExtensions;
178+
allowedFileExtensionsByMediaType[mediaType] = fileUploadConfiguration.FileExtensions ?? []; // Although we never expect null here, legacy data type configuration did allow it.
179179
}
180180

181181
return allowedFileExtensionsByMediaType;

src/Umbraco.Web.UI.Client/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
This package contains the types for the Umbraco Backoffice.
44

5+
## Preview
6+
7+
A live preview of the latest backoffice build from the main branch is available at:
8+
9+
**[backofficepreview.umbraco.com](https://backofficepreview.umbraco.com/)**
10+
11+
This preview is automatically deployed via GitHub Actions whenever changes are pushed to main or version branches.
12+
513
## Installation
614

715
```bash

src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.element.ts

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ export class UmbIconPickerModalElement extends UmbModalBaseElement<UmbIconPicker
3030
@state()
3131
private _colorList = umbracoColors.filter((color) => !color.legacy);
3232

33+
@state()
34+
private _isSearching = false;
35+
3336
constructor() {
3437
super();
3538
this.consumeContext(UMB_ICON_REGISTRY_CONTEXT, (context) => {
@@ -44,8 +47,10 @@ export class UmbIconPickerModalElement extends UmbModalBaseElement<UmbIconPicker
4447
if (!this.#icons) return;
4548
const value = this._searchInput?.value;
4649
if (value) {
50+
this._isSearching = value.length > 0;
4751
this._iconsFiltered = this.#icons.filter((icon) => icon.name.toLowerCase().includes(value.toLowerCase()));
4852
} else {
53+
this._isSearching = false;
4954
this._iconsFiltered = this.#icons;
5055
}
5156
}
@@ -54,8 +59,12 @@ export class UmbIconPickerModalElement extends UmbModalBaseElement<UmbIconPicker
5459
const isActivate = e.type === 'click' || (e.type === 'keyup' && (e as KeyboardEvent).key === 'Enter');
5560
if (!isActivate) return;
5661

57-
const nextIcon = this.value.icon === iconName ? '' : iconName;
58-
this.modalContext?.updateValue({ icon: nextIcon });
62+
if (this.data?.showEmptyOption) {
63+
const nextIcon = this.value.icon === iconName ? '' : iconName;
64+
this.modalContext?.updateValue({ icon: nextIcon });
65+
} else {
66+
this.modalContext?.updateValue({ icon: iconName });
67+
}
5968
}
6069

6170
#onColorChange(e: UUIColorSwatchesEvent) {
@@ -93,16 +102,21 @@ export class UmbIconPickerModalElement extends UmbModalBaseElement<UmbIconPicker
93102
</uui-color-swatches>
94103
<hr />
95104
<uui-scroll-container id="icons">
96-
<uui-button
97-
class=${!this.value.icon ? 'selected' : ''}
98-
label=${this.localize.term('defaultdialogs_noIcon')}
99-
title=${this.localize.term('defaultdialogs_noIcon')}
100-
@click=${this.#clearIcon}
101-
@keyup=${(e: KeyboardEvent) => {
102-
if (e.key === 'Enter' || e.key === ' ') this.#clearIcon();
103-
}}>
104-
<uui-icon style="opacity:.35" name=${ifDefined(this.data?.placeholder)}></uui-icon> </uui-button
105-
>${this.renderIcons()}</uui-scroll-container
105+
${this.data?.showEmptyOption && !this._isSearching
106+
? html`
107+
<uui-button
108+
class=${!this.value.icon ? 'selected' : ''}
109+
label=${this.localize.term('defaultdialogs_noIcon')}
110+
title=${this.localize.term('defaultdialogs_noIcon')}
111+
@click=${this.#clearIcon}
112+
@keyup=${(e: KeyboardEvent) => {
113+
if (e.key === 'Enter' || e.key === ' ') this.#clearIcon();
114+
}}>
115+
<uui-icon style="opacity:.35" name=${ifDefined(this.data?.placeholder)}></uui-icon>
116+
</uui-button>
117+
`
118+
: nothing}
119+
${this.renderIcons()}</uui-scroll-container
106120
>
107121
</div>
108122
<uui-button

src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.token.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
22

33
export interface UmbIconPickerModalData {
44
placeholder?: string;
5+
showEmptyOption?: boolean;
56
}
67

78
export interface UmbIconPickerModalValue {

src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.element.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,45 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
99
import { extractUmbColorVariable } from '@umbraco-cms/backoffice/resources';
1010
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
1111

12+
import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
13+
1214
/**
1315
* @element umb-property-editor-ui-icon-picker
1416
*/
1517
@customElement('umb-property-editor-ui-icon-picker')
16-
export class UmbPropertyEditorUIIconPickerElement extends UmbLitElement implements UmbPropertyEditorUiElement {
17-
//
18+
export class UmbPropertyEditorUIIconPickerElement
19+
extends UmbFormControlMixin<string, typeof UmbLitElement, undefined>(UmbLitElement, undefined)
20+
implements UmbPropertyEditorUiElement
21+
{
22+
@property({ type: Boolean })
23+
mandatory = false;
24+
25+
protected override firstUpdated(): void {
26+
this.addValidator(
27+
'valueMissing',
28+
() => 'Icon is required',
29+
() => this.mandatory && !this._icon,
30+
);
31+
}
32+
1833
@property()
19-
public set value(v: string) {
20-
this._value = v ?? '';
21-
const parts = this._value.split(' ');
34+
public override set value(v: string) {
35+
const val = v ?? '';
36+
super.value = val;
37+
38+
const parts = val.split(' ');
2239
if (parts.length === 2) {
2340
this._icon = parts[0];
2441
this._color = parts[1].replace('color-', '');
2542
} else {
26-
this._icon = this._value;
43+
this._icon = val;
2744
this._color = '';
2845
}
2946
}
30-
public get value() {
31-
return this._value;
47+
48+
public override get value() {
49+
return (super.value as string) ?? '';
3250
}
33-
private _value = '';
3451

3552
@state()
3653
private _icon = '';
@@ -53,7 +70,7 @@ export class UmbPropertyEditorUIIconPickerElement extends UmbLitElement implemen
5370
icon: this._icon,
5471
color: this._color,
5572
},
56-
data: { placeholder: this._placeholderIcon },
73+
data: { placeholder: this._placeholderIcon, showEmptyOption: !this.mandatory },
5774
}).catch(() => undefined);
5875

5976
if (!data) return;

0 commit comments

Comments
 (0)