${this.renderSearch()}
${
// TODO: Missing localization for the color aliases. [NL]
@@ -101,7 +92,18 @@ export class UmbIconPickerModalElement extends UmbModalBaseElement
- ${this.renderIcons()}
+
+ {
+ if (e.key === 'Enter' || e.key === ' ') this.#clearIcon();
+ }}>
+ ${this.renderIcons()}
this.#changeIcon(e, icon.name)}
@keyup=${(e: KeyboardEvent) => this.#changeIcon(e, icon.name)}>
`,
@@ -199,7 +201,7 @@ export class UmbIconPickerModalElement extends UmbModalBaseElement =
...entityActionManifests,
...entityBulkActionManifests,
...entityManifests,
+ ...entitySignManifests,
...extensionManifests,
...iconRegistryManifests,
...localizationManifests,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/extractUmbColorVariable.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/extractUmbColorVariable.function.ts
index 56120d2c8e..2db31e0259 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/extractUmbColorVariable.function.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/extractUmbColorVariable.function.ts
@@ -1,3 +1,5 @@
+// TODO: This does not belong here, lets move it to the icon package.
+
export const umbracoColors = [
{ alias: 'text', varName: '--uui-color-text' },
{ alias: 'yellow', varName: '--uui-palette-sunglow' },
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-element-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-element-base.ts
index dcccd76ed5..eae3d64977 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-element-base.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-element-base.ts
@@ -7,10 +7,13 @@ import {
state,
repeat,
property,
+ css,
type TemplateResult,
} from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UUIMenuItemEvent } from '@umbraco-cms/backoffice/external/uui';
+import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
+import type { UmbEntityFlag } from '@umbraco-cms/backoffice/entity-flag';
export abstract class UmbTreeItemElementBase<
TreeItemModelType extends UmbTreeItemModel,
@@ -19,6 +22,7 @@ export abstract class UmbTreeItemElementBase<
@property({ type: Object, attribute: false })
set item(newVal: TreeItemModelType) {
this._item = newVal;
+ this._extractFlags(newVal);
if (this._item) {
this._label = this.localize.string(this._item?.name ?? '');
@@ -30,6 +34,18 @@ export abstract class UmbTreeItemElementBase<
}
protected _item?: TreeItemModelType;
+ /**
+ * @param item - The item from which to extract flags.
+ * @description This method is called whenever the `item` property is set. It extracts the flags from the item and assigns them to the `_flags` state property.
+ * This method is in some cases overridden in subclasses to customize how flags are extracted!
+ */
+ protected _extractFlags(item: TreeItemModelType | undefined) {
+ this._flags = item?.flags ?? [];
+ }
+
+ @state()
+ protected _flags?: Array;
+
@state()
private _label?: string;
@@ -212,32 +228,41 @@ export abstract class UmbTreeItemElementBase<
renderIconContainer() {
return html`
- {
- this._iconSlotHasChildren = this.#hasNodes(e);
- }}>
- ${!this._iconSlotHasChildren ? this.#renderIcon() : nothing}
+
+ {
+ this._iconSlotHasChildren = this.#hasNodes(e);
+ }}>
+ ${this.#renderSigns()}
+
`;
}
// eslint-disable-next-line @typescript-eslint/naming-convention
_renderExpandSymbol?: () => HTMLElement | TemplateResult<1> | undefined;
+ #renderSigns() {
+ return this._item
+ ? html`${!this._iconSlotHasChildren ? this.#renderIcon() : nothing}`
+ : nothing;
+ }
+
#renderIcon() {
- const icon = this._item?.icon;
+ const iconName = this._getIconName();
const isFolder = this._item?.isFolder;
- if (icon) {
- return html``;
+ if (iconName) {
+ return html``;
}
if (isFolder) {
- return html``;
+ return html``;
}
- return html``;
+ return html``;
}
protected _getIconToRender(icon: string) {
@@ -245,6 +270,10 @@ export abstract class UmbTreeItemElementBase<
return this._isActive || this._isSelected ? iconWithoutColor : icon;
}
+ protected _getIconName(): string | null | undefined {
+ return this._item?.icon;
+ }
+
renderLabel() {
return html``;
}
@@ -293,4 +322,38 @@ export abstract class UmbTreeItemElementBase<
.loading=${this._isLoadingNextChildren}>
`;
}
+
+ static override styles = [
+ UmbTextStyles,
+ css`
+ #icon-container {
+ position: relative;
+ font-size: 15px;
+ }
+
+ uui-menu-item {
+ --umb-sign-bundle-bg: var(--uui-color-surface);
+ }
+
+ uui-menu-item:hover {
+ --umb-sign-bundle-bg: var(--uui-color-surface-emphasis);
+ }
+
+ uui-menu-item[active],
+ uui-menu-item[selected] {
+ --umb-sign-bundle-bg: var(--uui-color-current);
+ }
+
+ uui-menu-item[selected]:hover,
+ uui-menu-item[active]:hover {
+ --umb-sign-bundle-bg: var(--uui-color-current-emphasis);
+ }
+
+ #label {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ `,
+ ];
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/types.ts
index 16a9c910a9..3a4fc49120 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/types.ts
@@ -1,11 +1,12 @@
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
+import type { UmbEntityWithOptionalFlags } from '@umbraco-cms/backoffice/entity-flag';
export type * from './entity-actions/types.js';
export type * from './extensions/types.js';
export type * from './folder/types.js';
export type * from './tree-menu-item/types.js';
-export interface UmbTreeItemModelBase extends UmbEntityModel {
+export interface UmbTreeItemModelBase extends UmbEntityWithOptionalFlags {
name: string;
hasChildren: boolean;
isFolder: boolean;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts
index e119531113..c37eb0e501 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts
@@ -3,6 +3,7 @@ import type { UmbVariantId } from './variant-id.class.js';
import type { UmbLanguageDetailModel } from '@umbraco-cms/backoffice/language';
import type { ScheduleRequestModel } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbPropertyValueData } from '@umbraco-cms/backoffice/property';
+import type { UmbEntityFlag } from '@umbraco-cms/backoffice/entity-flag';
export type UmbObjectWithVariantProperties = {
culture: string | null;
@@ -22,7 +23,9 @@ export interface UmbEntityVariantModel {
segment: string | null;
createDate: string | null;
updateDate: string | null;
+ // TODO: Can we remove partial from this one: [NL]
state?: string | null;
+ flags: Array;
}
/** @deprecated use `UmbEntityVariantModel` instead */
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts b/src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts
index 0cc97b1c69..b77da682d3 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts
@@ -26,7 +26,9 @@ export default defineConfig({
'entity-action/index': './entity-action/index.ts',
'entity-bulk-action/index': './entity-bulk-action/index.ts',
'entity-create-option-action/index': './entity-create-option-action/index.ts',
+ 'entity-flag/index': './entity-flag/index.ts',
'entity-item/index': './entity-item/index.ts',
+ 'entity-sign/index': './entity-sign/index.ts',
'entity/index': './entity/index.ts',
'entry-point': 'entry-point.ts',
'event/index': './event/index.ts',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts
index ca1fc64d37..6e853034a9 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts
@@ -44,6 +44,7 @@ export class UmbDocumentBlueprintServerDataSource implements UmbDetailDataSource
},
values: [],
variants: [],
+ flags: [],
...preset,
};
@@ -211,12 +212,14 @@ export class UmbDocumentBlueprintServerDataSource implements UmbDetailDataSource
updateDate: variant.updateDate,
scheduledPublishDate: variant.scheduledPublishDate || null,
scheduledUnpublishDate: variant.scheduledUnpublishDate || null,
+ flags: variant.flags,
};
}),
documentType: {
unique: data.documentType.id,
collection: data.documentType.collection ? { unique: data.documentType.collection.id } : null,
},
+ flags: data.flags,
};
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts
index c6a4d4f664..eb930d5c2b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts
@@ -2,12 +2,12 @@ import type { UmbDocumentBlueprintEntityType } from './entity.js';
import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant';
import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models';
import { DocumentVariantStateModel as UmbDocumentBlueprintVariantState } from '@umbraco-cms/backoffice/external/backend-api';
-import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content';
+import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content';
export { UmbDocumentBlueprintVariantState };
export type * from './tree/types.js';
export type * from './workspace/types.js';
-export interface UmbDocumentBlueprintDetailModel {
+export interface UmbDocumentBlueprintDetailModel extends UmbContentDetailModel {
documentType: {
unique: string;
collection: UmbReferenceByUnique | null;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts
index 76787a34dc..816687f36b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts
@@ -49,6 +49,7 @@ export class UmbDocumentCollectionServerDataSource implements UmbCollectionDataS
isTrashed: item.isTrashed,
sortOrder: item.sortOrder,
updater: item.updater,
+ flags: item.flags,
values: item.values.map((item) => {
return {
alias: item.alias,
@@ -69,6 +70,7 @@ export class UmbDocumentCollectionServerDataSource implements UmbCollectionDataS
state: item.state,
createDate: new Date(item.createDate),
updateDate: new Date(item.updateDate),
+ flags: item.flags,
};
}),
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/types.ts
index 6b1c9ddf49..de40f79a20 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/types.ts
@@ -1,6 +1,7 @@
import type { UmbDocumentEntityType } from '../entity.js';
-import type { UmbDocumentItemVariantModel } from '../item/repository/types.js';
+import type { UmbDocumentItemVariantModel } from '../item/types.js';
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
+import type { UmbEntityWithFlags } from '@umbraco-cms/backoffice/entity-flag';
import type { UmbCollectionFilterModel } from '@umbraco-cms/backoffice/collection';
export interface UmbDocumentCollectionFilterModel extends UmbCollectionFilterModel {
@@ -12,7 +13,7 @@ export interface UmbDocumentCollectionFilterModel extends UmbCollectionFilterMod
userDefinedProperties: Array<{ alias: string; header: string; isSystem: boolean }>;
}
-export interface UmbDocumentCollectionItemModel {
+export interface UmbDocumentCollectionItemModel extends UmbEntityWithFlags {
ancestors: Array;
creator?: string | null;
documentType: {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/constants.ts
index 8b2ea67a99..6843254db2 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/constants.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/constants.ts
@@ -2,6 +2,7 @@ export { UMB_DOCUMENT_ENTITY_TYPE, UMB_DOCUMENT_ROOT_ENTITY_TYPE } from './entit
export * from './collection/constants.js';
export * from './entity-actions/constants.js';
+export type * from './entity-sign/constants.js';
export * from './entity-bulk-actions/constants.js';
export * from './item/constants.js';
export * from './menu/constants.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/constants.ts
new file mode 100644
index 0000000000..c5ccfc00e5
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/constants.ts
@@ -0,0 +1,2 @@
+export type * from './has-schedule/constants.js';
+export type * from './has-pending-changes/constants.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/has-pending-changes/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/has-pending-changes/constants.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/has-pending-changes/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/has-pending-changes/manifests.ts
new file mode 100644
index 0000000000..c76ae71c84
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/has-pending-changes/manifests.ts
@@ -0,0 +1,13 @@
+import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
+
+export const manifests: Array = [
+ {
+ type: 'entitySign',
+ kind: 'icon',
+ alias: 'Umb.EntitySign.Document.HasPendingChanges',
+ name: 'Has Pending Changes Document Entity Sign',
+ forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE],
+ forEntityFlags: ['Umb.PendingChanges'],
+ meta: { iconName: 'icon-edit', label: 'Unpublished changes' },
+ },
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/has-schedule/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/has-schedule/constants.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/has-schedule/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/has-schedule/manifests.ts
new file mode 100644
index 0000000000..4486eb1573
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/has-schedule/manifests.ts
@@ -0,0 +1,19 @@
+import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
+
+export const manifests: Array = [
+ {
+ type: 'entitySign',
+ kind: 'icon',
+ alias: 'Umb.EntitySign.Document.HasScheduledPublish',
+ name: 'Document has scheduled publish Entity Sign',
+ forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE],
+ forEntityFlags: ['Umb.ScheduledForPublish'],
+ overwrites: 'Umb.EntitySign.Document.HasPendingChanges',
+ weight: 500,
+ meta: {
+ iconName: 'icon-time',
+ label: 'Scheduled publishing',
+ iconColorAlias: 'green',
+ },
+ },
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/is-protected/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/is-protected/constants.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/is-protected/manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/is-protected/manifest.ts
new file mode 100644
index 0000000000..a9ef60b149
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/is-protected/manifest.ts
@@ -0,0 +1,16 @@
+import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
+
+export const manifests: UmbExtensionManifest = {
+ type: 'entitySign',
+ kind: 'icon',
+ alias: 'Umb.EntitySign.Document.IsProtected',
+ name: 'Is Protected Document Entity Sign',
+ forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE],
+ forEntityFlags: ['Umb.IsProtected'],
+ weight: 1000,
+ meta: {
+ iconName: 'icon-lock',
+ label: 'Protected',
+ iconColorAlias: 'red',
+ },
+};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/manifests.ts
new file mode 100644
index 0000000000..3e79eacb50
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-sign/manifests.ts
@@ -0,0 +1,9 @@
+import { manifests as protectedManifest } from './is-protected/manifest.js';
+import { manifests as scheduleManifests } from './has-schedule/manifests.js';
+import { manifests as pendingChangesManifests } from './has-pending-changes/manifests.js';
+
+export const manifests: Array = [
+ protectedManifest,
+ ...scheduleManifests,
+ ...pendingChangesManifests,
+];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/document-item-data-resolver.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/document-item-data-resolver.ts
index e9aacc8f81..f27afee63b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/document-item-data-resolver.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/document-item-data-resolver.ts
@@ -2,13 +2,28 @@ import { UmbDocumentVariantState } from '../types.js';
import type { UmbDocumentItemModel } from './types.js';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbEntityFlag } from '@umbraco-cms/backoffice/entity-flag';
import type { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api';
-import { UmbBasicState, UmbBooleanState, UmbObjectState, UmbStringState } from '@umbraco-cms/backoffice/observable-api';
+import {
+ UmbArrayState,
+ UmbBasicState,
+ UmbBooleanState,
+ UmbObjectState,
+ UmbStringState,
+ type Observable,
+} from '@umbraco-cms/backoffice/observable-api';
import { type UmbVariantContext, UMB_VARIANT_CONTEXT } from '@umbraco-cms/backoffice/variant';
import type { UmbItemDataResolver } from '@umbraco-cms/backoffice/entity-item';
type UmbDocumentItemDataResolverModel = Omit;
+function isVariantsInvariant(variants: Array<{ culture: string | null }>): boolean {
+ return variants?.[0]?.culture === null;
+}
+function findVariant(variants: Array, culture: string): T | undefined {
+ return variants.find((x) => x.culture === culture);
+}
+
/**
* A controller for resolving data for a document item
* @exports
@@ -31,8 +46,8 @@ export class UmbDocumentItemDataResolver(undefined);
+ public readonly state = this.#state.asObservable() as Observable;
#isDraft = new UmbBooleanState(undefined);
public readonly isDraft = this.#isDraft.asObservable();
@@ -43,6 +58,9 @@ export class UmbDocumentItemDataResolver(undefined);
public readonly updateDate = this.#updateDate.asObservable();
+ #flags = new UmbArrayState([], (data) => data.alias);
+ public readonly flags = this.#flags.asObservable();
+
#variantContext?: UmbVariantContext;
#fallbackCulture?: string | null;
#displayCulture?: string | null;
@@ -148,8 +166,7 @@ export class UmbDocumentItemDataResolver {
- const variant = await this.#getCurrentVariant();
- return variant?.state;
+ return await this.observe(this.state).asPromise();
}
/**
@@ -207,27 +224,33 @@ export class UmbDocumentItemDataResolver x.culture === culture);
- }
-
- async #getCurrentVariant() {
- if (this.#isInvariant()) {
- return this.getData()?.variants?.[0];
+ #setFlags() {
+ const data = this.getData();
+ if (!data) {
+ this.#flags.setValue([]);
+ return;
}
- return this.#findVariant(this.#displayCulture!);
+ const flags = data.flags ?? [];
+ const variantFlags = this.#getCurrentVariant()?.flags ?? [];
+ this.#flags.setValue([...flags, ...variantFlags]);
}
- #isInvariant() {
- return this.getData()?.variants?.[0]?.culture === null;
+ #getCurrentVariant() {
+ const variants = this.getData()?.variants;
+ if (!variants) return undefined;
+
+ if (isVariantsInvariant(variants)) {
+ return variants[0];
+ }
+
+ return findVariant(variants, this.#displayCulture!);
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/document-item.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/document-item.server.data-source.ts
index 70b96553a2..996afcc869 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/document-item.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/document-item.server.data-source.ts
@@ -54,10 +54,12 @@ const mapper = (item: DocumentItemResponseModel): UmbDocumentItemModel => {
culture: variant.culture || null,
name: variant.name,
state: variant.state,
+ flags: variant.flags,
// TODO: [v17] Implement dates when available in the API. [LK]
//createDate: new Date(variant.createDate),
//updateDate: new Date(variant.updateDate),
};
}),
+ flags: item.flags,
};
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/types.ts
index 2ed94e972e..8826cb6f37 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/types.ts
@@ -1,9 +1,10 @@
import type { UmbDocumentEntityType } from '../../entity.js';
import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity';
+import type { UmbEntityFlag, UmbEntityWithFlags } from '@umbraco-cms/backoffice/entity-flag';
import type { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models';
-export interface UmbDocumentItemModel {
+export interface UmbDocumentItemModel extends UmbEntityWithFlags {
documentType: {
unique: string;
icon: string;
@@ -24,4 +25,5 @@ export interface UmbDocumentItemVariantModel {
state: DocumentVariantStateModel | null;
createDate?: Date;
updateDate?: Date;
+ flags: Array;
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts
index ab1b483f43..11ea0cf492 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts
@@ -2,6 +2,7 @@ import { manifests as auditLogManifests } from './audit-log/manifests.js';
import { manifests as collectionManifests } from './collection/manifests.js';
import { manifests as entityActionManifests } from './entity-actions/manifests.js';
import { manifests as entityBulkActionManifests } from './entity-bulk-actions/manifests.js';
+import { manifests as entitySignManifests } from './entity-sign/manifests.js';
import { manifests as globalContextManifests } from './global-contexts/manifests.js';
import { manifests as itemManifests } from './item/manifests.js';
import { manifests as menuManifests } from './menu/manifests.js';
@@ -27,6 +28,7 @@ export const manifests: Array =
...collectionManifests,
...entityActionManifests,
...entityBulkActionManifests,
+ ...entitySignManifests,
...globalContextManifests,
...itemManifests,
...menuManifests,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/save-modal/document-save-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/save-modal/document-save-modal.stories.ts
index f5e0d3faae..37e0b2ff97 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/save-modal/document-save-modal.stories.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/save-modal/document-save-modal.stories.ts
@@ -22,6 +22,7 @@ const modalData: UmbDocumentSaveModalData = {
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -46,6 +47,7 @@ const modalData: UmbDocumentSaveModalData = {
updateDate: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -70,6 +72,7 @@ const modalData: UmbDocumentSaveModalData = {
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -121,6 +124,7 @@ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => {
publishDate: null,
updateDate: null,
segment: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -143,6 +147,7 @@ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => {
publishDate: null,
updateDate: null,
segment: null,
+ flags: [],
},
language: {
entityType: 'language',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/pending-changes/document-published-pending-changes.manager.test.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/pending-changes/document-published-pending-changes.manager.test.ts
index 43e091aa4c..d885e1fa31 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/pending-changes/document-published-pending-changes.manager.test.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/pending-changes/document-published-pending-changes.manager.test.ts
@@ -55,6 +55,7 @@ describe('UmbSelectionManager', () => {
collection: null,
},
isTrashed: false,
+ flags: [],
variants: [
{
state: DocumentVariantStateModel.PUBLISHED,
@@ -66,6 +67,7 @@ describe('UmbSelectionManager', () => {
updateDate: '2023-02-06T15:32:24.957009',
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
],
values: [
@@ -120,6 +122,7 @@ describe('UmbSelectionManager', () => {
collection: null,
},
isTrashed: false,
+ flags: [],
variants: [
{
state: DocumentVariantStateModel.PUBLISHED,
@@ -131,6 +134,7 @@ describe('UmbSelectionManager', () => {
updateDate: '2023-02-06T15:32:24.957009',
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
{
state: DocumentVariantStateModel.PUBLISHED,
@@ -142,6 +146,7 @@ describe('UmbSelectionManager', () => {
updateDate: '2023-02-06T15:32:24.957009',
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
],
values: [
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish-with-descendants/modal/document-publish-with-descendants-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish-with-descendants/modal/document-publish-with-descendants-modal.stories.ts
index 54a9d07742..fee181962e 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish-with-descendants/modal/document-publish-with-descendants-modal.stories.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish-with-descendants/modal/document-publish-with-descendants-modal.stories.ts
@@ -25,6 +25,7 @@ const modalData: UmbDocumentPublishWithDescendantsModalData = {
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -49,6 +50,7 @@ const modalData: UmbDocumentPublishWithDescendantsModalData = {
updateDate: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -73,6 +75,7 @@ const modalData: UmbDocumentPublishWithDescendantsModalData = {
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/entity-bulk-action/publish.bulk-action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/entity-bulk-action/publish.bulk-action.ts
index e52342a7b4..f190bfc2c7 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/entity-bulk-action/publish.bulk-action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/entity-bulk-action/publish.bulk-action.ts
@@ -54,6 +54,7 @@ export class UmbDocumentPublishEntityBulkAction extends UmbEntityBulkActionBase<
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
unique: new UmbVariantId(language.unique, null).toString(),
culture: language.unique,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/modal/document-publish-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/modal/document-publish-modal.stories.ts
index 8d32c68d3e..06a6f7c5de 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/modal/document-publish-modal.stories.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/modal/document-publish-modal.stories.ts
@@ -22,6 +22,7 @@ const modalData: UmbDocumentPublishModalData = {
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -46,6 +47,7 @@ const modalData: UmbDocumentPublishModalData = {
updateDate: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -70,6 +72,7 @@ const modalData: UmbDocumentPublishModalData = {
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -121,6 +124,7 @@ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => {
publishDate: null,
updateDate: null,
segment: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -143,6 +147,7 @@ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => {
publishDate: null,
updateDate: null,
segment: null,
+ flags: [],
},
language: {
entityType: 'language',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/repository/document-publishing.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/repository/document-publishing.server.data-source.ts
index 8689a74f64..5da4d1e6e3 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/repository/document-publishing.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/repository/document-publishing.server.data-source.ts
@@ -180,6 +180,7 @@ export class UmbDocumentPublishingServerDataSource {
updateDate: variant.updateDate,
scheduledPublishDate: variant.scheduledPublishDate || null,
scheduledUnpublishDate: variant.scheduledUnpublishDate || null,
+ flags: variant.flags,
};
}),
template: data.template ? { unique: data.template.id } : null,
@@ -189,6 +190,7 @@ export class UmbDocumentPublishingServerDataSource {
icon: data.documentType.icon,
},
isTrashed: data.isTrashed,
+ flags: data.flags,
};
return { data: document };
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/modal/document-schedule-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/modal/document-schedule-modal.stories.ts
index 84453c2efc..901efa458d 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/modal/document-schedule-modal.stories.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/modal/document-schedule-modal.stories.ts
@@ -24,6 +24,7 @@ const modalData: UmbDocumentScheduleModalData = {
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -48,6 +49,7 @@ const modalData: UmbDocumentScheduleModalData = {
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -99,6 +101,7 @@ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => {
publishDate: null,
updateDate: null,
segment: null,
+ flags: [],
},
language: {
entityType: 'language',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/entity-bulk-action/unpublish.bulk-action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/entity-bulk-action/unpublish.bulk-action.ts
index 243e631ea1..a01416791b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/entity-bulk-action/unpublish.bulk-action.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/entity-bulk-action/unpublish.bulk-action.ts
@@ -53,6 +53,7 @@ export class UmbDocumentUnpublishEntityBulkAction extends UmbEntityBulkActionBas
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
unique: new UmbVariantId(language.unique, null).toString(),
culture: language.unique,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/modal/document-unpublish-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/modal/document-unpublish-modal.stories.ts
index 40ef10377f..5a8481f4fe 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/modal/document-unpublish-modal.stories.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/modal/document-unpublish-modal.stories.ts
@@ -25,6 +25,7 @@ const modalData: UmbDocumentUnpublishModalData = {
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -49,6 +50,7 @@ const modalData: UmbDocumentUnpublishModalData = {
updateDate: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -73,6 +75,7 @@ const modalData: UmbDocumentUnpublishModalData = {
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
},
language: {
entityType: 'language',
@@ -124,6 +127,7 @@ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => {
publishDate: null,
updateDate: null,
segment: null,
+ flags: []
},
language: {
entityType: 'language',
@@ -146,6 +150,7 @@ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => {
publishDate: null,
updateDate: null,
segment: null,
+ flags: []
},
language: {
entityType: 'language',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/data/document-recycle-bin-tree.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/data/document-recycle-bin-tree.server.data-source.ts
index 91567e8909..aebf809208 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/data/document-recycle-bin-tree.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/data/document-recycle-bin-tree.server.data-source.ts
@@ -79,10 +79,13 @@ const mapper = (item: DocumentRecycleBinItemResponseModel): UmbDocumentRecycleBi
culture: variant.culture || null,
segment: null, // TODO: add segment to the backend API?
state: variant.state,
+ flags: variant.flags ?? [],
};
}),
name: item.variants[0]?.name, // TODO: this is not correct. We need to get it from the variants. This is a temp solution.
isFolder: false,
createDate: item.createDate,
+ // TODO: Recycle bin items should have flags, but the API does not return any at the moment. [NL]
+ flags: (item as any).flags ?? [],
};
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts
index b051f6ed3f..315ebbbf24 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts
@@ -55,6 +55,7 @@ export class UmbDocumentServerDataSource
isTrashed: false,
values: [],
variants: [],
+ flags: [],
};
const scaffold = umbDeepMerge(preset, defaultData);
@@ -102,6 +103,7 @@ export class UmbDocumentServerDataSource
updateDate: variant.updateDate,
scheduledPublishDate: variant.scheduledPublishDate || null,
scheduledUnpublishDate: variant.scheduledUnpublishDate || null,
+ flags: variant.flags,
};
}),
template: data.template ? { unique: data.template.id } : null,
@@ -111,6 +113,7 @@ export class UmbDocumentServerDataSource
icon: data.documentType.icon,
},
isTrashed: data.isTrashed,
+ flags: data.flags,
};
return { data: document };
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts
index d6a4cdae75..d91ec198f5 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts
@@ -66,8 +66,10 @@ export class UmbDocumentSearchServerDataSource
culture: variant.culture || null,
name: variant.name,
state: variant.state,
+ flags: variant.flags,
};
}),
+ flags: item.flags,
};
});
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.context.ts
index fc9b250eb7..29cbc3d63b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.context.ts
@@ -27,6 +27,7 @@ export class UmbDocumentTreeItemContext extends UmbDefaultTreeItemContext<
return hasCollection || hasChildren;
},
);
+ readonly flags = this.#item.flags;
// TODO: Move to API
readonly ancestors = this._treeItem.asObservablePart((item) => item?.ancestors ?? []);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.element.ts
index 7ef228559f..85fcec66c3 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.element.ts
@@ -1,7 +1,6 @@
import type { UmbDocumentTreeItemModel } from '../types.js';
import type { UmbDocumentTreeItemContext } from './document-tree-item.context.js';
-import { css, html, nothing, customElement, classMap, state, property } from '@umbraco-cms/backoffice/external/lit';
-import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
+import { css, html, customElement, state, property, classMap } from '@umbraco-cms/backoffice/external/lit';
import { UmbTreeItemElementBase } from '@umbraco-cms/backoffice/tree';
@customElement('umb-document-tree-item')
@@ -10,6 +9,7 @@ export class UmbDocumentTreeItemElement extends UmbTreeItemElementBase<
UmbDocumentTreeItemContext
> {
#api: UmbDocumentTreeItemContext | undefined;
+
@property({ type: Object, attribute: false })
public override get api(): UmbDocumentTreeItemContext | undefined {
return this.#api;
@@ -20,12 +20,13 @@ export class UmbDocumentTreeItemElement extends UmbTreeItemElementBase<
if (this.#api) {
this.observe(this.#api.name, (name) => (this._name = name || ''));
this.observe(this.#api.isDraft, (isDraft) => (this._isDraft = isDraft || false));
- this.observe(this.#api.icon, (icon) => (this._icon = icon || ''));
this.observe(this.#api.hasCollection, (has) => {
const oldValue = this._forceShowExpand;
this._forceShowExpand = has;
this.requestUpdate('_forceShowExpand', oldValue);
});
+ this.observe(this.#api.icon, (icon) => (this.#icon = icon || ''));
+ this.observe(this.#api.flags, (flags) => (this._flags = flags || ''));
}
super.api = value;
@@ -34,20 +35,22 @@ export class UmbDocumentTreeItemElement extends UmbTreeItemElementBase<
@state()
private _name = '';
- @state()
- private _isDraft = false;
+ /**
+ * @internal
+ * Indicates whether the document is a draft, this is controlled internally but present as an attribute as it affects styling.
+ */
+ @property({ type: Boolean, reflect: true, attribute: 'draft' })
+ protected _isDraft = false;
- @state()
- private _icon = '';
+ #icon: string | null | undefined;
- override renderIconContainer() {
- const icon = this._icon;
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ protected override _extractFlags(item: UmbDocumentTreeItemModel | undefined) {
+ // Empty on purpose and NOT calling super to prevent doing what the base does. [NL]
+ }
- return html`
-
- ${icon ? html` ` : nothing}
-
- `;
+ protected override _getIconName(): string | null | undefined {
+ return this.#icon;
}
// eslint-disable-next-line @typescript-eslint/naming-convention
@@ -66,62 +69,12 @@ export class UmbDocumentTreeItemElement extends UmbTreeItemElementBase<
}
static override styles = [
- UmbTextStyles,
+ ...UmbTreeItemElementBase.styles,
css`
- #icon-container {
- position: relative;
+ :host([draft]) #label {
+ opacity: 0.6;
}
-
- #icon {
- vertical-align: middle;
- }
-
- #label {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-
- #state-icon {
- position: absolute;
- bottom: -5px;
- right: -5px;
- font-size: 10px;
- background: var(--uui-color-surface);
- width: 14px;
- height: 14px;
- border-radius: 100%;
- line-height: 14px;
- }
-
- :hover #state-icon {
- background: var(--uui-color-surface-emphasis);
- }
-
- /** Active */
- [active] #state-icon {
- background: var(--uui-color-current);
- }
-
- [active]:hover #state-icon {
- background: var(--uui-color-current-emphasis);
- }
-
- /** Selected */
- [selected] #state-icon {
- background-color: var(--uui-color-selected);
- }
-
- [selected]:hover #state-icon {
- background-color: var(--uui-color-selected-emphasis);
- }
-
- /** Disabled */
- [disabled] #state-icon {
- background-color: var(--uui-color-disabled);
- }
-
- .draft {
+ :host([draft]) umb-icon {
opacity: 0.6;
}
`,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/types.ts
index 7afd0ae918..c91ef5eede 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/types.ts
@@ -8,8 +8,9 @@ import type {
import type { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models';
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
+import type { UmbEntityFlag, UmbEntityWithFlags } from '@umbraco-cms/backoffice/entity-flag';
-export interface UmbDocumentTreeItemModel extends UmbTreeItemModel {
+export interface UmbDocumentTreeItemModel extends Omit, UmbEntityWithFlags {
ancestors: Array;
entityType: UmbDocumentEntityType;
noAccess: boolean;
@@ -33,6 +34,7 @@ export interface UmbDocumentTreeItemVariantModel {
culture: string | null;
segment: string | null;
state: DocumentVariantStateModel | null; // TODO: make our own enum for this. We might have states for "unsaved changes" etc.
+ flags: Array;
}
export interface UmbDocumentTreeRootItemsRequestArgs extends UmbTreeRootItemsRequestArgs {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/constants.ts
index b434f6d318..0a86f3501b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/constants.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/constants.ts
@@ -15,4 +15,5 @@ export const UMB_DOCUMENT_DETAIL_MODEL_VARIANT_SCAFFOLD: UmbDocumentVariantModel
updateDate: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null,
+ flags: [],
} as const;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.context.ts
index dfffd07267..66849f58ff 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.context.ts
@@ -27,6 +27,7 @@ export class UmbMediaCollectionContext extends UmbDefaultCollectionContext<
updateDate: date,
createDate: date,
entityType: UMB_MEDIA_PLACEHOLDER_ENTITY_TYPE,
+ flags: [],
...placeholder,
}))
.reverse();
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.server.data-source.ts
index b1a305495b..e6d6ef4862 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.server.data-source.ts
@@ -45,6 +45,7 @@ export class UmbMediaCollectionServerDataSource implements UmbCollectionDataSour
values: item.values.map((item) => {
return { alias: item.alias, value: item.value as string };
}),
+ flags: item.flags,
};
return model;
});
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/types.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/types.ts
index 06712e08d8..9cb9332e60 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/types.ts
@@ -1,5 +1,6 @@
import type { UmbFileDropzoneItemStatus } from '@umbraco-cms/backoffice/dropzone';
import type { UmbCollectionFilterModel } from '@umbraco-cms/backoffice/collection';
+import type { UmbEntityWithFlags } from '@umbraco-cms/backoffice/entity-flag';
export interface UmbMediaCollectionFilterModel extends UmbCollectionFilterModel {
unique?: string;
@@ -9,7 +10,7 @@ export interface UmbMediaCollectionFilterModel extends UmbCollectionFilterModel
userDefinedProperties: Array<{ alias: string; header: string; isSystem: boolean }>;
}
-export interface UmbMediaCollectionItemModel {
+export interface UmbMediaCollectionItemModel extends UmbEntityWithFlags {
unique: string;
entityType: string;
contentTypeAlias?: string;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/dropzone/media-dropzone.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/dropzone/media-dropzone.manager.ts
index 2fd41b6421..bcb5c86274 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/dropzone/media-dropzone.manager.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/dropzone/media-dropzone.manager.ts
@@ -190,7 +190,7 @@ export class UmbMediaDropzoneManager extends UmbDropzoneManager {
const preset: Partial = {
unique: item.unique,
mediaType: { unique: mediaTypeUnique, collection: null },
- variants: [{ culture: null, segment: null, createDate: null, updateDate: null, name }],
+ variants: [{ culture: null, segment: null, createDate: null, updateDate: null, flags: [], name }],
values: item.temporaryFile ? [umbracoFile] : undefined,
};
const { data } = await this.#mediaDetailRepository.createScaffold(preset);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/components/media-picker-folder-path.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/components/media-picker-folder-path.element.ts
index 3c2f0422c0..7aa35f9370 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/components/media-picker-folder-path.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/components/media-picker-folder-path.element.ts
@@ -117,6 +117,7 @@ export class UmbMediaPickerFolderPathElement extends UmbLitElement {
name: newName,
createDate: null,
updateDate: null,
+ flags: [],
},
],
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts
index 614e79d94e..dede293238 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts
@@ -45,6 +45,7 @@ export class UmbMediaServerDataSource extends UmbControllerBase implements UmbDe
icon: mediaTypeIcon,
},
isTrashed: false,
+ flags: [],
values: [],
variants: [
{
@@ -53,6 +54,7 @@ export class UmbMediaServerDataSource extends UmbControllerBase implements UmbDe
name: '',
createDate: null,
updateDate: null,
+ flags: [],
},
],
};
@@ -90,6 +92,8 @@ export class UmbMediaServerDataSource extends UmbControllerBase implements UmbDe
name: variant.name,
createDate: variant.createDate,
updateDate: variant.updateDate,
+ // TODO: Media variant flags are not yet implemented in the backend.
+ flags: [],
};
}),
mediaType: {
@@ -98,6 +102,7 @@ export class UmbMediaServerDataSource extends UmbControllerBase implements UmbDe
icon: data.mediaType.icon,
},
isTrashed: data.isTrashed,
+ flags: data.flags,
};
return { data: media };
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/types.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/types.ts
index 8f094c91b3..be7a5233cf 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/types.ts
@@ -27,6 +27,8 @@ export interface UmbMediaTreeRootModel extends UmbTreeRootModel {
export interface UmbMediaTreeItemVariantModel {
name: string;
culture: string | null;
+ // Notice: Media variant flags are not yet implemented in the backend.
+ //flags: Array;
}
export interface UmbMediaTreeRootItemsRequestArgs extends UmbTreeRootItemsRequestArgs {
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/constants.ts
index 8a3af27b20..d823f4f0b8 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/constants.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/constants.ts
@@ -10,4 +10,5 @@ export const UMB_MEMBER_DETAIL_MODEL_VARIANT_SCAFFOLD: UmbMediaVariantModel = {
name: '',
createDate: null,
updateDate: null,
+ flags: [],
} as const;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/repository/member-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/repository/member-collection.server.data-source.ts
index 0c9742104d..f35676c7c9 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/repository/member-collection.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/repository/member-collection.server.data-source.ts
@@ -62,6 +62,7 @@ export class UmbMemberCollectionServerDataSource implements UmbCollectionDataSou
memberType: { unique: item.memberType.id, icon: item.memberType.icon },
username: item.username,
values: item.values as UmbMemberValueModel[],
+ flags: item.flags,
};
return memberDetail;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts
index 134cb2bfe1..b96137e638 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts
@@ -53,6 +53,7 @@ export class UmbMemberServerDataSource extends UmbControllerBase implements UmbD
lastPasswordChangeDate: null,
groups: [],
values: [],
+ flags: [],
variants: [
{
name: '',
@@ -60,6 +61,7 @@ export class UmbMemberServerDataSource extends UmbControllerBase implements UmbD
segment: null,
createDate: new Date().toISOString(),
updateDate: new Date().toISOString(),
+ flags: [],
},
],
};
@@ -120,8 +122,11 @@ export class UmbMemberServerDataSource extends UmbControllerBase implements UmbD
name: variant.name,
createDate: variant.createDate,
updateDate: variant.updateDate,
+ // TODO: Transfer member flags when available in the API: [NL]
+ flags: [], //variant.flags,
};
}),
+ flags: data.flags,
};
return { data: Member };
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/constants.ts
index 465892c416..0664db72ac 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/constants.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/constants.ts
@@ -6,6 +6,7 @@ export const UMB_MEMBER_DETAIL_MODEL_VARIANT_SCAFFOLD: UmbMemberVariantModel = {
name: '',
createDate: null,
updateDate: null,
+ flags: [],
} as const;
export { UMB_MEMBER_WORKSPACE_CONTEXT } from './member-workspace.context-token.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/manifests.ts
index 2479e6b7a3..8cf5a3bf17 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/manifests.ts
@@ -45,6 +45,7 @@ const propertyEditorUiManifest: ManifestPropertyEditorUi = {
label: 'Workspace View icon',
description: "The icon for the Collection's Workspace View.",
propertyEditorUiAlias: 'Umb.PropertyEditorUi.IconPicker',
+ config: [{ alias: 'placeholder', value: 'icon-grid' }],
},
{
alias: 'tabName',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/manifests.ts
index ab1792f1c8..780ddf721e 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/manifests.ts
@@ -8,6 +8,16 @@ export const manifests: Array = [
label: 'Icon Picker',
icon: 'icon-autofill',
group: 'common',
+ settings: {
+ properties: [
+ {
+ alias: 'placeholder',
+ label: 'Placeholder icon (empty state)',
+ description: 'Icon name to show when no icon is selected',
+ propertyEditorUiAlias: 'Umb.PropertyEditorUi.IconPicker',
+ },
+ ],
+ },
},
},
];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.element.ts
index 60298ab57a..fffedbbaec 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.element.ts
@@ -1,5 +1,8 @@
-import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
-import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor';
+import { html, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
+import type {
+ UmbPropertyEditorConfigCollection,
+ UmbPropertyEditorUiElement,
+} from '@umbraco-cms/backoffice/property-editor';
import { umbOpenModal } from '@umbraco-cms/backoffice/modal';
import { UMB_ICON_PICKER_MODAL } from '@umbraco-cms/backoffice/icon';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
@@ -35,11 +38,29 @@ export class UmbPropertyEditorUIIconPickerElement extends UmbLitElement implemen
@state()
private _color = '';
+ @state()
+ private _placeholderIcon = '';
+
+ public set config(config: UmbPropertyEditorConfigCollection | undefined) {
+ if (!config) return;
+ const placeholder = config.getValueByAlias('placeholder');
+ this._placeholderIcon = typeof placeholder === 'string' ? placeholder : '';
+ }
+
private async _openModal() {
- const data = await umbOpenModal(this, UMB_ICON_PICKER_MODAL).catch(() => undefined);
+ const data = await umbOpenModal(this, UMB_ICON_PICKER_MODAL, {
+ value: {
+ icon: this._icon,
+ color: this._color,
+ },
+ data: { placeholder: this._placeholderIcon },
+ }).catch(() => undefined);
+
if (!data) return;
- if (data.color) {
+ if (!data.icon) {
+ this.value = '';
+ } else if (data.color) {
this.value = `${data.icon} color-${data.color}`;
} else {
this.value = data.icon as string;
@@ -49,15 +70,21 @@ export class UmbPropertyEditorUIIconPickerElement extends UmbLitElement implemen
}
override render() {
+ const isEmpty = !this._icon;
+
return html`
- ${this._color
- ? html` `
- : html` `}
+ ${isEmpty
+ ? html` `
+ : this._color
+ ? html`
+
+ `
+ : html``}
`;
}
diff --git a/src/Umbraco.Web.UI.Client/tsconfig.json b/src/Umbraco.Web.UI.Client/tsconfig.json
index eebc431a10..ef64a1e410 100644
--- a/src/Umbraco.Web.UI.Client/tsconfig.json
+++ b/src/Umbraco.Web.UI.Client/tsconfig.json
@@ -77,6 +77,8 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js
"./src/packages/core/entity-create-option-action/index.ts"
],
"@umbraco-cms/backoffice/entity-item": ["./src/packages/core/entity-item/index.ts"],
+ "@umbraco-cms/backoffice/entity-sign": ["./src/packages/core/entity-sign/index.ts"],
+ "@umbraco-cms/backoffice/entity-flag": ["./src/packages/core/entity-flag/index.ts"],
"@umbraco-cms/backoffice/entity": ["./src/packages/core/entity/index.ts"],
"@umbraco-cms/backoffice/event": ["./src/packages/core/event/index.ts"],
"@umbraco-cms/backoffice/extension-registry": ["./src/packages/core/extension-registry/index.ts"],