diff --git a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/models.ts b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/models.ts index 9ef7b35807..bb559217ec 100644 --- a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/models.ts +++ b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/models.ts @@ -113,7 +113,7 @@ export type CopyMediaTypeRequestModel = { export type CreateDataTypeRequestModel = { name: string editorAlias: string -editorUiAlias?: string | null +editorUiAlias: string values: Array id?: string | null parent?: ReferenceByIdModel | null @@ -333,6 +333,7 @@ stylesheets: Array scripts: Array languages: Array dictionaryItems: Array +id?: string | null }; export type CreatePartialViewFolderRequestModel = { @@ -436,7 +437,9 @@ userName: string name: string languageIsoCode?: string | null documentStartNodeIds: Array +hasDocumentRootAccess: boolean mediaStartNodeIds: Array +hasMediaRootAccess: boolean avatarUrls: Array languages: Array hasAccessToAllLanguages: boolean @@ -479,7 +482,7 @@ properties: Array export type DataTypeResponseModel = { name: string editorAlias: string -editorUiAlias?: string | null +editorUiAlias: string values: Array id: string isDeletable: boolean @@ -1811,6 +1814,11 @@ export type PagedUserResponseModel = { items: Array }; +export type PagedWebhookEventModel = { + total: number +items: Array + }; + export type PagedWebhookResponseModel = { total: number items: Array @@ -2263,7 +2271,7 @@ export type UnpublishDocumentRequestModel = { export type UpdateDataTypeRequestModel = { name: string editorAlias: string -editorUiAlias?: string | null +editorUiAlias: string values: Array }; @@ -2512,7 +2520,9 @@ name: string userGroupIds: Array languageIsoCode: string documentStartNodeIds: Array +hasDocumentRootAccess: boolean mediaStartNodeIds: Array +hasMediaRootAccess: boolean }; export type UpdateWebhookRequestModel = { @@ -2621,7 +2631,9 @@ userGroupIds: Array id: string languageIsoCode?: string | null documentStartNodeIds: Array +hasDocumentRootAccess: boolean mediaStartNodeIds: Array +hasMediaRootAccess: boolean avatarUrls: Array state: UserStateModel failedLoginAttempts: number @@ -2676,6 +2688,12 @@ export type VerifyResetPasswordTokenRequestModel = { resetCode: string }; +export type WebhookEventModel = { + eventName: string +eventType: string +alias: string + }; + export type WebhookEventResponseModel = { eventName: string eventType: string @@ -5221,6 +5239,11 @@ requestBody?: UpdateWebhookRequestModel DeleteWebhookById: { id: string + }; +GetWebhookEvents: { + skip?: number +take?: number + }; } @@ -5232,6 +5255,7 @@ DeleteWebhookById: { ,GetWebhookById: WebhookResponseModel ,PutWebhookById: string ,DeleteWebhookById: string + ,GetWebhookEvents: PagedWebhookEventModel } diff --git a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/services.ts b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/services.ts index 476f2ab3c6..503eeca574 100644 --- a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/services.ts +++ b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/services.ts @@ -9071,4 +9071,26 @@ requestBody }); } + /** + * @returns unknown Success + * @throws ApiError + */ + public static getWebhookEvents(data: WebhookData['payloads']['GetWebhookEvents'] = {}): CancelablePromise { + const { + + skip, +take + } = data; + return __request(OpenAPI, { + method: 'GET', + url: '/umbraco/management/api/v1/webhook/events', + query: { + skip, take + }, + errors: { + 401: `The resource is protected and requires an authentication token`, + }, + }); + } + } \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts index f26833d53e..c794c4a871 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts @@ -14,6 +14,7 @@ export const data: Array = [ isFolder: true, hasChildren: false, editorAlias: '', + editorUiAlias: '', values: [], isDeletable: true, canIgnoreStartNodes: false, @@ -25,6 +26,7 @@ export const data: Array = [ isFolder: true, hasChildren: true, editorAlias: '', + editorUiAlias: '', values: [], isDeletable: true, canIgnoreStartNodes: false, @@ -308,6 +310,7 @@ export const data: Array = [ id: 'dt-datePicker-time', parent: null, editorAlias: 'Umbraco.DateTime', + editorUiAlias: 'Umb.PropertyEditorUi.DatePicker', hasChildren: false, isFolder: false, isDeletable: true, diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.db.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.db.ts index fad4ede41a..8880e64ff8 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.db.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.db.ts @@ -44,6 +44,7 @@ const createFolderMockMapper = (request: CreateFolderRequestModel): UmbMockDataT isFolder: true, hasChildren: false, editorAlias: '', + editorUiAlias: '', isDeletable: true, canIgnoreStartNodes: false, values: [], diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.data.ts index b2e34eae17..27b5ce7669 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.data.ts @@ -11,7 +11,9 @@ export const data: Array = [ { id: 'bca6c733-a63d-4353-a271-9a8b6bcca8bd', documentStartNodeIds: [], + hasDocumentRootAccess: true, mediaStartNodeIds: [], + hasMediaRootAccess: true, name: 'Umbraco User', email: 'noreply@umbraco.com', languageIsoCode: 'en-us', @@ -30,7 +32,9 @@ export const data: Array = [ { id: '82e11d3d-b91d-43c9-9071-34d28e62e81d', documentStartNodeIds: ['simple-document-id'], + hasDocumentRootAccess: true, mediaStartNodeIds: ['f2f81a40-c989-4b6b-84e2-057cecd3adc1'], + hasMediaRootAccess: true, name: 'Amelie Walker', email: 'awalker1@domain.com', languageIsoCode: 'da-dk', @@ -50,6 +54,8 @@ export const data: Array = [ id: 'aa1d83a9-bc7f-47d2-b288-58d8a31f5017', documentStartNodeIds: [], mediaStartNodeIds: [], + hasDocumentRootAccess: true, + hasMediaRootAccess: true, name: 'Oliver Kim', email: 'okim1@domain.com', languageIsoCode: 'da-dk', @@ -69,6 +75,8 @@ export const data: Array = [ id: 'ff2f4a50-d3d4-4bc4-869d-c7948c160e54', documentStartNodeIds: [], mediaStartNodeIds: [], + hasDocumentRootAccess: true, + hasMediaRootAccess: true, name: 'Eliana Nieves', email: 'enieves1@domain.com', languageIsoCode: 'en-us', @@ -88,6 +96,8 @@ export const data: Array = [ id: 'c290c6d9-9f12-4838-8567-621b52a178de', documentStartNodeIds: [], mediaStartNodeIds: [], + hasDocumentRootAccess: true, + hasMediaRootAccess: true, name: 'Jasmine Patel', email: 'jpatel1@domain.com', languageIsoCode: 'en-us', diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.db.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.db.ts index 231e29bf0d..f414e6bc65 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.db.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/user/user.db.ts @@ -68,6 +68,8 @@ class UmbUserMockDB extends UmbEntityMockDbBase { languages: [], documentStartNodeIds: firstUser.documentStartNodeIds, mediaStartNodeIds: firstUser.mediaStartNodeIds, + hasDocumentRootAccess: firstUser.hasDocumentRootAccess, + hasMediaRootAccess: firstUser.hasMediaRootAccess, fallbackPermissions: [], permissions, allowedSections, @@ -197,6 +199,8 @@ const createMockMapper = (item: CreateUserRequestModel): UmbMockUserModel => { languageIsoCode: null, documentStartNodeIds: [], mediaStartNodeIds: [], + hasDocumentRootAccess: false, + hasMediaRootAccess: false, avatarUrls: [], state: UserStateModel.INACTIVE, failedLoginAttempts: 0, @@ -219,6 +223,8 @@ const detailResponseMapper = (item: UmbMockUserModel): UserResponseModel => { languageIsoCode: item.languageIsoCode, documentStartNodeIds: item.documentStartNodeIds, mediaStartNodeIds: item.mediaStartNodeIds, + hasDocumentRootAccess: item.hasDocumentRootAccess, + hasMediaRootAccess: item.hasMediaRootAccess, avatarUrls: item.avatarUrls, state: item.state, failedLoginAttempts: item.failedLoginAttempts, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-column-span/property-editor-ui-block-grid-column-span.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-column-span/property-editor-ui-block-grid-column-span.element.ts index 69bcdf527e..e635d38d9a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-column-span/property-editor-ui-block-grid-column-span.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-column-span/property-editor-ui-block-grid-column-span.element.ts @@ -2,7 +2,10 @@ import type { UmbBlockGridTypeColumnSpanOption } from '../../types.js'; import { html, customElement, property, css, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UmbPropertyValueChangeEvent, + type UmbPropertyEditorConfigCollection, +} from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @customElement('umb-property-editor-ui-block-grid-column-span') @@ -30,7 +33,7 @@ export class UmbPropertyEditorUIBlockGridColumnSpanElement extends UmbLitElement this.value = [...value, { columnSpan: index }]; } - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts index a38f9966e8..00d7468381 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts @@ -1,7 +1,10 @@ import { html, customElement, property, css } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UmbPropertyValueChangeEvent, + type UmbPropertyEditorConfigCollection, +} from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbBlockGridTypeGroupType } from '@umbraco-cms/backoffice/block-grid'; @@ -25,7 +28,7 @@ export class UmbPropertyEditorUIBlockGridGroupConfigurationElement #addGroup() { this.value = [...this._value, { name: 'Unnamed group', key: UmbId.new() }]; - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.element.ts index b5e2ab09fe..9cd3218e1c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.element.ts @@ -6,7 +6,10 @@ import '@umbraco-cms/backoffice/static-file'; import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UmbPropertyValueChangeEvent, + type UmbPropertyEditorConfigCollection, +} from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @customElement('umb-property-editor-ui-block-grid-layout-stylesheet') @@ -29,7 +32,7 @@ export class UmbPropertyEditorUIBlockGridLayoutStylesheetElement private _onChange(event: CustomEvent) { this.value = (event.target as UmbInputStaticFileElement).selection; - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } // TODO: Implement mandatory? diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts index 0fbed19899..0902e37c11 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts @@ -86,6 +86,7 @@ export class UmbDataTypeServerDataSource implements UmbDetailDataSource item.alias !== alias)]; - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } #onEdit(crop: UmbCrop) { @@ -88,7 +89,7 @@ export class UmbPropertyEditorUIImageCropsConfigurationElement } else { this.value = [...this.value, newCrop]; } - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); form.reset(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/Umbraco.IconPicker.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/Umbraco.IconPicker.ts deleted file mode 100644 index b9f63ab377..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/Umbraco.IconPicker.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { ManifestPropertyEditorSchema } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifest: ManifestPropertyEditorSchema = { - type: 'propertyEditorSchema', - name: 'Icon Picker', - alias: 'Umbraco.IconPicker', - meta: { - defaultPropertyEditorUiAlias: 'Umb.PropertyEditorUi.IconPicker', - }, -}; 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 437d5fb241..28b29af0d5 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 @@ -1,4 +1,3 @@ -import { manifest as schemaManifest } from './Umbraco.IconPicker.js'; import type { ManifestPropertyEditorUi, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; const manifest: ManifestPropertyEditorUi = { @@ -8,10 +7,9 @@ const manifest: ManifestPropertyEditorUi = { element: () => import('./property-editor-ui-icon-picker.element.js'), meta: { label: 'Icon Picker', - propertyEditorSchemaAlias: 'Umbraco.IconPicker', icon: 'icon-autofill', group: 'common', }, }; -export const manifests: Array = [manifest, schemaManifest]; +export const manifests: Array = [manifest]; 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 f34445a035..0c35c621d5 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 @@ -3,6 +3,7 @@ import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extensi import { UMB_MODAL_MANAGER_CONTEXT, UMB_ICON_PICKER_MODAL } from '@umbraco-cms/backoffice/modal'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { extractUmbColorVariable } from '@umbraco-cms/backoffice/resources'; +import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor'; /** * @element umb-property-editor-ui-icon-picker @@ -46,7 +47,7 @@ export class UmbPropertyEditorUIIconPickerElement extends UmbLitElement implemen this.value = data.icon as string; } - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/overlay-size/property-editor-ui-overlay-size.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/overlay-size/property-editor-ui-overlay-size.element.ts index e807ef8bbe..831ddbdd3e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/overlay-size/property-editor-ui-overlay-size.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/overlay-size/property-editor-ui-overlay-size.element.ts @@ -1,7 +1,10 @@ import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UmbPropertyValueChangeEvent, + type UmbPropertyEditorConfigCollection, +} from '@umbraco-cms/backoffice/property-editor'; import type { UUIModalSidebarSize, UUISelectEvent } from '@umbraco-cms/backoffice/external/uui'; /** @@ -33,7 +36,7 @@ export class UmbPropertyEditorUIOverlaySizeElement extends UmbLitElement impleme #onChange(event: UUISelectEvent) { this.value = event.target.value as string; - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.element.ts index 19663c22dc..91e235229e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.element.ts @@ -9,7 +9,10 @@ import { } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UmbPropertyValueChangeEvent, + type UmbPropertyEditorConfigCollection, +} from '@umbraco-cms/backoffice/property-editor'; import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; @@ -50,7 +53,7 @@ export class UmbPropertyEditorUITextBoxElement const newValue = (e.target as HTMLInputElement).value; if (newValue === this.value) return; this.value = newValue; - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/textarea/property-editor-ui-textarea.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/textarea/property-editor-ui-textarea.element.ts index 6ab34bcdf6..b7a050689b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/textarea/property-editor-ui-textarea.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/textarea/property-editor-ui-textarea.element.ts @@ -2,7 +2,10 @@ import { css, html, customElement, property, state, ifDefined, styleMap } from ' import type { UUITextareaElement } from '@umbraco-cms/backoffice/external/uui'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UmbPropertyValueChangeEvent, + type UmbPropertyEditorConfigCollection, +} from '@umbraco-cms/backoffice/property-editor'; @customElement('umb-property-editor-ui-textarea') export class UmbPropertyEditorUITextareaElement extends UmbLitElement implements UmbPropertyEditorUiElement { @@ -38,7 +41,7 @@ export class UmbPropertyEditorUITextareaElement extends UmbLitElement implements private onInput(e: InputEvent) { this.value = (e.target as UUITextareaElement).value as string; - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/upload-field/property-editor-ui-upload-field.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/upload-field/property-editor-ui-upload-field.element.ts index 1b55630fb5..31e223a69b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/upload-field/property-editor-ui-upload-field.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/upload-field/property-editor-ui-upload-field.element.ts @@ -2,7 +2,10 @@ import type { UmbInputUploadFieldElement } from '../../core/components/input-upl import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UmbPropertyValueChangeEvent, + type UmbPropertyEditorConfigCollection, +} from '@umbraco-cms/backoffice/property-editor'; /** * @element umb-property-editor-ui-upload-field @@ -28,7 +31,7 @@ export class UmbPropertyEditorUIUploadFieldElement extends UmbLitElement impleme private _onChange(event: CustomEvent) { this.value = (event.target as unknown as UmbInputUploadFieldElement).value as string; - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/value-type/property-editor-ui-value-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/value-type/property-editor-ui-value-type.element.ts index 02cd33ec60..645332cfa7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/value-type/property-editor-ui-value-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/value-type/property-editor-ui-value-type.element.ts @@ -2,7 +2,10 @@ import { html, customElement, property, state, query } from '@umbraco-cms/backof import type { UUISelectElement, UUISelectEvent } from '@umbraco-cms/backoffice/external/uui'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UmbPropertyValueChangeEvent, + type UmbPropertyEditorConfigCollection, +} from '@umbraco-cms/backoffice/property-editor'; /** * @element umb-property-editor-ui-value-type @@ -46,7 +49,7 @@ export class UmbPropertyEditorUIValueTypeElement extends UmbLitElement implement #onChange(e: UUISelectEvent) { this.value = e.target.value as string; - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/static-file/property-editors/static-file-picker/property-editor-ui-static-file-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/static-file/property-editors/static-file-picker/property-editor-ui-static-file-picker.element.ts index 1ef62bbb86..84fbb7315a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/static-file/property-editors/static-file-picker/property-editor-ui-static-file-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/static-file/property-editors/static-file-picker/property-editor-ui-static-file-picker.element.ts @@ -2,7 +2,10 @@ import type { UmbInputStaticFileElement } from '../../components/index.js'; import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UmbPropertyValueChangeEvent, + type UmbPropertyEditorConfigCollection, +} from '@umbraco-cms/backoffice/property-editor'; import '../../components/input-static-file/index.js'; @customElement('umb-property-editor-ui-static-file-picker') @@ -31,7 +34,7 @@ export class UmbPropertyEditorUIStaticFilePickerElement extends UmbLitElement im private _onChange(event: CustomEvent) { this.value = (event.target as UmbInputStaticFileElement).selection; - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } // TODO: Implement mandatory? diff --git a/src/Umbraco.Web.UI.Client/src/packages/tags/property-editors/tags/property-editor-ui-tags.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tags/property-editors/tags/property-editor-ui-tags.element.ts index 7c25a6004f..1f6b321345 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tags/property-editors/tags/property-editor-ui-tags.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tags/property-editors/tags/property-editor-ui-tags.element.ts @@ -1,7 +1,10 @@ import type { UmbTagsInputElement } from '../../components/tags-input/tags-input.element.js'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; import { html, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UmbPropertyValueChangeEvent, + type UmbPropertyEditorConfigCollection, +} from '@umbraco-cms/backoffice/property-editor'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @@ -51,7 +54,7 @@ export class UmbPropertyEditorUITagsElement extends UmbLitElement implements Umb #onChange(event: CustomEvent) { this.value = ((event.target as UmbTagsInputElement).value as string).split(','); - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts index 6d49f9ba0c..1ce12335fb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts @@ -5,7 +5,10 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs'; -import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UmbPropertyValueChangeEvent, + type UmbPropertyEditorConfigCollection, +} from '@umbraco-cms/backoffice/property-editor'; import { tinymce } from '@umbraco-cms/backoffice/external/tinymce'; const tinyIconSet = tinymce.IconManager.get('default'); @@ -106,7 +109,7 @@ export class UmbPropertyEditorUITinyMceToolbarConfigurationElement this.value = value; - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/repository/user-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/repository/user-collection.server.data-source.ts index 37b5078a7a..61b063b3b2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/repository/user-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/repository/user-collection.server.data-source.ts @@ -64,6 +64,8 @@ export class UmbUserCollectionServerDataSource implements UmbCollectionDataSourc languageIsoCode: item.languageIsoCode || null, documentStartNodeUniques: item.documentStartNodeIds, mediaStartNodeUniques: item.mediaStartNodeIds, + hasDocumentRootAccess: item.hasDocumentRootAccess, + hasMediaRootAccess: item.hasMediaRootAccess, avatarUrls: item.avatarUrls, state: item.state, failedLoginAttempts: item.failedLoginAttempts, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts index eef9a30525..b32acc6bcd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts @@ -34,15 +34,18 @@ export class UmbUserServerDataSource implements UmbDetailDataSource; - unique: string; - languageIsoCode: string | null; - documentStartNodeUniques: Array; - mediaStartNodeUniques: Array; avatarUrls: Array; - state: UmbUserStateEnum | null; - failedLoginAttempts: number; createDate: string | null; - updateDate: string | null; - lastLoginDate: string | null; - lastLockoutDate: string | null; - lastPasswordChangeDate: string | null; + documentStartNodeUniques: Array; + email: string; + entityType: UmbUserEntityType; + failedLoginAttempts: number; + hasDocumentRootAccess: boolean; + hasMediaRootAccess: boolean; isAdmin: boolean; + languageIsoCode: string | null; + lastLockoutDate: string | null; + lastLoginDate: string | null; + lastPasswordChangeDate: string | null; + mediaStartNodeUniques: Array; + name: string; + state: UmbUserStateEnum | null; + unique: string; + updateDate: string | null; + userGroupUniques: Array; + userName: string; } export type UmbUserMfaProviderModel = UserTwoFactorProviderModel; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-access-settings/user-workspace-access-settings.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-access-settings/user-workspace-access-settings.element.ts deleted file mode 100644 index 73d4e395b8..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-access-settings/user-workspace-access-settings.element.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserDetailModel } from '../../../types.js'; -import { html, customElement, state, css } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -import type { UmbInputDocumentElement } from '@umbraco-cms/backoffice/document'; -import type { UmbInputMediaElement } from '@umbraco-cms/backoffice/media'; -import type { UmbUserGroupInputElement } from '@umbraco-cms/backoffice/user-group'; - -@customElement('umb-user-workspace-access-settings') -export class UmbUserWorkspaceAccessSettingsElement extends UmbLitElement { - @state() - private _user?: UmbUserDetailModel; - - #userWorkspaceContext?: typeof UMB_USER_WORKSPACE_CONTEXT.TYPE; - - constructor() { - super(); - - this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (instance) => { - this.#userWorkspaceContext = instance; - this.observe(this.#userWorkspaceContext.data, (user) => (this._user = user), 'umbUserObserver'); - }); - } - - #onUserGroupsChange(event: UmbChangeEvent) { - const target = event.target as UmbUserGroupInputElement; - this.#userWorkspaceContext?.updateProperty('userGroupUniques', target.selection); - } - - #onDocumentStartNodeChange(event: UmbChangeEvent) { - const target = event.target as UmbInputDocumentElement; - this.#userWorkspaceContext?.updateProperty('documentStartNodeUniques', target.selection); - } - - #onMediaStartNodeChange(event: UmbChangeEvent) { - const target = event.target as UmbInputMediaElement; - this.#userWorkspaceContext?.updateProperty('mediaStartNodeUniques', target.selection); - } - - render() { - return html` -
Assign Access
-
- - - - - - - - - -
-
- - -
- Based on the assigned groups and start nodes, the user has access to the following nodes -
- - ${this.#renderDocumentStartNodes()} -
- ${this.#renderMediaStartNodes()} -
`; - } - - #renderDocumentStartNodes() { - return html` Content - `; - } - - #renderMediaStartNodes() { - return html` Media - `; - } - - static styles = [ - UmbTextStyles, - css` - #access { - margin-top: var(--uui-size-space-4); - } - - hr { - border: none; - border-bottom: 1px solid var(--uui-color-divider); - width: 100%; - } - .faded-text { - color: var(--uui-color-text-alt); - font-size: 0.8rem; - } - `, - ]; -} - -export default UmbUserWorkspaceAccessSettingsElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-user-workspace-access-settings': UmbUserWorkspaceAccessSettingsElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts new file mode 100644 index 0000000000..7b9ad681c5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts @@ -0,0 +1,77 @@ +import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; +import type { UmbUserDetailModel } from '../../../types.js'; +import { html, customElement, state, css } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; + +import '../user-workspace-assign-access/user-workspace-assign-access.element.js'; + +const elementName = 'umb-user-workspace-access'; +@customElement(elementName) +export class UmbUserWorkspaceAccessElement extends UmbLitElement { + @state() + private _user?: UmbUserDetailModel; + + #userWorkspaceContext?: typeof UMB_USER_WORKSPACE_CONTEXT.TYPE; + + constructor() { + super(); + + this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (instance) => { + this.#userWorkspaceContext = instance; + this.observe(this.#userWorkspaceContext.data, (user) => (this._user = user), 'umbUserObserver'); + }); + } + + render() { + return html` +
+ Based on the assigned groups and start nodes, the user has access to the following nodes +
+ + ${this.#renderDocumentStartNodes()} +
+ ${this.#renderMediaStartNodes()} +
`; + } + + #renderDocumentStartNodes() { + return html` Content + `; + } + + #renderMediaStartNodes() { + return html` Media + `; + } + + static styles = [ + UmbTextStyles, + css` + #access { + margin-top: var(--uui-size-space-4); + } + + hr { + border: none; + border-bottom: 1px solid var(--uui-color-divider); + width: 100%; + } + .faded-text { + color: var(--uui-color-text-alt); + font-size: 0.8rem; + } + `, + ]; +} + +export default UmbUserWorkspaceAccessElement; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserWorkspaceAccessElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-assign-access/user-workspace-assign-access.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-assign-access/user-workspace-assign-access.element.ts new file mode 100644 index 0000000000..4859421d47 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/components/user-workspace-assign-access/user-workspace-assign-access.element.ts @@ -0,0 +1,188 @@ +import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; +import type { UmbUserDetailModel } from '../../../types.js'; +import { html, customElement, state, css, nothing } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import type { UmbInputDocumentElement } from '@umbraco-cms/backoffice/document'; +import type { UmbInputMediaElement } from '@umbraco-cms/backoffice/media'; +import type { UmbUserGroupInputElement } from '@umbraco-cms/backoffice/user-group'; +import type { UUIBooleanInputEvent } from '@umbraco-cms/backoffice/external/uui'; + +const elementName = 'umb-user-workspace-assign-access'; +@customElement(elementName) +export class UmbUserWorkspaceAssignAccessElement extends UmbLitElement { + @state() + private _userGroupUniques: UmbUserDetailModel['userGroupUniques'] = []; + + @state() + private _documentStartNodeUniques: UmbUserDetailModel['documentStartNodeUniques'] = []; + + @state() + private _documentRootAccess: UmbUserDetailModel['hasDocumentRootAccess'] = false; + + @state() + private _mediaStartNodeUniques: UmbUserDetailModel['documentStartNodeUniques'] = []; + + @state() + private _mediaRootAccess: UmbUserDetailModel['hasMediaRootAccess'] = false; + + #workspaceContext?: typeof UMB_USER_WORKSPACE_CONTEXT.TYPE; + + constructor() { + super(); + + this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (instance) => { + this.#workspaceContext = instance; + + this.observe( + this.#workspaceContext.userGroupUniques, + (value) => (this._userGroupUniques = value), + '_observeUserGroupAccess', + ); + + this.observe( + this.#workspaceContext.hasDocumentRootAccess, + (value) => (this._documentRootAccess = value), + '_observeDocumentRootAccess', + ); + + this.observe( + this.#workspaceContext.documentStartNodeUniques, + (value) => (this._documentStartNodeUniques = value), + '_observeDocumentStartNode', + ); + + this.observe( + this.#workspaceContext.hasMediaRootAccess, + (value) => (this._mediaRootAccess = value), + '_observeMediaRootAccess', + ); + + this.observe( + this.#workspaceContext.mediaStartNodeUniques, + (value) => (this._mediaStartNodeUniques = value), + '_observeMediaStartNode', + ); + }); + } + + #onUserGroupsChange(event: CustomEvent) { + event.stopPropagation(); + const target = event.target as UmbUserGroupInputElement; + const selection = target.selection; + // TODO make contexts method + this.#workspaceContext?.updateProperty('userGroupUniques', selection); + } + + #onAllowAllDocumentsChange(event: UUIBooleanInputEvent) { + event.stopPropagation(); + const target = event.target; + // TODO make contexts method + this.#workspaceContext?.updateProperty('hasDocumentRootAccess', target.checked); + this.#workspaceContext?.updateProperty('documentStartNodeUniques', []); + } + + #onDocumentStartNodeChange(event: CustomEvent) { + event.stopPropagation(); + const target = event.target as UmbInputDocumentElement; + const selection = target.selection; + // TODO make contexts method + this.#workspaceContext?.updateProperty('documentStartNodeUniques', selection); + } + + #onAllowAllMediaChange(event: UUIBooleanInputEvent) { + event.stopPropagation(); + const target = event.target; + // TODO make contexts method + this.#workspaceContext?.updateProperty('hasMediaRootAccess', target.checked); + this.#workspaceContext?.updateProperty('mediaStartNodeUniques', []); + } + + #onMediaStartNodeChange(event: CustomEvent) { + event.stopPropagation(); + const target = event.target as UmbInputMediaElement; + const selection = target.selection; + // TODO make contexts method + this.#workspaceContext?.updateProperty('mediaStartNodeUniques', selection); + } + + render() { + return html` + +
Assign Access
+
+ ${this.#renderGroupAccess()} ${this.#renderDocumentAccess()} ${this.#renderMediaAccess()} +
+
+ `; + } + + #renderGroupAccess() { + return html` + + `; + } + + #renderDocumentAccess() { + return html` + +
+ +
+ + ${this._documentRootAccess === false + ? html` + + ` + : nothing} +
+ `; + } + + #renderMediaAccess() { + return html` + +
+ +
+ + ${this._mediaRootAccess === false + ? html` + + ` + : nothing} +
+ `; + } + + static styles = [UmbTextStyles]; +} + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserWorkspaceAssignAccessElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts index ae421d9037..d54a8699f1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -10,7 +10,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; // import local components. Theses are not meant to be used outside of this component. import './components/user-workspace-profile-settings/user-workspace-profile-settings.element.js'; -import './components/user-workspace-access-settings/user-workspace-access-settings.element.js'; +import './components/user-workspace-access/user-workspace-access.element.js'; import './components/user-workspace-info/user-workspace-info.element.js'; import './components/user-workspace-avatar/user-workspace-avatar.element.js'; @@ -72,8 +72,9 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { if (!this._user) return nothing; return html` - + + + `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts index 2eecb90751..7bf10835fa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts @@ -23,6 +23,13 @@ export class UmbUserWorkspaceContext readonly data = this.#currentData.asObservable(); readonly state = this.#currentData.asObservablePart((x) => x?.state); readonly unique = this.#currentData.asObservablePart((x) => x?.unique); + readonly userGroupUniques = this.#currentData.asObservablePart((x) => x?.userGroupUniques || []); + readonly documentStartNodeUniques = this.#currentData.asObservablePart( + (data) => data?.documentStartNodeUniques || [], + ); + readonly hasDocumentRootAccess = this.#currentData.asObservablePart((data) => data?.hasDocumentRootAccess || false); + readonly mediaStartNodeUniques = this.#currentData.asObservablePart((data) => data?.mediaStartNodeUniques || []); + readonly hasMediaRootAccess = this.#currentData.asObservablePart((data) => data?.hasMediaRootAccess || false); readonly routes = new UmbWorkspaceRouteManager(this);