From 5a6dcf80ae833c190177a1a12dfc9beecc0d46ad Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 22 Aug 2024 16:50:16 +0000 Subject: [PATCH 001/322] Adds new method to extensionRegistry for appendCondition --- .../registry/extension.registry.test.ts | 83 ++++++++++++++++++- .../registry/extension.registry.ts | 29 ++++++- 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 83ee09d37b..0ad82590b7 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -1,4 +1,5 @@ -import type { ManifestElementWithElementName, ManifestKind, ManifestBase } from '../types/index.js'; +import { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; +import type { ManifestElementWithElementName, ManifestKind, ManifestBase, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; import { UmbExtensionRegistry } from './extension.registry.js'; import { expect } from '@open-wc/testing'; @@ -453,3 +454,83 @@ describe('UmbExtensionRegistry with exclusions', () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.Late')).to.be.false; }); }); + +describe('Append Conditions', () => { + let extensionRegistry: UmbExtensionRegistry; + let manifests: Array< + ManifestWithDynamicConditions + >; + + beforeEach(() => { + extensionRegistry = new UmbExtensionRegistry(); + manifests = [ + { + type: 'section', + name: 'test-section-1', + alias: 'Umb.Test.Section.1', + weight: 1, + conditions: [ + { + alias: "Umb.Test.Condition.Valid" + } + ] + }, + { + type: 'section', + name: 'test-section-2', + alias: 'Umb.Test.Section.2', + weight: 200 + }, + ]; + + manifests.forEach((manifest) => extensionRegistry.register(manifest)); + + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid' + }); + }); + + + it('allows an extension condition to be updated', () => { + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; + + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + // Register new condition as if I was in my own entrypoint + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-valid', + alias: 'Umb.Test.Condition.Valid' + }); + + // Add the new condition to the extension + const conditionToAdd:UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid' + }; + extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); + + // Check new condition is registered + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + + // Verify the extension now has two conditions + const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(updatedExt.conditions?.length).to.equal(2); + + // Add a condition with a specific config to Section2 + const workspaceCondition:WorkspaceAliasConditionConfig = { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document' + + }; + extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); + + const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; + expect(updatedWorkspaceExt.conditions?.length).to.equal(1); + }); +}); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 2680d599e9..a716615b16 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -1,4 +1,4 @@ -import type { ManifestBase, ManifestKind } from '../types/index.js'; +import type { ManifestBase, ManifestKind, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; @@ -430,4 +430,31 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } + + /** + * Appends a new condition to an existing extension + * Useful to add a condition for example the Save And Publish workspace action shipped by core + * As overwriting the whole extension to simply add an extra condition is not ideal as it causes a lot of duplicated code + * and could easily get out of sync from the CMS core implementation if a 3rd party dev was to try and overwrite it + * @param alias {string} - The alias of the extension to get. + * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. + */ + appendCondition(alias: string, newCondition: UmbConditionConfigBase) { + const allExtensions = this._extensions.getValue(); + const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + + if(extensionToUpdate === undefined) { + console.error(`Extension with alias ${alias} not found`); + } + + // Append the condition to the extensions conditions array + if (extensionToUpdate.conditions){ + extensionToUpdate.conditions.push(newCondition); + } else { + extensionToUpdate.conditions = [newCondition]; + } + + // Update the extensions observable + this._extensions.setValue(allExtensions); + } } From c6c80ddf290e35ecdb44c3640fc2ce274f0c50a0 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 23 Aug 2024 09:57:11 +0000 Subject: [PATCH 002/322] Adds appendConditions to allow adding multiple in one go --- .../registry/extension.registry.test.ts | 20 +++++++++++++++++++ .../registry/extension.registry.ts | 11 +++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 0ad82590b7..f6add8c5c2 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -533,4 +533,24 @@ describe('Append Conditions', () => { const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); }); + + it('allows an extension to update with multiple conditions', () => { + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + const conditions:Array = [ + { + alias: 'Umb.Test.Condition.Valid' + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document' + } as WorkspaceAliasConditionConfig + ] + + extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); + + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(3); + }); }); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index a716615b16..4311109022 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -436,7 +436,7 @@ export class UmbExtensionRegistry< * Useful to add a condition for example the Save And Publish workspace action shipped by core * As overwriting the whole extension to simply add an extra condition is not ideal as it causes a lot of duplicated code * and could easily get out of sync from the CMS core implementation if a 3rd party dev was to try and overwrite it - * @param alias {string} - The alias of the extension to get. + * @param alias {string} - The alias of the extension to append the condition to * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. */ appendCondition(alias: string, newCondition: UmbConditionConfigBase) { @@ -457,4 +457,13 @@ export class UmbExtensionRegistry< // Update the extensions observable this._extensions.setValue(allExtensions); } + + /** + * Appends a collection of conditions to an exsiting extension + * @param alias {string} - The alias of the extension to append the condition to + * @param newConditions {Array} - A collection of conditions to append to an extension. + */ + appendConditions(alias: string, newConditions: Array){ + newConditions.forEach((condition) => this.appendCondition(alias, condition)); + } } From be2f95a854439009ba8e141658603871d0be5917 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 29 Aug 2024 11:10:48 +0000 Subject: [PATCH 003/322] Adds prependCondition and prependConditions so you can make sure your condition loads first, as order of conditions are important --- .../registry/extension.registry.test.ts | 89 +++++++++++++++++++ .../registry/extension.registry.ts | 48 ++++++++-- 2 files changed, 132 insertions(+), 5 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index f6add8c5c2..9add871f65 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -554,3 +554,92 @@ describe('Append Conditions', () => { expect(ext.conditions?.length).to.equal(3); }); }); + +describe('Prepend Conditions', () => { + let extensionRegistry: UmbExtensionRegistry; + let manifests: Array; + + beforeEach(() => { + extensionRegistry = new UmbExtensionRegistry(); + manifests = [ + { + type: 'section', + name: 'test-section-1', + alias: 'Umb.Test.Section.1', + weight: 1, + conditions: [ + { + alias: "Umb.Test.Condition.Valid" + } + ] + }, + { + type: 'section', + name: 'test-section-2', + alias: 'Umb.Test.Section.2', + weight: 200 + }, + ]; + + manifests.forEach((manifest) => extensionRegistry.register(manifest)); + + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid' + }); + }); + + it('allows an extension condition to be prepended', () => { + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; + + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + // Register new condition as if I was in my own entrypoint + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-valid', + alias: 'Umb.Test.Condition.Valid' + }); + + // Prepend the new condition to the extension + const conditionToPrepend: UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid' + }; + extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); + + // Check new condition is registered + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + + // Verify the extension now has two conditions and the new condition is prepended + const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(updatedExt.conditions?.length).to.equal(2); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); + + it('allows an extension to update with multiple prepended conditions', () => { + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Valid' + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document' + } as WorkspaceAliasConditionConfig + ]; + + extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); +}); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 4311109022..f6e9f9d934 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -1,4 +1,9 @@ -import type { ManifestBase, ManifestKind, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; +import type { + ManifestBase, + ManifestKind, + ManifestWithDynamicConditions, + UmbConditionConfigBase, +} from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; @@ -430,7 +435,7 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } - + /** * Appends a new condition to an existing extension * Useful to add a condition for example the Save And Publish workspace action shipped by core @@ -443,12 +448,12 @@ export class UmbExtensionRegistry< const allExtensions = this._extensions.getValue(); const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; - if(extensionToUpdate === undefined) { + if (extensionToUpdate === undefined) { console.error(`Extension with alias ${alias} not found`); } // Append the condition to the extensions conditions array - if (extensionToUpdate.conditions){ + if (extensionToUpdate.conditions) { extensionToUpdate.conditions.push(newCondition); } else { extensionToUpdate.conditions = [newCondition]; @@ -463,7 +468,40 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to append the condition to * @param newConditions {Array} - A collection of conditions to append to an extension. */ - appendConditions(alias: string, newConditions: Array){ + appendConditions(alias: string, newConditions: Array) { newConditions.forEach((condition) => this.appendCondition(alias, condition)); } + + /** + * Prepends a new condition to an existing extension + * @param alias {string} - The alias of the extension to prepend the condition to + * @param newCondition {UmbConditionConfigBase} - The condition to prepend to the extension. + */ + prependCondition(alias: string, newCondition: UmbConditionConfigBase) { + const allExtensions = this._extensions.getValue(); + const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + + if (extensionToUpdate === undefined) { + console.error(`Extension with alias ${alias} not found`); + } + + // Prepend the condition to the extensions conditions array + if (extensionToUpdate.conditions) { + extensionToUpdate.conditions.unshift(newCondition); + } else { + extensionToUpdate.conditions = [newCondition]; + } + + // Update the extensions observable + this._extensions.setValue(allExtensions); + } + + /** + * Prepends a collection of conditions to an existing extension + * @param alias {string} - The alias of the extension to prepend the conditions to + * @param newConditions {Array} - A collection of conditions to prepend to an extension. + */ + prependConditions(alias: string, newConditions: Array) { + newConditions.forEach((condition) => this.prependCondition(alias, condition)); + } } From 6e3a3e6112d579cfc69bca4011b2caa884f71d76 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 29 Aug 2024 16:14:06 +0000 Subject: [PATCH 004/322] Adds _whenExtensionAliasIsRegistered as a promise so that we basically wait until the manifest is registered so late extensions will work as well Seems to work with my hack in an entrypoint and the console logs the extension with the updated condition but its the tests I am struggling to get to work. As this code is heavily worked from me trying to Google, read RXJS docs and talking with Copilot I am not fully in confident in this approach --- .../registry/extension.registry.test.ts | 19 +-- .../registry/extension.registry.ts | 114 +++++++++++++----- src/packages/property-editors/entry-point.ts | 31 +++++ 3 files changed, 123 insertions(+), 41 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 9add871f65..94c5fccbf5 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -493,7 +493,7 @@ describe('Append Conditions', () => { }); - it('allows an extension condition to be updated', () => { + it('allows an extension condition to be updated', async () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; @@ -513,7 +513,7 @@ describe('Append Conditions', () => { const conditionToAdd:UmbConditionConfigBase = { alias: 'Umb.Test.Condition.Valid' }; - extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); + await extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; @@ -528,13 +528,13 @@ describe('Append Conditions', () => { match: 'Umb.Workspace.Document' }; - extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); + await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); }); - it('allows an extension to update with multiple conditions', () => { + it('allows an extension to update with multiple conditions', async () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); @@ -548,7 +548,7 @@ describe('Append Conditions', () => { } as WorkspaceAliasConditionConfig ] - extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(3); @@ -590,7 +590,7 @@ describe('Prepend Conditions', () => { }); }); - it('allows an extension condition to be prepended', () => { + it('allows an extension condition to be prepended', async () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; @@ -610,7 +610,8 @@ describe('Prepend Conditions', () => { const conditionToPrepend: UmbConditionConfigBase = { alias: 'Umb.Test.Condition.Valid' }; - extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); + + await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; @@ -621,7 +622,7 @@ describe('Prepend Conditions', () => { expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); }); - it('allows an extension to update with multiple prepended conditions', () => { + it('allows an extension to update with multiple prepended conditions', async () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); @@ -635,7 +636,7 @@ describe('Prepend Conditions', () => { } as WorkspaceAliasConditionConfig ]; - extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(extUpdated.conditions?.length).to.equal(3); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index f6e9f9d934..7d2837de3e 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -6,8 +6,8 @@ import type { } from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; -import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import { map, distinctUntilChanged, combineLatest, of, switchMap } from '@umbraco-cms/backoffice/external/rxjs'; +import type { Observable, Subscription } from '@umbraco-cms/backoffice/external/rxjs'; +import { map, distinctUntilChanged, combineLatest, of, switchMap, filter } from '@umbraco-cms/backoffice/external/rxjs'; /** * @@ -436,6 +436,37 @@ export class UmbExtensionRegistry< ) as Observable>; } + + /** + * Returns a promise that resolves when the extension with the specified alias is found. + * @param alias {string} - The alias of the extension to wait for. + * @returns {Promise} - A promise that resolves with the extension. + */ + private _whenExtensionAliasIsRegistered(alias: string): Promise { + return new Promise((resolve, reject) => { + const subscription: Subscription = this.extensions + .pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))) + .subscribe({ + next: (allExtensions) => { + console.log('I AM IN NEXT', allExtensions); + const extension = allExtensions.find((ext) => ext.alias === alias); + if (extension) { + subscription.unsubscribe(); + resolve(extension as ManifestBase); + } + }, + error: (error) => { + console.error('I AM IN ERROR', error); + reject(error); + }, + complete: () => { + console.log('I AM IN COMPLETE'); + reject(new Error(`Extension with alias ${alias} not found`)); + }, + }); + }); + } + /** * Appends a new condition to an existing extension * Useful to add a condition for example the Save And Publish workspace action shipped by core @@ -444,23 +475,39 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to append the condition to * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. */ - appendCondition(alias: string, newCondition: UmbConditionConfigBase) { - const allExtensions = this._extensions.getValue(); - const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + async appendCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { + try { - if (extensionToUpdate === undefined) { - console.error(`Extension with alias ${alias} not found`); - } + // Wait for the extension to be registered (as it could be registered late) + const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - // Append the condition to the extensions conditions array - if (extensionToUpdate.conditions) { - extensionToUpdate.conditions.push(newCondition); - } else { - extensionToUpdate.conditions = [newCondition]; - } + // Got it... now carry on & mutate it + console.log('got the extension to update/mutate', extensionToWaitFor); + + // Append the condition to the extensions conditions array + if (extensionToWaitFor.conditions) { + extensionToWaitFor.conditions.push(newCondition); + } else { + extensionToWaitFor.conditions = [newCondition]; + } - // Update the extensions observable - this._extensions.setValue(allExtensions); + const allExtensions = this._extensions.getValue(); + const extensionToUpdateIndex = allExtensions.findIndex((ext) => ext.alias === alias); + if (extensionToUpdateIndex !== -1) { + // Replace the existing extension with the updated one + allExtensions[extensionToUpdateIndex] = extensionToWaitFor as ManifestTypes; + + // Update the main extensions collection/observable + this._extensions.setValue(allExtensions); + + // Log the updated extensions for debugging + console.log('UPDATED extensions:', this._extensions.getValue()); + console.table(this._extensions.getValue()); + } + } catch (error) { + // TODO: [WB] Will this ever catch an error? + console.error(`Extension with alias ${alias} was never found and threw ${error}`); + } } /** @@ -468,7 +515,7 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to append the condition to * @param newConditions {Array} - A collection of conditions to append to an extension. */ - appendConditions(alias: string, newConditions: Array) { + async appendConditions(alias: string, newConditions: Array): Promise { newConditions.forEach((condition) => this.appendCondition(alias, condition)); } @@ -477,23 +524,26 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to prepend the condition to * @param newCondition {UmbConditionConfigBase} - The condition to prepend to the extension. */ - prependCondition(alias: string, newCondition: UmbConditionConfigBase) { - const allExtensions = this._extensions.getValue(); - const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + async prependCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { + try { - if (extensionToUpdate === undefined) { - console.error(`Extension with alias ${alias} not found`); - } + // Wait for the extension to be registered (as it could be registered late) + const extensionToUpdate = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - // Prepend the condition to the extensions conditions array - if (extensionToUpdate.conditions) { - extensionToUpdate.conditions.unshift(newCondition); - } else { - extensionToUpdate.conditions = [newCondition]; - } + // Got it... now carry on & mutate it + console.log('got the extension to update/mutate', extensionToUpdate); + + // Append the condition to the extensions conditions array + if (extensionToUpdate.conditions) { + extensionToUpdate.conditions.unshift(newCondition); + } else { + extensionToUpdate.conditions = [newCondition]; + } - // Update the extensions observable - this._extensions.setValue(allExtensions); + } catch (error) { + // TODO: [WB] Will this ever catch an error? + console.error(`Extension with alias ${alias} was never found and threw ${error}`); + } } /** @@ -501,7 +551,7 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to prepend the conditions to * @param newConditions {Array} - A collection of conditions to prepend to an extension. */ - prependConditions(alias: string, newConditions: Array) { + async prependConditions(alias: string, newConditions: Array): Promise { newConditions.forEach((condition) => this.prependCondition(alias, condition)); } } diff --git a/src/packages/property-editors/entry-point.ts b/src/packages/property-editors/entry-point.ts index 9745b0d139..baafe2af43 100644 --- a/src/packages/property-editors/entry-point.ts +++ b/src/packages/property-editors/entry-point.ts @@ -1,2 +1,33 @@ +import type { ManifestWithDynamicConditions, UmbConditionConfigBase, UmbEntryPointOnInit } from '@umbraco-cms/backoffice/extension-api'; +import type { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; + import './checkbox-list/components/index.js'; import './content-picker/components/index.js'; + +export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { + + console.log('HELLO AGAIN'); + + const condition: UmbConditionConfigBase = { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.WARRENYO', + } as WorkspaceAliasConditionConfig; + + _extensionRegistry.appendCondition('Umb.Dashboard.UmbracoNewsLATE', condition); + + const ext:ManifestWithDynamicConditions = { + alias: 'Umb.Dashboard.UmbracoNewsLATE', + type: 'dashboard', + name: 'WARREN Package', + weight: 100, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.LATE-COMER-EXISTING', + } as WorkspaceAliasConditionConfig, + ], + }; + + _extensionRegistry.register(ext); + +}; From 3ba83153b15106f667030b08e066fc0051f40431 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 10:19:27 +0200 Subject: [PATCH 005/322] simplify _whenExtensionAliasIsRegistered --- .../registry/extension.registry.ts | 43 ++++++------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 7d2837de3e..e21077c4ab 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -6,8 +6,16 @@ import type { } from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; -import type { Observable, Subscription } from '@umbraco-cms/backoffice/external/rxjs'; -import { map, distinctUntilChanged, combineLatest, of, switchMap, filter } from '@umbraco-cms/backoffice/external/rxjs'; +import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; +import { + map, + distinctUntilChanged, + combineLatest, + of, + switchMap, + filter, + firstValueFrom, +} from '@umbraco-cms/backoffice/external/rxjs'; /** * @@ -436,35 +444,15 @@ export class UmbExtensionRegistry< ) as Observable>; } - /** * Returns a promise that resolves when the extension with the specified alias is found. * @param alias {string} - The alias of the extension to wait for. * @returns {Promise} - A promise that resolves with the extension. */ - private _whenExtensionAliasIsRegistered(alias: string): Promise { - return new Promise((resolve, reject) => { - const subscription: Subscription = this.extensions - .pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))) - .subscribe({ - next: (allExtensions) => { - console.log('I AM IN NEXT', allExtensions); - const extension = allExtensions.find((ext) => ext.alias === alias); - if (extension) { - subscription.unsubscribe(); - resolve(extension as ManifestBase); - } - }, - error: (error) => { - console.error('I AM IN ERROR', error); - reject(error); - }, - complete: () => { - console.log('I AM IN COMPLETE'); - reject(new Error(`Extension with alias ${alias} not found`)); - }, - }); - }); + private async _whenExtensionAliasIsRegistered(alias: string): Promise { + const source = this.extensions.pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))); + const value = await firstValueFrom(source); + return value[0]; } /** @@ -477,7 +465,6 @@ export class UmbExtensionRegistry< */ async appendCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { try { - // Wait for the extension to be registered (as it could be registered late) const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; @@ -526,7 +513,6 @@ export class UmbExtensionRegistry< */ async prependCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { try { - // Wait for the extension to be registered (as it could be registered late) const extensionToUpdate = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; @@ -539,7 +525,6 @@ export class UmbExtensionRegistry< } else { extensionToUpdate.conditions = [newCondition]; } - } catch (error) { // TODO: [WB] Will this ever catch an error? console.error(`Extension with alias ${alias} was never found and threw ${error}`); From 130646d9f8bc4460f17bab1acf4238b1b71af6be Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 10:22:24 +0200 Subject: [PATCH 006/322] split some tests --- .../registry/extension.registry.test.ts | 188 +++++++++--------- 1 file changed, 97 insertions(+), 91 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 94c5fccbf5..dd1e8612f9 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -1,5 +1,11 @@ import { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; -import type { ManifestElementWithElementName, ManifestKind, ManifestBase, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; +import type { + ManifestElementWithElementName, + ManifestKind, + ManifestBase, + ManifestWithDynamicConditions, + UmbConditionConfigBase, +} from '../types/index.js'; import { UmbExtensionRegistry } from './extension.registry.js'; import { expect } from '@open-wc/testing'; @@ -457,9 +463,7 @@ describe('UmbExtensionRegistry with exclusions', () => { describe('Append Conditions', () => { let extensionRegistry: UmbExtensionRegistry; - let manifests: Array< - ManifestWithDynamicConditions - >; + let manifests: Array; beforeEach(() => { extensionRegistry = new UmbExtensionRegistry(); @@ -471,15 +475,15 @@ describe('Append Conditions', () => { weight: 1, conditions: [ { - alias: "Umb.Test.Condition.Valid" - } - ] + alias: 'Umb.Test.Condition.Valid', + }, + ], }, { type: 'section', name: 'test-section-2', alias: 'Umb.Test.Section.2', - weight: 200 + weight: 200, }, ]; @@ -488,17 +492,18 @@ describe('Append Conditions', () => { extensionRegistry.register({ type: 'condition', name: 'test-condition-invalid', - alias: 'Umb.Test.Condition.Invalid' + alias: 'Umb.Test.Condition.Invalid', }); }); - - it('allows an extension condition to be updated', async () => { + it('should have the extensions registered', () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; + }); + it('allows an extension condition to be updated', async () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); @@ -506,12 +511,12 @@ describe('Append Conditions', () => { extensionRegistry.register({ type: 'condition', name: 'test-condition-valid', - alias: 'Umb.Test.Condition.Valid' + alias: 'Umb.Test.Condition.Valid', }); // Add the new condition to the extension - const conditionToAdd:UmbConditionConfigBase = { - alias: 'Umb.Test.Condition.Valid' + const conditionToAdd: UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid', }; await extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); @@ -523,10 +528,9 @@ describe('Append Conditions', () => { expect(updatedExt.conditions?.length).to.equal(2); // Add a condition with a specific config to Section2 - const workspaceCondition:WorkspaceAliasConditionConfig = { + const workspaceCondition: WorkspaceAliasConditionConfig = { alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document' - + match: 'Umb.Workspace.Document', }; await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); @@ -538,15 +542,15 @@ describe('Append Conditions', () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); - const conditions:Array = [ + const conditions: Array = [ { - alias: 'Umb.Test.Condition.Valid' + alias: 'Umb.Test.Condition.Valid', }, { alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document' - } as WorkspaceAliasConditionConfig - ] + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); @@ -560,87 +564,89 @@ describe('Prepend Conditions', () => { let manifests: Array; beforeEach(() => { - extensionRegistry = new UmbExtensionRegistry(); - manifests = [ - { - type: 'section', - name: 'test-section-1', - alias: 'Umb.Test.Section.1', - weight: 1, - conditions: [ - { - alias: "Umb.Test.Condition.Valid" - } - ] - }, + extensionRegistry = new UmbExtensionRegistry(); + manifests = [ + { + type: 'section', + name: 'test-section-1', + alias: 'Umb.Test.Section.1', + weight: 1, + conditions: [ { - type: 'section', - name: 'test-section-2', - alias: 'Umb.Test.Section.2', - weight: 200 + alias: 'Umb.Test.Condition.Valid', }, - ]; + ], + }, + { + type: 'section', + name: 'test-section-2', + alias: 'Umb.Test.Section.2', + weight: 200, + }, + ]; - manifests.forEach((manifest) => extensionRegistry.register(manifest)); + manifests.forEach((manifest) => extensionRegistry.register(manifest)); - extensionRegistry.register({ - type: 'condition', - name: 'test-condition-invalid', - alias: 'Umb.Test.Condition.Invalid' - }); + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid', + }); + }); + + it('should have the extensions registered', () => { + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; }); it('allows an extension condition to be prepended', async () => { - expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; - - const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(1); - - // Register new condition as if I was in my own entrypoint - extensionRegistry.register({ - type: 'condition', - name: 'test-condition-valid', - alias: 'Umb.Test.Condition.Valid' - }); - - // Prepend the new condition to the extension - const conditionToPrepend: UmbConditionConfigBase = { - alias: 'Umb.Test.Condition.Valid' - }; - - await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); - - // Check new condition is registered - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; - - // Verify the extension now has two conditions and the new condition is prepended - const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(updatedExt.conditions?.length).to.equal(2); - expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + // Register new condition as if I was in my own entrypoint + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-valid', + alias: 'Umb.Test.Condition.Valid', + }); + + // Prepend the new condition to the extension + const conditionToPrepend: UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid', + }; + + await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); + + // Check new condition is registered + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + + // Verify the extension now has two conditions and the new condition is prepended + const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(updatedExt.conditions?.length).to.equal(2); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); }); it('allows an extension to update with multiple prepended conditions', async () => { - const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(1); + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); - const conditions: Array = [ - { - alias: 'Umb.Test.Condition.Valid' - }, - { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document' - } as WorkspaceAliasConditionConfig - ]; + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Valid', + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; - await extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); - const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(extUpdated.conditions?.length).to.equal(3); - expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); }); }); From 900e98b71446ad151e13d8d91cdd5efa070d4cee Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 30 Aug 2024 11:43:31 +0100 Subject: [PATCH 007/322] Rework of tests to pass and minor fix to _whenExtensionAliasIsRegistered to get the ext alias that matches --- .../registry/extension.registry.test.ts | 56 +++++++++++-------- .../registry/extension.registry.ts | 21 +++---- 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index dd1e8612f9..e089f1bd17 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -475,7 +475,7 @@ describe('Append Conditions', () => { weight: 1, conditions: [ { - alias: 'Umb.Test.Condition.Valid', + alias: 'Umb.Test.Condition.Invalid', }, ], }, @@ -483,7 +483,7 @@ describe('Append Conditions', () => { type: 'section', name: 'test-section-2', alias: 'Umb.Test.Section.2', - weight: 200, + weight: 200 }, ]; @@ -523,19 +523,23 @@ describe('Append Conditions', () => { // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; - // Verify the extension now has two conditions + // Verify the extension now has two conditions and in correct order with aliases const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(updatedExt.conditions?.length).to.equal(2); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(updatedExt.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); // Add a condition with a specific config to Section2 const workspaceCondition: WorkspaceAliasConditionConfig = { alias: 'Umb.Condition.WorkspaceAlias', match: 'Umb.Workspace.Document', }; + await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); + expect(updatedWorkspaceExt.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); }); it('allows an extension to update with multiple conditions', async () => { @@ -555,7 +559,10 @@ describe('Append Conditions', () => { await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); }); }); @@ -582,59 +589,60 @@ describe('Prepend Conditions', () => { name: 'test-section-2', alias: 'Umb.Test.Section.2', weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], }, ]; manifests.forEach((manifest) => extensionRegistry.register(manifest)); - - extensionRegistry.register({ - type: 'condition', - name: 'test-condition-invalid', - alias: 'Umb.Test.Condition.Invalid', - }); }); it('should have the extensions registered', () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.false; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; }); it('allows an extension condition to be prepended', async () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); + expect(ext.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); - // Register new condition as if I was in my own entrypoint extensionRegistry.register({ type: 'condition', - name: 'test-condition-valid', - alias: 'Umb.Test.Condition.Valid', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid', }); // Prepend the new condition to the extension const conditionToPrepend: UmbConditionConfigBase = { - alias: 'Umb.Test.Condition.Valid', + alias: 'Umb.Test.Condition.Invalid', }; await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); // Check new condition is registered - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; // Verify the extension now has two conditions and the new condition is prepended const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(updatedExt.conditions?.length).to.equal(2); - expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); // Our new one prepended + expect(updatedExt.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); }); it('allows an extension to update with multiple prepended conditions', async () => { - const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + const ext = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); + expect(ext.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); const conditions: Array = [ { - alias: 'Umb.Test.Condition.Valid', + alias: 'Umb.Test.Condition.Invalid', }, { alias: 'Umb.Condition.WorkspaceAlias', @@ -642,11 +650,15 @@ describe('Prepend Conditions', () => { } as WorkspaceAliasConditionConfig, ]; - await extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.prependConditions('Umb.Test.Section.2', conditions); - const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(extUpdated.conditions?.length).to.equal(3); + + // The thing to note here our two new conditions is that are prepended in reverse order they are passed in + // as each one is prepended to the front of the array expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); }); }); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index e21077c4ab..5cd0dbcbe8 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -452,7 +452,8 @@ export class UmbExtensionRegistry< private async _whenExtensionAliasIsRegistered(alias: string): Promise { const source = this.extensions.pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))); const value = await firstValueFrom(source); - return value[0]; + const ext = value.find((ext) => ext.alias === alias) as ManifestBase; + return ext; } /** @@ -468,9 +469,6 @@ export class UmbExtensionRegistry< // Wait for the extension to be registered (as it could be registered late) const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - // Got it... now carry on & mutate it - console.log('got the extension to update/mutate', extensionToWaitFor); - // Append the condition to the extensions conditions array if (extensionToWaitFor.conditions) { extensionToWaitFor.conditions.push(newCondition); @@ -486,10 +484,6 @@ export class UmbExtensionRegistry< // Update the main extensions collection/observable this._extensions.setValue(allExtensions); - - // Log the updated extensions for debugging - console.log('UPDATED extensions:', this._extensions.getValue()); - console.table(this._extensions.getValue()); } } catch (error) { // TODO: [WB] Will this ever catch an error? @@ -503,7 +497,9 @@ export class UmbExtensionRegistry< * @param newConditions {Array} - A collection of conditions to append to an extension. */ async appendConditions(alias: string, newConditions: Array): Promise { - newConditions.forEach((condition) => this.appendCondition(alias, condition)); + for (const condition of newConditions) { + await this.appendCondition(alias, condition); + } } /** @@ -516,9 +512,6 @@ export class UmbExtensionRegistry< // Wait for the extension to be registered (as it could be registered late) const extensionToUpdate = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - // Got it... now carry on & mutate it - console.log('got the extension to update/mutate', extensionToUpdate); - // Append the condition to the extensions conditions array if (extensionToUpdate.conditions) { extensionToUpdate.conditions.unshift(newCondition); @@ -537,6 +530,8 @@ export class UmbExtensionRegistry< * @param newConditions {Array} - A collection of conditions to prepend to an extension. */ async prependConditions(alias: string, newConditions: Array): Promise { - newConditions.forEach((condition) => this.prependCondition(alias, condition)); + for (const condition of newConditions) { + await this.prependCondition(alias, condition); + } } } From 7a0a86e32b6da54523a8f02cac909c5d16c68f07 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 30 Aug 2024 13:27:48 +0100 Subject: [PATCH 008/322] Trying to add a test to show that a late registered extension works - but test says otherwise compared to using it in entrypoint --- .../registry/extension.registry.test.ts | 46 ++++++++++++++++++- src/packages/property-editors/entry-point.ts | 20 +++++++- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index e089f1bd17..b38fdac8b2 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -483,7 +483,7 @@ describe('Append Conditions', () => { type: 'section', name: 'test-section-2', alias: 'Umb.Test.Section.2', - weight: 200 + weight: 200, }, ]; @@ -661,4 +661,48 @@ describe('Prepend Conditions', () => { expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); }); + + it('allows conditions to be prepended when an extension is loaded later on', async () => { + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Invalid', + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; + + console.log('About to go KABOOM..'); + + // Prepend the conditions + // [WB] HELP: Why is this fine when using in in an entrypoint + // /src/packages/property-editors/entry-point.ts + // But this TEST implodes if it can't find the extension that is not yet registered + await extensionRegistry.prependConditions('Late.Extension.To.Be.Loaded', conditions); + + // Make sure the extension is not registered YET + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // Register the extension LATE/after the conditions have been added + extensionRegistry.register({ + type: 'section', + name: 'Late Section Extension with one condition', + alias: 'Late.Extension.To.Be.Loaded', + weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], + }); + + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); }); diff --git a/src/packages/property-editors/entry-point.ts b/src/packages/property-editors/entry-point.ts index baafe2af43..64d64bc9c4 100644 --- a/src/packages/property-editors/entry-point.ts +++ b/src/packages/property-editors/entry-point.ts @@ -1,4 +1,8 @@ -import type { ManifestWithDynamicConditions, UmbConditionConfigBase, UmbEntryPointOnInit } from '@umbraco-cms/backoffice/extension-api'; +import type { + ManifestWithDynamicConditions, + UmbConditionConfigBase, + UmbEntryPointOnInit, +} from '@umbraco-cms/backoffice/extension-api'; import type { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; import './checkbox-list/components/index.js'; @@ -13,9 +17,16 @@ export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { match: 'Umb.Workspace.WARRENYO', } as WorkspaceAliasConditionConfig; + console.log( + 'Should not be false and not registered', + _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'), + ); + _extensionRegistry.appendCondition('Umb.Dashboard.UmbracoNewsLATE', condition); - const ext:ManifestWithDynamicConditions = { + console.log('I HAZ APPENED CONDITIONS'); + + const ext: ManifestWithDynamicConditions = { alias: 'Umb.Dashboard.UmbracoNewsLATE', type: 'dashboard', name: 'WARREN Package', @@ -30,4 +41,9 @@ export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { _extensionRegistry.register(ext); + const amIRegistered = _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'); + console.log('Should be true and registered', amIRegistered); + + const getTheThing = _extensionRegistry.getByAlias('Umb.Dashboard.UmbracoNewsLATE'); + console.log('Should be the extension', getTheThing); }; From ac3b2ba1deb742e60f8a9e2ce163eb020cb8e004 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 20:36:10 +0200 Subject: [PATCH 009/322] generate new server client --- src/external/backend-api/src/services.gen.ts | 66 ++++++++++-- src/external/backend-api/src/types.gen.ts | 106 ++++++++++++++++++- 2 files changed, 161 insertions(+), 11 deletions(-) diff --git a/src/external/backend-api/src/services.gen.ts b/src/external/backend-api/src/services.gen.ts index c6edaee403..63fb202bed 100644 --- a/src/external/backend-api/src/services.gen.ts +++ b/src/external/backend-api/src/services.gen.ts @@ -3,7 +3,7 @@ import type { CancelablePromise } from './core/CancelablePromise'; import { OpenAPI } from './core/OpenAPI'; import { request as __request } from './core/request'; -import type { GetCultureData, GetCultureResponse, PostDataTypeData, PostDataTypeResponse, GetDataTypeByIdData, GetDataTypeByIdResponse, DeleteDataTypeByIdData, DeleteDataTypeByIdResponse, PutDataTypeByIdData, PutDataTypeByIdResponse, PostDataTypeByIdCopyData, PostDataTypeByIdCopyResponse, GetDataTypeByIdIsUsedData, GetDataTypeByIdIsUsedResponse, PutDataTypeByIdMoveData, PutDataTypeByIdMoveResponse, GetDataTypeByIdReferencesData, GetDataTypeByIdReferencesResponse, GetDataTypeConfigurationResponse, PostDataTypeFolderData, PostDataTypeFolderResponse, GetDataTypeFolderByIdData, GetDataTypeFolderByIdResponse, DeleteDataTypeFolderByIdData, DeleteDataTypeFolderByIdResponse, PutDataTypeFolderByIdData, PutDataTypeFolderByIdResponse, GetFilterDataTypeData, GetFilterDataTypeResponse, GetItemDataTypeData, GetItemDataTypeResponse, GetItemDataTypeSearchData, GetItemDataTypeSearchResponse, GetTreeDataTypeAncestorsData, GetTreeDataTypeAncestorsResponse, GetTreeDataTypeChildrenData, GetTreeDataTypeChildrenResponse, GetTreeDataTypeRootData, GetTreeDataTypeRootResponse, GetDictionaryData, GetDictionaryResponse, PostDictionaryData, PostDictionaryResponse, GetDictionaryByIdData, GetDictionaryByIdResponse, DeleteDictionaryByIdData, DeleteDictionaryByIdResponse, PutDictionaryByIdData, PutDictionaryByIdResponse, GetDictionaryByIdExportData, GetDictionaryByIdExportResponse, PutDictionaryByIdMoveData, PutDictionaryByIdMoveResponse, PostDictionaryImportData, PostDictionaryImportResponse, GetItemDictionaryData, GetItemDictionaryResponse, GetTreeDictionaryAncestorsData, GetTreeDictionaryAncestorsResponse, GetTreeDictionaryChildrenData, GetTreeDictionaryChildrenResponse, GetTreeDictionaryRootData, GetTreeDictionaryRootResponse, PostDocumentBlueprintData, PostDocumentBlueprintResponse, GetDocumentBlueprintByIdData, GetDocumentBlueprintByIdResponse, DeleteDocumentBlueprintByIdData, DeleteDocumentBlueprintByIdResponse, PutDocumentBlueprintByIdData, PutDocumentBlueprintByIdResponse, PutDocumentBlueprintByIdMoveData, PutDocumentBlueprintByIdMoveResponse, PostDocumentBlueprintFolderData, PostDocumentBlueprintFolderResponse, GetDocumentBlueprintFolderByIdData, GetDocumentBlueprintFolderByIdResponse, DeleteDocumentBlueprintFolderByIdData, DeleteDocumentBlueprintFolderByIdResponse, PutDocumentBlueprintFolderByIdData, PutDocumentBlueprintFolderByIdResponse, PostDocumentBlueprintFromDocumentData, PostDocumentBlueprintFromDocumentResponse, GetItemDocumentBlueprintData, GetItemDocumentBlueprintResponse, GetTreeDocumentBlueprintAncestorsData, GetTreeDocumentBlueprintAncestorsResponse, GetTreeDocumentBlueprintChildrenData, GetTreeDocumentBlueprintChildrenResponse, GetTreeDocumentBlueprintRootData, GetTreeDocumentBlueprintRootResponse, PostDocumentTypeData, PostDocumentTypeResponse, GetDocumentTypeByIdData, GetDocumentTypeByIdResponse, DeleteDocumentTypeByIdData, DeleteDocumentTypeByIdResponse, PutDocumentTypeByIdData, PutDocumentTypeByIdResponse, GetDocumentTypeByIdAllowedChildrenData, GetDocumentTypeByIdAllowedChildrenResponse, GetDocumentTypeByIdBlueprintData, GetDocumentTypeByIdBlueprintResponse, GetDocumentTypeByIdCompositionReferencesData, GetDocumentTypeByIdCompositionReferencesResponse, PostDocumentTypeByIdCopyData, PostDocumentTypeByIdCopyResponse, GetDocumentTypeByIdExportData, GetDocumentTypeByIdExportResponse, PutDocumentTypeByIdImportData, PutDocumentTypeByIdImportResponse, PutDocumentTypeByIdMoveData, PutDocumentTypeByIdMoveResponse, GetDocumentTypeAllowedAtRootData, GetDocumentTypeAllowedAtRootResponse, PostDocumentTypeAvailableCompositionsData, PostDocumentTypeAvailableCompositionsResponse, GetDocumentTypeConfigurationResponse, PostDocumentTypeFolderData, PostDocumentTypeFolderResponse, GetDocumentTypeFolderByIdData, GetDocumentTypeFolderByIdResponse, DeleteDocumentTypeFolderByIdData, DeleteDocumentTypeFolderByIdResponse, PutDocumentTypeFolderByIdData, PutDocumentTypeFolderByIdResponse, PostDocumentTypeImportData, PostDocumentTypeImportResponse, GetItemDocumentTypeData, GetItemDocumentTypeResponse, GetItemDocumentTypeSearchData, GetItemDocumentTypeSearchResponse, GetTreeDocumentTypeAncestorsData, GetTreeDocumentTypeAncestorsResponse, GetTreeDocumentTypeChildrenData, GetTreeDocumentTypeChildrenResponse, GetTreeDocumentTypeRootData, GetTreeDocumentTypeRootResponse, GetDocumentVersionData, GetDocumentVersionResponse, GetDocumentVersionByIdData, GetDocumentVersionByIdResponse, PutDocumentVersionByIdPreventCleanupData, PutDocumentVersionByIdPreventCleanupResponse, PostDocumentVersionByIdRollbackData, PostDocumentVersionByIdRollbackResponse, GetCollectionDocumentByIdData, GetCollectionDocumentByIdResponse, PostDocumentData, PostDocumentResponse, GetDocumentByIdData, GetDocumentByIdResponse, DeleteDocumentByIdData, DeleteDocumentByIdResponse, PutDocumentByIdData, PutDocumentByIdResponse, GetDocumentByIdAuditLogData, GetDocumentByIdAuditLogResponse, PostDocumentByIdCopyData, PostDocumentByIdCopyResponse, GetDocumentByIdDomainsData, GetDocumentByIdDomainsResponse, PutDocumentByIdDomainsData, PutDocumentByIdDomainsResponse, PutDocumentByIdMoveData, PutDocumentByIdMoveResponse, PutDocumentByIdMoveToRecycleBinData, PutDocumentByIdMoveToRecycleBinResponse, GetDocumentByIdNotificationsData, GetDocumentByIdNotificationsResponse, PutDocumentByIdNotificationsData, PutDocumentByIdNotificationsResponse, PostDocumentByIdPublicAccessData, PostDocumentByIdPublicAccessResponse, DeleteDocumentByIdPublicAccessData, DeleteDocumentByIdPublicAccessResponse, GetDocumentByIdPublicAccessData, GetDocumentByIdPublicAccessResponse, PutDocumentByIdPublicAccessData, PutDocumentByIdPublicAccessResponse, PutDocumentByIdPublishData, PutDocumentByIdPublishResponse, PutDocumentByIdPublishWithDescendantsData, PutDocumentByIdPublishWithDescendantsResponse, GetDocumentByIdReferencedByData, GetDocumentByIdReferencedByResponse, GetDocumentByIdReferencedDescendantsData, GetDocumentByIdReferencedDescendantsResponse, PutDocumentByIdUnpublishData, PutDocumentByIdUnpublishResponse, PutDocumentByIdValidateData, PutDocumentByIdValidateResponse, GetDocumentAreReferencedData, GetDocumentAreReferencedResponse, GetDocumentConfigurationResponse, PutDocumentSortData, PutDocumentSortResponse, GetDocumentUrlsData, GetDocumentUrlsResponse, PostDocumentValidateData, PostDocumentValidateResponse, GetItemDocumentData, GetItemDocumentResponse, GetItemDocumentSearchData, GetItemDocumentSearchResponse, DeleteRecycleBinDocumentResponse, DeleteRecycleBinDocumentByIdData, DeleteRecycleBinDocumentByIdResponse, GetRecycleBinDocumentByIdOriginalParentData, GetRecycleBinDocumentByIdOriginalParentResponse, PutRecycleBinDocumentByIdRestoreData, PutRecycleBinDocumentByIdRestoreResponse, GetRecycleBinDocumentChildrenData, GetRecycleBinDocumentChildrenResponse, GetRecycleBinDocumentRootData, GetRecycleBinDocumentRootResponse, GetTreeDocumentAncestorsData, GetTreeDocumentAncestorsResponse, GetTreeDocumentChildrenData, GetTreeDocumentChildrenResponse, GetTreeDocumentRootData, GetTreeDocumentRootResponse, PostDynamicRootQueryData, PostDynamicRootQueryResponse, GetDynamicRootStepsResponse, GetHealthCheckGroupData, GetHealthCheckGroupResponse, GetHealthCheckGroupByNameData, GetHealthCheckGroupByNameResponse, PostHealthCheckGroupByNameCheckData, PostHealthCheckGroupByNameCheckResponse, PostHealthCheckExecuteActionData, PostHealthCheckExecuteActionResponse, GetHelpData, GetHelpResponse, GetImagingResizeUrlsData, GetImagingResizeUrlsResponse, GetImportAnalyzeData, GetImportAnalyzeResponse, GetIndexerData, GetIndexerResponse, GetIndexerByIndexNameData, GetIndexerByIndexNameResponse, PostIndexerByIndexNameRebuildData, PostIndexerByIndexNameRebuildResponse, GetInstallSettingsResponse, PostInstallSetupData, PostInstallSetupResponse, PostInstallValidateDatabaseData, PostInstallValidateDatabaseResponse, GetItemLanguageData, GetItemLanguageResponse, GetItemLanguageDefaultResponse, GetLanguageData, GetLanguageResponse, PostLanguageData, PostLanguageResponse, GetLanguageByIsoCodeData, GetLanguageByIsoCodeResponse, DeleteLanguageByIsoCodeData, DeleteLanguageByIsoCodeResponse, PutLanguageByIsoCodeData, PutLanguageByIsoCodeResponse, GetLogViewerLevelData, GetLogViewerLevelResponse, GetLogViewerLevelCountData, GetLogViewerLevelCountResponse, GetLogViewerLogData, GetLogViewerLogResponse, GetLogViewerMessageTemplateData, GetLogViewerMessageTemplateResponse, GetLogViewerSavedSearchData, GetLogViewerSavedSearchResponse, PostLogViewerSavedSearchData, PostLogViewerSavedSearchResponse, GetLogViewerSavedSearchByNameData, GetLogViewerSavedSearchByNameResponse, DeleteLogViewerSavedSearchByNameData, DeleteLogViewerSavedSearchByNameResponse, GetLogViewerValidateLogsSizeData, GetLogViewerValidateLogsSizeResponse, GetManifestManifestResponse, GetManifestManifestPrivateResponse, GetManifestManifestPublicResponse, GetItemMediaTypeData, GetItemMediaTypeResponse, GetItemMediaTypeAllowedData, GetItemMediaTypeAllowedResponse, GetItemMediaTypeFoldersData, GetItemMediaTypeFoldersResponse, GetItemMediaTypeSearchData, GetItemMediaTypeSearchResponse, PostMediaTypeData, PostMediaTypeResponse, GetMediaTypeByIdData, GetMediaTypeByIdResponse, DeleteMediaTypeByIdData, DeleteMediaTypeByIdResponse, PutMediaTypeByIdData, PutMediaTypeByIdResponse, GetMediaTypeByIdAllowedChildrenData, GetMediaTypeByIdAllowedChildrenResponse, GetMediaTypeByIdCompositionReferencesData, GetMediaTypeByIdCompositionReferencesResponse, PostMediaTypeByIdCopyData, PostMediaTypeByIdCopyResponse, GetMediaTypeByIdExportData, GetMediaTypeByIdExportResponse, PutMediaTypeByIdImportData, PutMediaTypeByIdImportResponse, PutMediaTypeByIdMoveData, PutMediaTypeByIdMoveResponse, GetMediaTypeAllowedAtRootData, GetMediaTypeAllowedAtRootResponse, PostMediaTypeAvailableCompositionsData, PostMediaTypeAvailableCompositionsResponse, GetMediaTypeConfigurationResponse, PostMediaTypeFolderData, PostMediaTypeFolderResponse, GetMediaTypeFolderByIdData, GetMediaTypeFolderByIdResponse, DeleteMediaTypeFolderByIdData, DeleteMediaTypeFolderByIdResponse, PutMediaTypeFolderByIdData, PutMediaTypeFolderByIdResponse, PostMediaTypeImportData, PostMediaTypeImportResponse, GetTreeMediaTypeAncestorsData, GetTreeMediaTypeAncestorsResponse, GetTreeMediaTypeChildrenData, GetTreeMediaTypeChildrenResponse, GetTreeMediaTypeRootData, GetTreeMediaTypeRootResponse, GetCollectionMediaData, GetCollectionMediaResponse, GetItemMediaData, GetItemMediaResponse, GetItemMediaSearchData, GetItemMediaSearchResponse, PostMediaData, PostMediaResponse, GetMediaByIdData, GetMediaByIdResponse, DeleteMediaByIdData, DeleteMediaByIdResponse, PutMediaByIdData, PutMediaByIdResponse, GetMediaByIdAuditLogData, GetMediaByIdAuditLogResponse, PutMediaByIdMoveData, PutMediaByIdMoveResponse, PutMediaByIdMoveToRecycleBinData, PutMediaByIdMoveToRecycleBinResponse, GetMediaByIdReferencedByData, GetMediaByIdReferencedByResponse, GetMediaByIdReferencedDescendantsData, GetMediaByIdReferencedDescendantsResponse, PutMediaByIdValidateData, PutMediaByIdValidateResponse, GetMediaAreReferencedData, GetMediaAreReferencedResponse, GetMediaConfigurationResponse, PutMediaSortData, PutMediaSortResponse, GetMediaUrlsData, GetMediaUrlsResponse, PostMediaValidateData, PostMediaValidateResponse, DeleteRecycleBinMediaResponse, DeleteRecycleBinMediaByIdData, DeleteRecycleBinMediaByIdResponse, GetRecycleBinMediaByIdOriginalParentData, GetRecycleBinMediaByIdOriginalParentResponse, PutRecycleBinMediaByIdRestoreData, PutRecycleBinMediaByIdRestoreResponse, GetRecycleBinMediaChildrenData, GetRecycleBinMediaChildrenResponse, GetRecycleBinMediaRootData, GetRecycleBinMediaRootResponse, GetTreeMediaAncestorsData, GetTreeMediaAncestorsResponse, GetTreeMediaChildrenData, GetTreeMediaChildrenResponse, GetTreeMediaRootData, GetTreeMediaRootResponse, GetItemMemberGroupData, GetItemMemberGroupResponse, GetMemberGroupData, GetMemberGroupResponse, PostMemberGroupData, PostMemberGroupResponse, GetMemberGroupByIdData, GetMemberGroupByIdResponse, DeleteMemberGroupByIdData, DeleteMemberGroupByIdResponse, PutMemberGroupByIdData, PutMemberGroupByIdResponse, GetTreeMemberGroupRootData, GetTreeMemberGroupRootResponse, GetItemMemberTypeData, GetItemMemberTypeResponse, GetItemMemberTypeSearchData, GetItemMemberTypeSearchResponse, PostMemberTypeData, PostMemberTypeResponse, GetMemberTypeByIdData, GetMemberTypeByIdResponse, DeleteMemberTypeByIdData, DeleteMemberTypeByIdResponse, PutMemberTypeByIdData, PutMemberTypeByIdResponse, GetMemberTypeByIdCompositionReferencesData, GetMemberTypeByIdCompositionReferencesResponse, PostMemberTypeByIdCopyData, PostMemberTypeByIdCopyResponse, PostMemberTypeAvailableCompositionsData, PostMemberTypeAvailableCompositionsResponse, GetMemberTypeConfigurationResponse, GetTreeMemberTypeRootData, GetTreeMemberTypeRootResponse, GetFilterMemberData, GetFilterMemberResponse, GetItemMemberData, GetItemMemberResponse, GetItemMemberSearchData, GetItemMemberSearchResponse, PostMemberData, PostMemberResponse, GetMemberByIdData, GetMemberByIdResponse, DeleteMemberByIdData, DeleteMemberByIdResponse, PutMemberByIdData, PutMemberByIdResponse, PutMemberByIdValidateData, PutMemberByIdValidateResponse, GetMemberConfigurationResponse, PostMemberValidateData, PostMemberValidateResponse, PostModelsBuilderBuildResponse, GetModelsBuilderDashboardResponse, GetModelsBuilderStatusResponse, GetObjectTypesData, GetObjectTypesResponse, GetOembedQueryData, GetOembedQueryResponse, PostPackageByNameRunMigrationData, PostPackageByNameRunMigrationResponse, GetPackageConfigurationResponse, GetPackageCreatedData, GetPackageCreatedResponse, PostPackageCreatedData, PostPackageCreatedResponse, GetPackageCreatedByIdData, GetPackageCreatedByIdResponse, DeletePackageCreatedByIdData, DeletePackageCreatedByIdResponse, PutPackageCreatedByIdData, PutPackageCreatedByIdResponse, GetPackageCreatedByIdDownloadData, GetPackageCreatedByIdDownloadResponse, GetPackageMigrationStatusData, GetPackageMigrationStatusResponse, GetItemPartialViewData, GetItemPartialViewResponse, PostPartialViewData, PostPartialViewResponse, GetPartialViewByPathData, GetPartialViewByPathResponse, DeletePartialViewByPathData, DeletePartialViewByPathResponse, PutPartialViewByPathData, PutPartialViewByPathResponse, PutPartialViewByPathRenameData, PutPartialViewByPathRenameResponse, PostPartialViewFolderData, PostPartialViewFolderResponse, GetPartialViewFolderByPathData, GetPartialViewFolderByPathResponse, DeletePartialViewFolderByPathData, DeletePartialViewFolderByPathResponse, GetPartialViewSnippetData, GetPartialViewSnippetResponse, GetPartialViewSnippetByIdData, GetPartialViewSnippetByIdResponse, GetTreePartialViewAncestorsData, GetTreePartialViewAncestorsResponse, GetTreePartialViewChildrenData, GetTreePartialViewChildrenResponse, GetTreePartialViewRootData, GetTreePartialViewRootResponse, DeletePreviewResponse, PostPreviewResponse, GetProfilingStatusResponse, PutProfilingStatusData, PutProfilingStatusResponse, GetPropertyTypeIsUsedData, GetPropertyTypeIsUsedResponse, PostPublishedCacheCollectResponse, PostPublishedCacheRebuildResponse, PostPublishedCacheReloadResponse, GetPublishedCacheStatusResponse, GetRedirectManagementData, GetRedirectManagementResponse, GetRedirectManagementByIdData, GetRedirectManagementByIdResponse, DeleteRedirectManagementByIdData, DeleteRedirectManagementByIdResponse, GetRedirectManagementStatusResponse, PostRedirectManagementStatusData, PostRedirectManagementStatusResponse, GetItemRelationTypeData, GetItemRelationTypeResponse, GetRelationTypeData, GetRelationTypeResponse, GetRelationTypeByIdData, GetRelationTypeByIdResponse, GetRelationByRelationTypeIdData, GetRelationByRelationTypeIdResponse, GetItemScriptData, GetItemScriptResponse, PostScriptData, PostScriptResponse, GetScriptByPathData, GetScriptByPathResponse, DeleteScriptByPathData, DeleteScriptByPathResponse, PutScriptByPathData, PutScriptByPathResponse, PutScriptByPathRenameData, PutScriptByPathRenameResponse, PostScriptFolderData, PostScriptFolderResponse, GetScriptFolderByPathData, GetScriptFolderByPathResponse, DeleteScriptFolderByPathData, DeleteScriptFolderByPathResponse, GetTreeScriptAncestorsData, GetTreeScriptAncestorsResponse, GetTreeScriptChildrenData, GetTreeScriptChildrenResponse, GetTreeScriptRootData, GetTreeScriptRootResponse, GetSearcherData, GetSearcherResponse, GetSearcherBySearcherNameQueryData, GetSearcherBySearcherNameQueryResponse, GetSecurityConfigurationResponse, PostSecurityForgotPasswordData, PostSecurityForgotPasswordResponse, PostSecurityForgotPasswordResetData, PostSecurityForgotPasswordResetResponse, PostSecurityForgotPasswordVerifyData, PostSecurityForgotPasswordVerifyResponse, GetSegmentData, GetSegmentResponse, GetServerConfigurationResponse, GetServerInformationResponse, GetServerStatusResponse, GetServerTroubleshootingResponse, GetItemStaticFileData, GetItemStaticFileResponse, GetTreeStaticFileAncestorsData, GetTreeStaticFileAncestorsResponse, GetTreeStaticFileChildrenData, GetTreeStaticFileChildrenResponse, GetTreeStaticFileRootData, GetTreeStaticFileRootResponse, GetItemStylesheetData, GetItemStylesheetResponse, PostStylesheetData, PostStylesheetResponse, GetStylesheetByPathData, GetStylesheetByPathResponse, DeleteStylesheetByPathData, DeleteStylesheetByPathResponse, PutStylesheetByPathData, PutStylesheetByPathResponse, PutStylesheetByPathRenameData, PutStylesheetByPathRenameResponse, PostStylesheetFolderData, PostStylesheetFolderResponse, GetStylesheetFolderByPathData, GetStylesheetFolderByPathResponse, DeleteStylesheetFolderByPathData, DeleteStylesheetFolderByPathResponse, GetTreeStylesheetAncestorsData, GetTreeStylesheetAncestorsResponse, GetTreeStylesheetChildrenData, GetTreeStylesheetChildrenResponse, GetTreeStylesheetRootData, GetTreeStylesheetRootResponse, GetTagData, GetTagResponse, GetTelemetryData, GetTelemetryResponse, GetTelemetryLevelResponse, PostTelemetryLevelData, PostTelemetryLevelResponse, GetItemTemplateData, GetItemTemplateResponse, GetItemTemplateSearchData, GetItemTemplateSearchResponse, PostTemplateData, PostTemplateResponse, GetTemplateByIdData, GetTemplateByIdResponse, DeleteTemplateByIdData, DeleteTemplateByIdResponse, PutTemplateByIdData, PutTemplateByIdResponse, GetTemplateConfigurationResponse, PostTemplateQueryExecuteData, PostTemplateQueryExecuteResponse, GetTemplateQuerySettingsResponse, GetTreeTemplateAncestorsData, GetTreeTemplateAncestorsResponse, GetTreeTemplateChildrenData, GetTreeTemplateChildrenResponse, GetTreeTemplateRootData, GetTreeTemplateRootResponse, PostTemporaryFileData, PostTemporaryFileResponse, GetTemporaryFileByIdData, GetTemporaryFileByIdResponse, DeleteTemporaryFileByIdData, DeleteTemporaryFileByIdResponse, GetTemporaryFileConfigurationResponse, PostUpgradeAuthorizeResponse, GetUpgradeSettingsResponse, PostUserDataData, PostUserDataResponse, GetUserDataData, GetUserDataResponse, PutUserDataData, PutUserDataResponse, GetUserDataByIdData, GetUserDataByIdResponse, GetFilterUserGroupData, GetFilterUserGroupResponse, GetItemUserGroupData, GetItemUserGroupResponse, DeleteUserGroupData, DeleteUserGroupResponse, PostUserGroupData, PostUserGroupResponse, GetUserGroupData, GetUserGroupResponse, GetUserGroupByIdData, GetUserGroupByIdResponse, DeleteUserGroupByIdData, DeleteUserGroupByIdResponse, PutUserGroupByIdData, PutUserGroupByIdResponse, DeleteUserGroupByIdUsersData, DeleteUserGroupByIdUsersResponse, PostUserGroupByIdUsersData, PostUserGroupByIdUsersResponse, GetFilterUserData, GetFilterUserResponse, GetItemUserData, GetItemUserResponse, PostUserData, PostUserResponse, DeleteUserData, DeleteUserResponse, GetUserData, GetUserResponse, GetUserByIdData, GetUserByIdResponse, DeleteUserByIdData, DeleteUserByIdResponse, PutUserByIdData, PutUserByIdResponse, GetUserById2FaData, GetUserById2FaResponse, DeleteUserById2FaByProviderNameData, DeleteUserById2FaByProviderNameResponse, GetUserByIdCalculateStartNodesData, GetUserByIdCalculateStartNodesResponse, PostUserByIdChangePasswordData, PostUserByIdChangePasswordResponse, PostUserByIdResetPasswordData, PostUserByIdResetPasswordResponse, DeleteUserAvatarByIdData, DeleteUserAvatarByIdResponse, PostUserAvatarByIdData, PostUserAvatarByIdResponse, GetUserConfigurationResponse, GetUserCurrentResponse, GetUserCurrent2FaResponse, DeleteUserCurrent2FaByProviderNameData, DeleteUserCurrent2FaByProviderNameResponse, PostUserCurrent2FaByProviderNameData, PostUserCurrent2FaByProviderNameResponse, GetUserCurrent2FaByProviderNameData, GetUserCurrent2FaByProviderNameResponse, PostUserCurrentAvatarData, PostUserCurrentAvatarResponse, PostUserCurrentChangePasswordData, PostUserCurrentChangePasswordResponse, GetUserCurrentConfigurationResponse, GetUserCurrentLoginProvidersResponse, GetUserCurrentPermissionsData, GetUserCurrentPermissionsResponse, GetUserCurrentPermissionsDocumentData, GetUserCurrentPermissionsDocumentResponse, GetUserCurrentPermissionsMediaData, GetUserCurrentPermissionsMediaResponse, PostUserDisableData, PostUserDisableResponse, PostUserEnableData, PostUserEnableResponse, PostUserInviteData, PostUserInviteResponse, PostUserInviteCreatePasswordData, PostUserInviteCreatePasswordResponse, PostUserInviteResendData, PostUserInviteResendResponse, PostUserInviteVerifyData, PostUserInviteVerifyResponse, PostUserSetUserGroupsData, PostUserSetUserGroupsResponse, PostUserUnlockData, PostUserUnlockResponse, GetItemWebhookData, GetItemWebhookResponse, GetWebhookData, GetWebhookResponse, PostWebhookData, PostWebhookResponse, GetWebhookByIdData, GetWebhookByIdResponse, DeleteWebhookByIdData, DeleteWebhookByIdResponse, PutWebhookByIdData, PutWebhookByIdResponse, GetWebhookEventsData, GetWebhookEventsResponse, PostCurrentUserChangePasswordData, PostCurrentUserChangePasswordResponse } from './types.gen'; +import type { GetCultureData, GetCultureResponse, PostDataTypeData, PostDataTypeResponse, GetDataTypeByIdData, GetDataTypeByIdResponse, DeleteDataTypeByIdData, DeleteDataTypeByIdResponse, PutDataTypeByIdData, PutDataTypeByIdResponse, PostDataTypeByIdCopyData, PostDataTypeByIdCopyResponse, GetDataTypeByIdIsUsedData, GetDataTypeByIdIsUsedResponse, PutDataTypeByIdMoveData, PutDataTypeByIdMoveResponse, GetDataTypeByIdReferencesData, GetDataTypeByIdReferencesResponse, GetDataTypeConfigurationResponse, PostDataTypeFolderData, PostDataTypeFolderResponse, GetDataTypeFolderByIdData, GetDataTypeFolderByIdResponse, DeleteDataTypeFolderByIdData, DeleteDataTypeFolderByIdResponse, PutDataTypeFolderByIdData, PutDataTypeFolderByIdResponse, GetFilterDataTypeData, GetFilterDataTypeResponse, GetItemDataTypeData, GetItemDataTypeResponse, GetItemDataTypeSearchData, GetItemDataTypeSearchResponse, GetTreeDataTypeAncestorsData, GetTreeDataTypeAncestorsResponse, GetTreeDataTypeChildrenData, GetTreeDataTypeChildrenResponse, GetTreeDataTypeRootData, GetTreeDataTypeRootResponse, GetDictionaryData, GetDictionaryResponse, PostDictionaryData, PostDictionaryResponse, GetDictionaryByIdData, GetDictionaryByIdResponse, DeleteDictionaryByIdData, DeleteDictionaryByIdResponse, PutDictionaryByIdData, PutDictionaryByIdResponse, GetDictionaryByIdExportData, GetDictionaryByIdExportResponse, PutDictionaryByIdMoveData, PutDictionaryByIdMoveResponse, PostDictionaryImportData, PostDictionaryImportResponse, GetItemDictionaryData, GetItemDictionaryResponse, GetTreeDictionaryAncestorsData, GetTreeDictionaryAncestorsResponse, GetTreeDictionaryChildrenData, GetTreeDictionaryChildrenResponse, GetTreeDictionaryRootData, GetTreeDictionaryRootResponse, PostDocumentBlueprintData, PostDocumentBlueprintResponse, GetDocumentBlueprintByIdData, GetDocumentBlueprintByIdResponse, DeleteDocumentBlueprintByIdData, DeleteDocumentBlueprintByIdResponse, PutDocumentBlueprintByIdData, PutDocumentBlueprintByIdResponse, PutDocumentBlueprintByIdMoveData, PutDocumentBlueprintByIdMoveResponse, PostDocumentBlueprintFolderData, PostDocumentBlueprintFolderResponse, GetDocumentBlueprintFolderByIdData, GetDocumentBlueprintFolderByIdResponse, DeleteDocumentBlueprintFolderByIdData, DeleteDocumentBlueprintFolderByIdResponse, PutDocumentBlueprintFolderByIdData, PutDocumentBlueprintFolderByIdResponse, PostDocumentBlueprintFromDocumentData, PostDocumentBlueprintFromDocumentResponse, GetItemDocumentBlueprintData, GetItemDocumentBlueprintResponse, GetTreeDocumentBlueprintAncestorsData, GetTreeDocumentBlueprintAncestorsResponse, GetTreeDocumentBlueprintChildrenData, GetTreeDocumentBlueprintChildrenResponse, GetTreeDocumentBlueprintRootData, GetTreeDocumentBlueprintRootResponse, PostDocumentTypeData, PostDocumentTypeResponse, GetDocumentTypeByIdData, GetDocumentTypeByIdResponse, DeleteDocumentTypeByIdData, DeleteDocumentTypeByIdResponse, PutDocumentTypeByIdData, PutDocumentTypeByIdResponse, GetDocumentTypeByIdAllowedChildrenData, GetDocumentTypeByIdAllowedChildrenResponse, GetDocumentTypeByIdBlueprintData, GetDocumentTypeByIdBlueprintResponse, GetDocumentTypeByIdCompositionReferencesData, GetDocumentTypeByIdCompositionReferencesResponse, PostDocumentTypeByIdCopyData, PostDocumentTypeByIdCopyResponse, GetDocumentTypeByIdExportData, GetDocumentTypeByIdExportResponse, PutDocumentTypeByIdImportData, PutDocumentTypeByIdImportResponse, PutDocumentTypeByIdMoveData, PutDocumentTypeByIdMoveResponse, GetDocumentTypeAllowedAtRootData, GetDocumentTypeAllowedAtRootResponse, PostDocumentTypeAvailableCompositionsData, PostDocumentTypeAvailableCompositionsResponse, GetDocumentTypeConfigurationResponse, PostDocumentTypeFolderData, PostDocumentTypeFolderResponse, GetDocumentTypeFolderByIdData, GetDocumentTypeFolderByIdResponse, DeleteDocumentTypeFolderByIdData, DeleteDocumentTypeFolderByIdResponse, PutDocumentTypeFolderByIdData, PutDocumentTypeFolderByIdResponse, PostDocumentTypeImportData, PostDocumentTypeImportResponse, GetItemDocumentTypeData, GetItemDocumentTypeResponse, GetItemDocumentTypeSearchData, GetItemDocumentTypeSearchResponse, GetTreeDocumentTypeAncestorsData, GetTreeDocumentTypeAncestorsResponse, GetTreeDocumentTypeChildrenData, GetTreeDocumentTypeChildrenResponse, GetTreeDocumentTypeRootData, GetTreeDocumentTypeRootResponse, GetDocumentVersionData, GetDocumentVersionResponse, GetDocumentVersionByIdData, GetDocumentVersionByIdResponse, PutDocumentVersionByIdPreventCleanupData, PutDocumentVersionByIdPreventCleanupResponse, PostDocumentVersionByIdRollbackData, PostDocumentVersionByIdRollbackResponse, GetCollectionDocumentByIdData, GetCollectionDocumentByIdResponse, PostDocumentData, PostDocumentResponse, GetDocumentByIdData, GetDocumentByIdResponse, DeleteDocumentByIdData, DeleteDocumentByIdResponse, PutDocumentByIdData, PutDocumentByIdResponse, GetDocumentByIdAuditLogData, GetDocumentByIdAuditLogResponse, PostDocumentByIdCopyData, PostDocumentByIdCopyResponse, GetDocumentByIdDomainsData, GetDocumentByIdDomainsResponse, PutDocumentByIdDomainsData, PutDocumentByIdDomainsResponse, PutDocumentByIdMoveData, PutDocumentByIdMoveResponse, PutDocumentByIdMoveToRecycleBinData, PutDocumentByIdMoveToRecycleBinResponse, GetDocumentByIdNotificationsData, GetDocumentByIdNotificationsResponse, PutDocumentByIdNotificationsData, PutDocumentByIdNotificationsResponse, PostDocumentByIdPublicAccessData, PostDocumentByIdPublicAccessResponse, DeleteDocumentByIdPublicAccessData, DeleteDocumentByIdPublicAccessResponse, GetDocumentByIdPublicAccessData, GetDocumentByIdPublicAccessResponse, PutDocumentByIdPublicAccessData, PutDocumentByIdPublicAccessResponse, PutDocumentByIdPublishData, PutDocumentByIdPublishResponse, PutDocumentByIdPublishWithDescendantsData, PutDocumentByIdPublishWithDescendantsResponse, GetDocumentByIdReferencedByData, GetDocumentByIdReferencedByResponse, GetDocumentByIdReferencedDescendantsData, GetDocumentByIdReferencedDescendantsResponse, PutDocumentByIdUnpublishData, PutDocumentByIdUnpublishResponse, PutDocumentByIdValidateData, PutDocumentByIdValidateResponse, GetDocumentAreReferencedData, GetDocumentAreReferencedResponse, GetDocumentConfigurationResponse, PutDocumentSortData, PutDocumentSortResponse, GetDocumentUrlsData, GetDocumentUrlsResponse, PostDocumentValidateData, PostDocumentValidateResponse, GetItemDocumentData, GetItemDocumentResponse, GetItemDocumentSearchData, GetItemDocumentSearchResponse, DeleteRecycleBinDocumentResponse, DeleteRecycleBinDocumentByIdData, DeleteRecycleBinDocumentByIdResponse, GetRecycleBinDocumentByIdOriginalParentData, GetRecycleBinDocumentByIdOriginalParentResponse, PutRecycleBinDocumentByIdRestoreData, PutRecycleBinDocumentByIdRestoreResponse, GetRecycleBinDocumentChildrenData, GetRecycleBinDocumentChildrenResponse, GetRecycleBinDocumentRootData, GetRecycleBinDocumentRootResponse, GetTreeDocumentAncestorsData, GetTreeDocumentAncestorsResponse, GetTreeDocumentChildrenData, GetTreeDocumentChildrenResponse, GetTreeDocumentRootData, GetTreeDocumentRootResponse, PostDynamicRootQueryData, PostDynamicRootQueryResponse, GetDynamicRootStepsResponse, GetHealthCheckGroupData, GetHealthCheckGroupResponse, GetHealthCheckGroupByNameData, GetHealthCheckGroupByNameResponse, PostHealthCheckGroupByNameCheckData, PostHealthCheckGroupByNameCheckResponse, PostHealthCheckExecuteActionData, PostHealthCheckExecuteActionResponse, GetHelpData, GetHelpResponse, GetImagingResizeUrlsData, GetImagingResizeUrlsResponse, GetImportAnalyzeData, GetImportAnalyzeResponse, GetIndexerData, GetIndexerResponse, GetIndexerByIndexNameData, GetIndexerByIndexNameResponse, PostIndexerByIndexNameRebuildData, PostIndexerByIndexNameRebuildResponse, GetInstallSettingsResponse, PostInstallSetupData, PostInstallSetupResponse, PostInstallValidateDatabaseData, PostInstallValidateDatabaseResponse, GetItemLanguageData, GetItemLanguageResponse, GetItemLanguageDefaultResponse, GetLanguageData, GetLanguageResponse, PostLanguageData, PostLanguageResponse, GetLanguageByIsoCodeData, GetLanguageByIsoCodeResponse, DeleteLanguageByIsoCodeData, DeleteLanguageByIsoCodeResponse, PutLanguageByIsoCodeData, PutLanguageByIsoCodeResponse, GetLogViewerLevelData, GetLogViewerLevelResponse, GetLogViewerLevelCountData, GetLogViewerLevelCountResponse, GetLogViewerLogData, GetLogViewerLogResponse, GetLogViewerMessageTemplateData, GetLogViewerMessageTemplateResponse, GetLogViewerSavedSearchData, GetLogViewerSavedSearchResponse, PostLogViewerSavedSearchData, PostLogViewerSavedSearchResponse, GetLogViewerSavedSearchByNameData, GetLogViewerSavedSearchByNameResponse, DeleteLogViewerSavedSearchByNameData, DeleteLogViewerSavedSearchByNameResponse, GetLogViewerValidateLogsSizeData, GetLogViewerValidateLogsSizeResponse, GetManifestManifestResponse, GetManifestManifestPrivateResponse, GetManifestManifestPublicResponse, GetItemMediaTypeData, GetItemMediaTypeResponse, GetItemMediaTypeAllowedData, GetItemMediaTypeAllowedResponse, GetItemMediaTypeFoldersData, GetItemMediaTypeFoldersResponse, GetItemMediaTypeSearchData, GetItemMediaTypeSearchResponse, PostMediaTypeData, PostMediaTypeResponse, GetMediaTypeByIdData, GetMediaTypeByIdResponse, DeleteMediaTypeByIdData, DeleteMediaTypeByIdResponse, PutMediaTypeByIdData, PutMediaTypeByIdResponse, GetMediaTypeByIdAllowedChildrenData, GetMediaTypeByIdAllowedChildrenResponse, GetMediaTypeByIdCompositionReferencesData, GetMediaTypeByIdCompositionReferencesResponse, PostMediaTypeByIdCopyData, PostMediaTypeByIdCopyResponse, GetMediaTypeByIdExportData, GetMediaTypeByIdExportResponse, PutMediaTypeByIdImportData, PutMediaTypeByIdImportResponse, PutMediaTypeByIdMoveData, PutMediaTypeByIdMoveResponse, GetMediaTypeAllowedAtRootData, GetMediaTypeAllowedAtRootResponse, PostMediaTypeAvailableCompositionsData, PostMediaTypeAvailableCompositionsResponse, GetMediaTypeConfigurationResponse, PostMediaTypeFolderData, PostMediaTypeFolderResponse, GetMediaTypeFolderByIdData, GetMediaTypeFolderByIdResponse, DeleteMediaTypeFolderByIdData, DeleteMediaTypeFolderByIdResponse, PutMediaTypeFolderByIdData, PutMediaTypeFolderByIdResponse, PostMediaTypeImportData, PostMediaTypeImportResponse, GetTreeMediaTypeAncestorsData, GetTreeMediaTypeAncestorsResponse, GetTreeMediaTypeChildrenData, GetTreeMediaTypeChildrenResponse, GetTreeMediaTypeRootData, GetTreeMediaTypeRootResponse, GetCollectionMediaData, GetCollectionMediaResponse, GetItemMediaData, GetItemMediaResponse, GetItemMediaSearchData, GetItemMediaSearchResponse, PostMediaData, PostMediaResponse, GetMediaByIdData, GetMediaByIdResponse, DeleteMediaByIdData, DeleteMediaByIdResponse, PutMediaByIdData, PutMediaByIdResponse, GetMediaByIdAuditLogData, GetMediaByIdAuditLogResponse, PutMediaByIdMoveData, PutMediaByIdMoveResponse, PutMediaByIdMoveToRecycleBinData, PutMediaByIdMoveToRecycleBinResponse, GetMediaByIdReferencedByData, GetMediaByIdReferencedByResponse, GetMediaByIdReferencedDescendantsData, GetMediaByIdReferencedDescendantsResponse, PutMediaByIdValidateData, PutMediaByIdValidateResponse, GetMediaAreReferencedData, GetMediaAreReferencedResponse, GetMediaConfigurationResponse, PutMediaSortData, PutMediaSortResponse, GetMediaUrlsData, GetMediaUrlsResponse, PostMediaValidateData, PostMediaValidateResponse, DeleteRecycleBinMediaResponse, DeleteRecycleBinMediaByIdData, DeleteRecycleBinMediaByIdResponse, GetRecycleBinMediaByIdOriginalParentData, GetRecycleBinMediaByIdOriginalParentResponse, PutRecycleBinMediaByIdRestoreData, PutRecycleBinMediaByIdRestoreResponse, GetRecycleBinMediaChildrenData, GetRecycleBinMediaChildrenResponse, GetRecycleBinMediaRootData, GetRecycleBinMediaRootResponse, GetTreeMediaAncestorsData, GetTreeMediaAncestorsResponse, GetTreeMediaChildrenData, GetTreeMediaChildrenResponse, GetTreeMediaRootData, GetTreeMediaRootResponse, GetItemMemberGroupData, GetItemMemberGroupResponse, GetMemberGroupData, GetMemberGroupResponse, PostMemberGroupData, PostMemberGroupResponse, GetMemberGroupByIdData, GetMemberGroupByIdResponse, DeleteMemberGroupByIdData, DeleteMemberGroupByIdResponse, PutMemberGroupByIdData, PutMemberGroupByIdResponse, GetTreeMemberGroupRootData, GetTreeMemberGroupRootResponse, GetItemMemberTypeData, GetItemMemberTypeResponse, GetItemMemberTypeSearchData, GetItemMemberTypeSearchResponse, PostMemberTypeData, PostMemberTypeResponse, GetMemberTypeByIdData, GetMemberTypeByIdResponse, DeleteMemberTypeByIdData, DeleteMemberTypeByIdResponse, PutMemberTypeByIdData, PutMemberTypeByIdResponse, GetMemberTypeByIdCompositionReferencesData, GetMemberTypeByIdCompositionReferencesResponse, PostMemberTypeByIdCopyData, PostMemberTypeByIdCopyResponse, PostMemberTypeAvailableCompositionsData, PostMemberTypeAvailableCompositionsResponse, GetMemberTypeConfigurationResponse, GetTreeMemberTypeRootData, GetTreeMemberTypeRootResponse, GetFilterMemberData, GetFilterMemberResponse, GetItemMemberData, GetItemMemberResponse, GetItemMemberSearchData, GetItemMemberSearchResponse, PostMemberData, PostMemberResponse, GetMemberByIdData, GetMemberByIdResponse, DeleteMemberByIdData, DeleteMemberByIdResponse, PutMemberByIdData, PutMemberByIdResponse, PutMemberByIdValidateData, PutMemberByIdValidateResponse, GetMemberConfigurationResponse, PostMemberValidateData, PostMemberValidateResponse, PostModelsBuilderBuildResponse, GetModelsBuilderDashboardResponse, GetModelsBuilderStatusResponse, GetObjectTypesData, GetObjectTypesResponse, GetOembedQueryData, GetOembedQueryResponse, PostPackageByNameRunMigrationData, PostPackageByNameRunMigrationResponse, GetPackageConfigurationResponse, GetPackageCreatedData, GetPackageCreatedResponse, PostPackageCreatedData, PostPackageCreatedResponse, GetPackageCreatedByIdData, GetPackageCreatedByIdResponse, DeletePackageCreatedByIdData, DeletePackageCreatedByIdResponse, PutPackageCreatedByIdData, PutPackageCreatedByIdResponse, GetPackageCreatedByIdDownloadData, GetPackageCreatedByIdDownloadResponse, GetPackageMigrationStatusData, GetPackageMigrationStatusResponse, GetItemPartialViewData, GetItemPartialViewResponse, PostPartialViewData, PostPartialViewResponse, GetPartialViewByPathData, GetPartialViewByPathResponse, DeletePartialViewByPathData, DeletePartialViewByPathResponse, PutPartialViewByPathData, PutPartialViewByPathResponse, PutPartialViewByPathRenameData, PutPartialViewByPathRenameResponse, PostPartialViewFolderData, PostPartialViewFolderResponse, GetPartialViewFolderByPathData, GetPartialViewFolderByPathResponse, DeletePartialViewFolderByPathData, DeletePartialViewFolderByPathResponse, GetPartialViewSnippetData, GetPartialViewSnippetResponse, GetPartialViewSnippetByIdData, GetPartialViewSnippetByIdResponse, GetTreePartialViewAncestorsData, GetTreePartialViewAncestorsResponse, GetTreePartialViewChildrenData, GetTreePartialViewChildrenResponse, GetTreePartialViewRootData, GetTreePartialViewRootResponse, DeletePreviewResponse, PostPreviewResponse, GetProfilingStatusResponse, PutProfilingStatusData, PutProfilingStatusResponse, GetPropertyTypeIsUsedData, GetPropertyTypeIsUsedResponse, PostPublishedCacheCollectResponse, PostPublishedCacheRebuildResponse, PostPublishedCacheReloadResponse, GetPublishedCacheStatusResponse, GetRedirectManagementData, GetRedirectManagementResponse, GetRedirectManagementByIdData, GetRedirectManagementByIdResponse, DeleteRedirectManagementByIdData, DeleteRedirectManagementByIdResponse, GetRedirectManagementStatusResponse, PostRedirectManagementStatusData, PostRedirectManagementStatusResponse, GetItemRelationTypeData, GetItemRelationTypeResponse, GetRelationTypeData, GetRelationTypeResponse, GetRelationTypeByIdData, GetRelationTypeByIdResponse, GetRelationByRelationTypeIdData, GetRelationByRelationTypeIdResponse, GetItemScriptData, GetItemScriptResponse, PostScriptData, PostScriptResponse, GetScriptByPathData, GetScriptByPathResponse, DeleteScriptByPathData, DeleteScriptByPathResponse, PutScriptByPathData, PutScriptByPathResponse, PutScriptByPathRenameData, PutScriptByPathRenameResponse, PostScriptFolderData, PostScriptFolderResponse, GetScriptFolderByPathData, GetScriptFolderByPathResponse, DeleteScriptFolderByPathData, DeleteScriptFolderByPathResponse, GetTreeScriptAncestorsData, GetTreeScriptAncestorsResponse, GetTreeScriptChildrenData, GetTreeScriptChildrenResponse, GetTreeScriptRootData, GetTreeScriptRootResponse, GetSearcherData, GetSearcherResponse, GetSearcherBySearcherNameQueryData, GetSearcherBySearcherNameQueryResponse, GetSecurityConfigurationResponse, PostSecurityForgotPasswordData, PostSecurityForgotPasswordResponse, PostSecurityForgotPasswordResetData, PostSecurityForgotPasswordResetResponse, PostSecurityForgotPasswordVerifyData, PostSecurityForgotPasswordVerifyResponse, GetSegmentData, GetSegmentResponse, GetServerConfigurationResponse, GetServerInformationResponse, GetServerStatusResponse, GetServerTroubleshootingResponse, GetItemStaticFileData, GetItemStaticFileResponse, GetTreeStaticFileAncestorsData, GetTreeStaticFileAncestorsResponse, GetTreeStaticFileChildrenData, GetTreeStaticFileChildrenResponse, GetTreeStaticFileRootData, GetTreeStaticFileRootResponse, GetItemStylesheetData, GetItemStylesheetResponse, PostStylesheetData, PostStylesheetResponse, GetStylesheetByPathData, GetStylesheetByPathResponse, DeleteStylesheetByPathData, DeleteStylesheetByPathResponse, PutStylesheetByPathData, PutStylesheetByPathResponse, PutStylesheetByPathRenameData, PutStylesheetByPathRenameResponse, PostStylesheetFolderData, PostStylesheetFolderResponse, GetStylesheetFolderByPathData, GetStylesheetFolderByPathResponse, DeleteStylesheetFolderByPathData, DeleteStylesheetFolderByPathResponse, GetTreeStylesheetAncestorsData, GetTreeStylesheetAncestorsResponse, GetTreeStylesheetChildrenData, GetTreeStylesheetChildrenResponse, GetTreeStylesheetRootData, GetTreeStylesheetRootResponse, GetTagData, GetTagResponse, GetTelemetryData, GetTelemetryResponse, GetTelemetryLevelResponse, PostTelemetryLevelData, PostTelemetryLevelResponse, GetItemTemplateData, GetItemTemplateResponse, GetItemTemplateSearchData, GetItemTemplateSearchResponse, PostTemplateData, PostTemplateResponse, GetTemplateByIdData, GetTemplateByIdResponse, DeleteTemplateByIdData, DeleteTemplateByIdResponse, PutTemplateByIdData, PutTemplateByIdResponse, GetTemplateConfigurationResponse, PostTemplateQueryExecuteData, PostTemplateQueryExecuteResponse, GetTemplateQuerySettingsResponse, GetTreeTemplateAncestorsData, GetTreeTemplateAncestorsResponse, GetTreeTemplateChildrenData, GetTreeTemplateChildrenResponse, GetTreeTemplateRootData, GetTreeTemplateRootResponse, PostTemporaryFileData, PostTemporaryFileResponse, GetTemporaryFileByIdData, GetTemporaryFileByIdResponse, DeleteTemporaryFileByIdData, DeleteTemporaryFileByIdResponse, GetTemporaryFileConfigurationResponse, PostUpgradeAuthorizeResponse, GetUpgradeSettingsResponse, PostUserDataData, PostUserDataResponse, GetUserDataData, GetUserDataResponse, PutUserDataData, PutUserDataResponse, GetUserDataByIdData, GetUserDataByIdResponse, GetFilterUserGroupData, GetFilterUserGroupResponse, GetItemUserGroupData, GetItemUserGroupResponse, DeleteUserGroupData, DeleteUserGroupResponse, PostUserGroupData, PostUserGroupResponse, GetUserGroupData, GetUserGroupResponse, GetUserGroupByIdData, GetUserGroupByIdResponse, DeleteUserGroupByIdData, DeleteUserGroupByIdResponse, PutUserGroupByIdData, PutUserGroupByIdResponse, DeleteUserGroupByIdUsersData, DeleteUserGroupByIdUsersResponse, PostUserGroupByIdUsersData, PostUserGroupByIdUsersResponse, GetFilterUserData, GetFilterUserResponse, GetItemUserData, GetItemUserResponse, PostUserData, PostUserResponse, DeleteUserData, DeleteUserResponse, GetUserData, GetUserResponse, GetUserByIdData, GetUserByIdResponse, DeleteUserByIdData, DeleteUserByIdResponse, PutUserByIdData, PutUserByIdResponse, GetUserById2FaData, GetUserById2FaResponse, DeleteUserById2FaByProviderNameData, DeleteUserById2FaByProviderNameResponse, GetUserByIdCalculateStartNodesData, GetUserByIdCalculateStartNodesResponse, PostUserByIdChangePasswordData, PostUserByIdChangePasswordResponse, PostUserByIdClientCredentialsData, PostUserByIdClientCredentialsResponse, GetUserByIdClientCredentialsData, GetUserByIdClientCredentialsResponse, DeleteUserByIdClientCredentialsByClientIdData, DeleteUserByIdClientCredentialsByClientIdResponse, PostUserByIdResetPasswordData, PostUserByIdResetPasswordResponse, DeleteUserAvatarByIdData, DeleteUserAvatarByIdResponse, PostUserAvatarByIdData, PostUserAvatarByIdResponse, GetUserConfigurationResponse, GetUserCurrentResponse, GetUserCurrent2FaResponse, DeleteUserCurrent2FaByProviderNameData, DeleteUserCurrent2FaByProviderNameResponse, PostUserCurrent2FaByProviderNameData, PostUserCurrent2FaByProviderNameResponse, GetUserCurrent2FaByProviderNameData, GetUserCurrent2FaByProviderNameResponse, PostUserCurrentAvatarData, PostUserCurrentAvatarResponse, PostUserCurrentChangePasswordData, PostUserCurrentChangePasswordResponse, GetUserCurrentConfigurationResponse, GetUserCurrentLoginProvidersResponse, GetUserCurrentPermissionsData, GetUserCurrentPermissionsResponse, GetUserCurrentPermissionsDocumentData, GetUserCurrentPermissionsDocumentResponse, GetUserCurrentPermissionsMediaData, GetUserCurrentPermissionsMediaResponse, PostUserDisableData, PostUserDisableResponse, PostUserEnableData, PostUserEnableResponse, PostUserInviteData, PostUserInviteResponse, PostUserInviteCreatePasswordData, PostUserInviteCreatePasswordResponse, PostUserInviteResendData, PostUserInviteResendResponse, PostUserInviteVerifyData, PostUserInviteVerifyResponse, PostUserSetUserGroupsData, PostUserSetUserGroupsResponse, PostUserUnlockData, PostUserUnlockResponse, GetItemWebhookData, GetItemWebhookResponse, GetWebhookData, GetWebhookResponse, PostWebhookData, PostWebhookResponse, GetWebhookByIdData, GetWebhookByIdResponse, DeleteWebhookByIdData, DeleteWebhookByIdResponse, PutWebhookByIdData, PutWebhookByIdResponse, GetWebhookEventsData, GetWebhookEventsResponse } from './types.gen'; export class CultureService { /** @@ -2425,6 +2425,7 @@ export class DocumentService { * @param data.query * @param data.skip * @param data.take + * @param data.parentId * @returns unknown OK * @throws ApiError */ @@ -2435,7 +2436,8 @@ export class DocumentService { query: { query: data.query, skip: data.skip, - take: data.take + take: data.take, + parentId: data.parentId }, errors: { 401: 'The resource is protected and requires an authentication token' @@ -4014,6 +4016,7 @@ export class MediaService { * @param data.query * @param data.skip * @param data.take + * @param data.parentId * @returns unknown OK * @throws ApiError */ @@ -4024,7 +4027,8 @@ export class MediaService { query: { query: data.query, skip: data.skip, - take: data.take + take: data.take, + parentId: data.parentId }, errors: { 401: 'The resource is protected and requires an authentication token' @@ -8102,7 +8106,7 @@ export class UserService { } }); } - + /** * @param data The data for the request. * @param data.id @@ -8110,18 +8114,64 @@ export class UserService { * @returns string OK * @throws ApiError */ - public static postCurrentUserByIdChangePassword(data: PostCurrentUserChangePasswordData): CancelablePromise { + public static postUserByIdClientCredentials(data: PostUserByIdClientCredentialsData): CancelablePromise { return __request(OpenAPI, { method: 'POST', - url: '/umbraco/management/api/v1/user/current/change-password', + url: '/umbraco/management/api/v1/user/{id}/client-credentials', + path: { + id: data.id + }, body: data.requestBody, mediaType: 'application/json', responseHeader: 'Umb-Notifications', errors: { 400: 'Bad Request', 401: 'The resource is protected and requires an authentication token', - 403: 'The authenticated user do not have access to this resource', - 404: 'Not Found' + 403: 'The authenticated user do not have access to this resource' + } + }); + } + + /** + * @param data The data for the request. + * @param data.id + * @returns string OK + * @throws ApiError + */ + public static getUserByIdClientCredentials(data: GetUserByIdClientCredentialsData): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/umbraco/management/api/v1/user/{id}/client-credentials', + path: { + id: data.id + }, + errors: { + 401: 'The resource is protected and requires an authentication token', + 403: 'The authenticated user do not have access to this resource' + } + }); + } + + /** + * @param data The data for the request. + * @param data.id + * @param data.clientId + * @returns string OK + * @throws ApiError + */ + public static deleteUserByIdClientCredentialsByClientId(data: DeleteUserByIdClientCredentialsByClientIdData): CancelablePromise { + return __request(OpenAPI, { + method: 'DELETE', + url: '/umbraco/management/api/v1/user/{id}/client-credentials/{clientId}', + path: { + id: data.id, + clientId: data.clientId + }, + responseHeader: 'Umb-Notifications', + errors: { + 400: 'Bad Request', + 401: 'The resource is protected and requires an authentication token', + 403: 'The authenticated user do not have access to this resource' } }); } diff --git a/src/external/backend-api/src/types.gen.ts b/src/external/backend-api/src/types.gen.ts index ffc97171b1..224bc0862b 100644 --- a/src/external/backend-api/src/types.gen.ts +++ b/src/external/backend-api/src/types.gen.ts @@ -384,6 +384,11 @@ export type CreateTemplateRequestModel = { id?: string | null; }; +export type CreateUserClientCredentialsRequestModel = { + clientId: string; + clientSecret: string; +}; + export type CreateUserDataRequestModel = { group: string; identifier: string; @@ -413,6 +418,7 @@ export type CreateUserRequestModel = { name: string; userGroupIds: Array<(ReferenceByIdModel)>; id?: string | null; + kind: UserKindModel; }; export type CreateWebhookRequestModel = { @@ -1075,6 +1081,7 @@ export type InviteUserRequestModel = { name: string; userGroupIds: Array<(ReferenceByIdModel)>; id?: string | null; + kind: UserKindModel; message?: string | null; }; @@ -1353,8 +1360,14 @@ export type MemberItemResponseModel = { id: string; memberType: MemberTypeReferenceResponseModel; variants: Array<(VariantItemResponseModel)>; + kind: MemberKindModel; }; +export enum MemberKindModel { + DEFAULT = 'Default', + API = 'Api' +} + export type MemberResponseModel = { values: Array<(MemberValueModel)>; variants: Array<(MemberVariantResponseModel)>; @@ -1370,6 +1383,7 @@ export type MemberResponseModel = { lastLockoutDate?: string | null; lastPasswordChangeDate?: string | null; groups: Array<(string)>; + kind: MemberKindModel; }; export type MemberTypeCompositionModel = { @@ -2685,8 +2699,14 @@ export type UserItemResponseModel = { id: string; name: string; avatarUrls: Array<(string)>; + kind: UserKindModel; }; +export enum UserKindModel { + DEFAULT = 'Default', + API = 'Api' +} + export enum UserOrderModel { USER_NAME = 'UserName', LANGUAGE = 'Language', @@ -2729,6 +2749,7 @@ export type UserResponseModel = { lastLockoutDate?: string | null; lastPasswordChangeDate?: string | null; isAdmin: boolean; + kind: UserKindModel; }; export type UserSettingsPresentationModel = { @@ -3494,6 +3515,7 @@ export type GetItemDocumentData = { export type GetItemDocumentResponse = Array<(DocumentItemResponseModel)>; export type GetItemDocumentSearchData = { + parentId?: string; query?: string; skip?: number; take?: number; @@ -3947,6 +3969,7 @@ export type GetItemMediaData = { export type GetItemMediaResponse = Array<(MediaItemResponseModel)>; export type GetItemMediaSearchData = { + parentId?: string; query?: string; skip?: number; take?: number; @@ -5068,11 +5091,25 @@ export type PostUserByIdChangePasswordData = { export type PostUserByIdChangePasswordResponse = string; -export type PostCurrentUserChangePasswordData = { - requestBody?: ChangePasswordCurrentUserRequestModel; +export type PostUserByIdClientCredentialsData = { + id: string; + requestBody?: CreateUserClientCredentialsRequestModel; +}; + +export type PostUserByIdClientCredentialsResponse = string; + +export type GetUserByIdClientCredentialsData = { + id: string; +}; + +export type GetUserByIdClientCredentialsResponse = Array<(string)>; + +export type DeleteUserByIdClientCredentialsByClientIdData = { + clientId: string; + id: string; }; -export type PostCurrentUserChangePasswordResponse = string; +export type DeleteUserByIdClientCredentialsByClientIdResponse = string; export type PostUserByIdResetPasswordData = { id: string; @@ -12959,6 +12996,69 @@ export type $OpenApiTs = { }; }; }; + '/umbraco/management/api/v1/user/{id}/client-credentials': { + post: { + req: PostUserByIdClientCredentialsData; + res: { + /** + * OK + */ + 200: string; + /** + * Bad Request + */ + 400: ProblemDetails; + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user do not have access to this resource + */ + 403: string; + }; + }; + get: { + req: GetUserByIdClientCredentialsData; + res: { + /** + * OK + */ + 200: Array<(string)>; + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user do not have access to this resource + */ + 403: unknown; + }; + }; + }; + '/umbraco/management/api/v1/user/{id}/client-credentials/{clientId}': { + delete: { + req: DeleteUserByIdClientCredentialsByClientIdData; + res: { + /** + * OK + */ + 200: string; + /** + * Bad Request + */ + 400: ProblemDetails; + /** + * The resource is protected and requires an authentication token + */ + 401: unknown; + /** + * The authenticated user do not have access to this resource + */ + 403: string; + }; + }; + }; '/umbraco/management/api/v1/user/{id}/reset-password': { post: { req: PostUserByIdResetPasswordData; From 7946bfb210ccd25f982d3342f02a9f53ea8c34ea Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 22:26:13 +0200 Subject: [PATCH 010/322] add utils for user model kind --- src/packages/user/user/utils/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/packages/user/user/utils/index.ts b/src/packages/user/user/utils/index.ts index 5d1478f0fa..6189fbcb68 100644 --- a/src/packages/user/user/utils/index.ts +++ b/src/packages/user/user/utils/index.ts @@ -1 +1,8 @@ export * from './is-user.function.js'; + +export type UmbUserModelKindType = 'Default' | 'Api'; + +export const UmbUserModelKind = Object.freeze({ + DEFAULT: 'Default', + API: 'Api', +}); From 428c03136d50cad90f6bc94e1b5099d98a6f9f1e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 22:26:52 +0200 Subject: [PATCH 011/322] add kind to user detail model --- src/packages/user/user/types.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/packages/user/user/types.ts b/src/packages/user/user/types.ts index b092e1b3e8..b0cbe18174 100644 --- a/src/packages/user/user/types.ts +++ b/src/packages/user/user/types.ts @@ -5,6 +5,7 @@ import { UserStateModel, type UserTwoFactorProviderModel, } from '@umbraco-cms/backoffice/external/backend-api'; +import { UmbUserModelKindType } from './utils/index.js'; export type UmbUserStateEnum = UserStateModel; export const UmbUserStateEnum = UserStateModel; @@ -26,6 +27,7 @@ export interface UmbUserDetailModel extends UmbUserStartNodesModel { updateDate: string | null; userGroupUniques: Array; userName: string; + kind: UmbUserModelKindType; } export interface UmbUserStartNodesModel { From 4fce5b7a001f19ec4e640765899e2a31ea9cde26 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 22:27:36 +0200 Subject: [PATCH 012/322] map kind in user detail data source --- .../detail/user-detail.server.data-source.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/packages/user/user/repository/detail/user-detail.server.data-source.ts b/src/packages/user/user/repository/detail/user-detail.server.data-source.ts index 8d924ca94f..0d89ee2a79 100644 --- a/src/packages/user/user/repository/detail/user-detail.server.data-source.ts +++ b/src/packages/user/user/repository/detail/user-detail.server.data-source.ts @@ -2,10 +2,15 @@ import type { UmbUserDetailModel, UmbUserStartNodesModel } from '../../types.js' import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; -import type { CreateUserRequestModel, UpdateUserRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; +import type { + CreateUserRequestModel, + UpdateUserRequestModel, + UserKindModel, +} from '@umbraco-cms/backoffice/external/backend-api'; import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { UmbUserModelKind } from '../../utils/index.js'; /** * A data source for the User that fetches data from the server @@ -34,17 +39,18 @@ export class UmbUserServerDataSource implements UmbDetailDataSource Date: Fri, 30 Aug 2024 22:28:22 +0200 Subject: [PATCH 013/322] select kind when creating a new user --- .../modals/create/create-user-modal.element.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user/modals/create/create-user-modal.element.ts b/src/packages/user/user/modals/create/create-user-modal.element.ts index fdf1e15950..85b6facca1 100644 --- a/src/packages/user/user/modals/create/create-user-modal.element.ts +++ b/src/packages/user/user/modals/create/create-user-modal.element.ts @@ -1,4 +1,5 @@ import { UmbUserDetailRepository } from '../../repository/index.js'; +import { UmbUserModelKind, UmbUserModelKindType } from '../../utils/index.js'; import { UMB_CREATE_USER_SUCCESS_MODAL } from './create-user-success-modal.token.js'; import type { UmbUserGroupInputElement } from '@umbraco-cms/backoffice/user-group'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -24,6 +25,7 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { const formData = new FormData(form); + const kind = formData.get('kind') as UmbUserModelKindType; const name = formData.get('name') as string; const email = formData.get('email') as string; @@ -35,6 +37,7 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { const { data: userScaffold } = await this.#userDetailRepository.createScaffold(); if (!userScaffold) return; + userScaffold.kind = kind; userScaffold.name = name; userScaffold.email = email; userScaffold.userName = email; @@ -94,6 +97,17 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { #renderForm() { return html`
+ + Kind + + + ${UmbUserModelKind.DEFAULT} + ${UmbUserModelKind.API} + + + Name @@ -115,7 +129,8 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { UmbTextStyles, css` uui-input, - uui-input-password { + uui-input-password, + uui-combobox { width: 100%; } From 32cb68e4c7360430995b0895bc650bc3071d36b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 30 Aug 2024 23:13:06 +0200 Subject: [PATCH 014/322] declare global UmbManifestTypes --- src/packages/core/extension-registry/models/index.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts index adc53de04c..de089cb774 100644 --- a/src/packages/core/extension-registry/models/index.ts +++ b/src/packages/core/extension-registry/models/index.ts @@ -218,3 +218,12 @@ export type ManifestTypes = | ManifestWorkspaces | ManifestWorkspaceViews | ManifestBase; + +type UnionOfProperties = T extends object ? T[keyof T] : never; + +declare global { + interface UmbManifestType { + CORE: ManifestTypes; + } + type UmbManifestTypes = UnionOfProperties; +} From 140d7337503d5f411070749e98573a5ac478dad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 30 Aug 2024 23:13:31 +0200 Subject: [PATCH 015/322] move block editor custom view into its own module --- .../block-custom-view/block-custom-view.ts | 2 +- examples/block-custom-view/index.ts | 4 +- .../block-grid-block-inline.element.ts | 2 +- .../block-grid-block.element.ts | 3 +- .../block-grid-entry.element.ts | 12 ++-- .../block-list-entry.element.ts | 7 +-- .../property-editor-ui-block-list.element.ts | 3 +- ...i-block-list-type-configuration.element.ts | 4 +- src/packages/block/block-list/types.ts | 2 +- .../block-rte-entry.element.ts | 6 +- .../tiny-mce-block-picker.plugin.ts | 2 +- src/packages/block/block-rte/types.ts | 2 +- .../block-type-custom-view-guide.element.ts | 5 +- .../input-block-type.element.ts | 2 +- src/packages/block/block-type/types.ts | 15 ++++- .../workspace/block-type-workspace.context.ts | 4 +- .../block}/block-editor-custom-view.model.ts | 8 ++- .../context/block-entries.context-token.ts | 2 +- .../block/context/block-entries.context.ts | 2 +- .../context/block-entry.context-token.ts | 2 +- .../block/context/block-entry.context.ts | 2 +- .../block/context/block-manager.context.ts | 2 +- src/packages/block/block/index.ts | 2 +- .../block-catalogue-modal.token.ts | 3 +- src/packages/block/block/types.ts | 49 +++++++++++++++- .../block/custom-view/custom-view.element.ts | 2 +- src/packages/block/custom-view/manifest.ts | 4 +- ...ck-editor-custom-view-element.interface.ts | 57 ------------------- .../extension-registry/interfaces/index.ts | 1 - .../core/extension-registry/models/index.ts | 3 - ...ui-block-rte-type-configuration.element.ts | 4 +- 31 files changed, 104 insertions(+), 114 deletions(-) rename src/packages/{core/extension-registry/models => block/block}/block-editor-custom-view.model.ts (84%) delete mode 100644 src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts diff --git a/examples/block-custom-view/block-custom-view.ts b/examples/block-custom-view/block-custom-view.ts index e564f537a6..61f207d30c 100644 --- a/examples/block-custom-view/block-custom-view.ts +++ b/examples/block-custom-view/block-custom-view.ts @@ -1,7 +1,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { html, customElement, LitElement, property, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; -import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block'; // eslint-disable-next-line local-rules/enforce-umb-prefix-on-element-name @customElement('example-block-custom-view') diff --git a/examples/block-custom-view/index.ts b/examples/block-custom-view/index.ts index da81e169ac..25c1f19d2a 100644 --- a/examples/block-custom-view/index.ts +++ b/examples/block-custom-view/index.ts @@ -1,6 +1,4 @@ -import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [ +export const manifests: Array = [ { type: 'blockEditorCustomView', alias: 'Umb.blockEditorCustomView.TestView', diff --git a/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts b/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts index 08948600e1..7aac7408c7 100644 --- a/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts +++ b/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts @@ -3,9 +3,9 @@ import { UmbBlockGridInlinePropertyDatasetContext } from './block-grid-inline-pr import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; -import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/extension-registry'; import '../block-grid-areas-container/index.js'; import '../ref-grid-block/index.js'; +import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block'; /** * @element umb-block-grid-block-inline diff --git a/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts b/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts index 67cd1c81e7..325db2f6d9 100644 --- a/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts +++ b/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts @@ -1,8 +1,7 @@ import { UMB_BLOCK_GRID_ENTRY_CONTEXT } from '../../context/block-grid-entry.context-token.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/extension-registry'; -import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockDataType, UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block'; import '@umbraco-cms/backoffice/ufm'; import '../block-grid-areas-container/index.js'; diff --git a/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts b/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts index 291e9f269d..b8e9ccf1e9 100644 --- a/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts +++ b/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts @@ -2,11 +2,7 @@ import { UmbBlockGridEntryContext } from '../../context/block-grid-entry.context import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; -import type { - ManifestBlockEditorCustomView, - UmbBlockEditorCustomViewProperties, - UmbPropertyEditorUiElement, -} from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import { UMB_BLOCK_GRID, type UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid'; @@ -14,7 +10,11 @@ import '../block-grid-block-inline/index.js'; import '../block-grid-block/index.js'; import '../block-scale-handler/index.js'; import { UmbObserveValidationStateController } from '@umbraco-cms/backoffice/validation'; -import { UmbDataPathBlockElementDataQuery } from '@umbraco-cms/backoffice/block'; +import { + type ManifestBlockEditorCustomView, + UmbDataPathBlockElementDataQuery, + type UmbBlockEditorCustomViewProperties, +} from '@umbraco-cms/backoffice/block'; import { UUIBlinkAnimationValue, UUIBlinkKeyframes } from '@umbraco-cms/backoffice/external/uui'; import type { UmbExtensionElementInitializer } from '@umbraco-cms/backoffice/extension-api'; /** diff --git a/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts b/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts index 4beee2607a..8cd7361a1e 100644 --- a/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts +++ b/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts @@ -2,16 +2,13 @@ import { UmbBlockListEntryContext } from '../../context/block-list-entry.context import { UMB_BLOCK_LIST, type UmbBlockListLayoutModel } from '../../types.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; -import type { - ManifestBlockEditorCustomView, - UmbBlockEditorCustomViewProperties, - UmbPropertyEditorUiElement, -} from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import '../ref-list-block/index.js'; import '../inline-list-block/index.js'; import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import { UmbObserveValidationStateController } from '@umbraco-cms/backoffice/validation'; import { UmbDataPathBlockElementDataQuery } from '@umbraco-cms/backoffice/block'; +import type { ManifestBlockEditorCustomView, UmbBlockEditorCustomViewProperties } from '@umbraco-cms/backoffice/block'; /** * @element umb-block-list-entry diff --git a/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index 2d60a0d689..dc71f8ebf7 100644 --- a/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -6,7 +6,7 @@ import { UMB_BLOCK_LIST_PROPERTY_EDITOR_ALIAS } from './manifests.js'; import { UmbLitElement, umbDestroyOnDisconnect } from '@umbraco-cms/backoffice/lit-element'; import { html, customElement, property, state, repeat, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbPropertyEditorUiElement, UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbPropertyValueChangeEvent, type UmbPropertyEditorConfigCollection, @@ -19,6 +19,7 @@ import { UmbBlockElementDataValidationPathTranslator, type UmbBlockLayoutBaseModel, } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import '../../components/block-list-entry/index.js'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; diff --git a/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts b/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts index 639175c2fb..53154a5743 100644 --- a/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts +++ b/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts @@ -1,7 +1,7 @@ import '../../../block-type/components/input-block-type/index.js'; -import type { UmbInputBlockTypeElement } from '../../../block-type/index.js'; import { UMB_BLOCK_LIST_TYPE } from '../../types.js'; -import type { UmbBlockTypeBaseModel, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel, UmbInputBlockTypeElement } from '@umbraco-cms/backoffice/block-type'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbPropertyValueChangeEvent, diff --git a/src/packages/block/block-list/types.ts b/src/packages/block/block-list/types.ts index 31c8dd7a55..94ff232c27 100644 --- a/src/packages/block/block-list/types.ts +++ b/src/packages/block/block-list/types.ts @@ -1,5 +1,5 @@ -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; export const UMB_BLOCK_LIST_TYPE = 'block-list-type'; export const UMB_BLOCK_LIST = 'block-list'; diff --git a/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts b/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts index 3ca6afa49d..8c52ee27a9 100644 --- a/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts +++ b/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts @@ -2,11 +2,9 @@ import type { UmbBlockRteLayoutModel } from '../../types.js'; import { UmbBlockRteEntryContext } from '../../context/block-rte-entry.context.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, property, state, customElement } from '@umbraco-cms/backoffice/external/lit'; -import type { - UmbBlockEditorCustomViewProperties, - UmbPropertyEditorUiElement, -} from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import type { UmbBlockEditorCustomViewProperties } from '@umbraco-cms/backoffice/block'; import '../ref-rte-block/index.js'; diff --git a/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts b/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts index 66fbd90b8c..8c01d6d7e6 100644 --- a/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts +++ b/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts @@ -2,7 +2,7 @@ import { UMB_BLOCK_RTE_MANAGER_CONTEXT } from '../context/block-rte-manager.cont import { UMB_BLOCK_RTE_ENTRIES_CONTEXT } from '../context/block-rte-entries.context-token.js'; import { type TinyMcePluginArguments, UmbTinyMcePluginBase } from '@umbraco-cms/backoffice/tiny-mce'; import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; export default class UmbTinyMceMultiUrlPickerPlugin extends UmbTinyMcePluginBase { #localize = new UmbLocalizationController(this._host); diff --git a/src/packages/block/block-rte/types.ts b/src/packages/block/block-rte/types.ts index ea18ec9bad..c97075ec68 100644 --- a/src/packages/block/block-rte/types.ts +++ b/src/packages/block/block-rte/types.ts @@ -1,4 +1,4 @@ -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; export const UMB_BLOCK_RTE_TYPE = 'block-rte-type'; diff --git a/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts b/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts index ef5347f3d5..7dbbe77f25 100644 --- a/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts +++ b/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts @@ -2,11 +2,12 @@ import { UMB_MANIFEST_VIEWER_MODAL } from '../../../modals/manifest-viewer/index import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, customElement, state, property, css } from '@umbraco-cms/backoffice/external/lit'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; -import { umbExtensionsRegistry, type ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/extension-registry'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import { UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/block'; @customElement('umb-block-type-custom-view-guide') export class UmbBlockTypeCustomViewGuideElement extends UmbLitElement { @@ -88,7 +89,7 @@ export class UmbBlockTypeCustomViewGuideElement extends UmbLitElement { async #generateManifest() { const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const manifest = { + const manifest: UmbManifestTypes = { type: 'blockEditorCustomView', alias: 'Local.blockEditorCustomView.' + this.#contentTypeAlias, name: 'Block Editor Custom View for ' + this.#contentTypeName, diff --git a/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index cade6212d8..2c6380be9f 100644 --- a/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -12,7 +12,7 @@ import { UMB_DOCUMENT_TYPE_PICKER_MODAL, } from '@umbraco-cms/backoffice/document-type'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import '../block-type-card/index.js'; diff --git a/src/packages/block/block-type/types.ts b/src/packages/block/block-type/types.ts index 4bb332af04..ece8e83203 100644 --- a/src/packages/block/block-type/types.ts +++ b/src/packages/block/block-type/types.ts @@ -1,6 +1,15 @@ -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; -export type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; - +import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; +// Shared with the Property Editor +export interface UmbBlockTypeBaseModel { + contentElementTypeKey: string; + settingsElementTypeKey?: string; + label?: string; + thumbnail?: string; + iconColor?: string; + backgroundColor?: string; + editorSize?: UUIModalSidebarSize; + forceHideContentEditorInOverlay: boolean; +} export interface UmbBlockTypeGroup { name?: string; key: string; diff --git a/src/packages/block/block-type/workspace/block-type-workspace.context.ts b/src/packages/block/block-type/workspace/block-type-workspace.context.ts index c50aad7dbb..61b2adb6a3 100644 --- a/src/packages/block/block-type/workspace/block-type-workspace.context.ts +++ b/src/packages/block/block-type/workspace/block-type-workspace.context.ts @@ -1,4 +1,4 @@ -import type { UmbBlockTypeWithGroupKey } from '../types.js'; +import type { UmbBlockTypeBaseModel, UmbBlockTypeWithGroupKey } from '../types.js'; import { UmbBlockTypeWorkspaceEditorElement } from './block-type-workspace-editor.element.js'; import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; @@ -13,7 +13,7 @@ import { } from '@umbraco-cms/backoffice/workspace'; import { UmbObjectState, appendToFrozenArray } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import type { ManifestWorkspace, UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry'; export class UmbBlockTypeWorkspaceContext extends UmbSubmittableWorkspaceContextBase diff --git a/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts b/src/packages/block/block/block-editor-custom-view.model.ts similarity index 84% rename from src/packages/core/extension-registry/models/block-editor-custom-view.model.ts rename to src/packages/block/block/block-editor-custom-view.model.ts index 55a8208789..9bbb3cd298 100644 --- a/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts +++ b/src/packages/block/block/block-editor-custom-view.model.ts @@ -1,4 +1,4 @@ -import type { UmbBlockEditorCustomViewElement } from '../interfaces/index.js'; +import type { UmbBlockEditorCustomViewElement } from './types.js'; import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api'; export interface ManifestBlockEditorCustomView extends ManifestElement { @@ -18,3 +18,9 @@ export interface ManifestBlockEditorCustomView extends ManifestElement; } + +declare global { + interface UmbManifestType { + blockEditorCustomView: ManifestBlockEditorCustomView; + } +} diff --git a/src/packages/block/block/context/block-entries.context-token.ts b/src/packages/block/block/context/block-entries.context-token.ts index 75b2db18d9..e98e9607a0 100644 --- a/src/packages/block/block/context/block-entries.context-token.ts +++ b/src/packages/block/block/context/block-entries.context-token.ts @@ -3,7 +3,7 @@ import type { UmbBlockWorkspaceOriginData } from '../workspace/block-workspace.m import type { UmbBlockEntriesContext } from './block-entries.context.js'; import type { UMB_BLOCK_MANAGER_CONTEXT } from './block-manager.context-token.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; export const UMB_BLOCK_ENTRIES_CONTEXT = new UmbContextToken< UmbBlockEntriesContext< diff --git a/src/packages/block/block/context/block-entries.context.ts b/src/packages/block/block/context/block-entries.context.ts index 234c942397..e5cb10d0b0 100644 --- a/src/packages/block/block/context/block-entries.context.ts +++ b/src/packages/block/block/context/block-entries.context.ts @@ -4,10 +4,10 @@ import type { UmbBlockDataObjectModel, UmbBlockManagerContext } from './block-ma import { UMB_BLOCK_ENTRIES_CONTEXT } from './block-entries.context-token.js'; import { type Observable, UmbArrayState, UmbBasicState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; export abstract class UmbBlockEntriesContext< BlockManagerContextTokenType extends UmbContextToken, diff --git a/src/packages/block/block/context/block-entry.context-token.ts b/src/packages/block/block/context/block-entry.context-token.ts index 93b66d9b29..f913bec728 100644 --- a/src/packages/block/block/context/block-entry.context-token.ts +++ b/src/packages/block/block/context/block-entry.context-token.ts @@ -4,7 +4,7 @@ import type { UMB_BLOCK_ENTRIES_CONTEXT } from './block-entries.context-token.js import type { UmbBlockEntriesContext } from './block-entries.context.js'; import type { UmbBlockEntryContext } from './block-entry.context.js'; import type { UMB_BLOCK_MANAGER_CONTEXT } from './block-manager.context-token.js'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; export const UMB_BLOCK_ENTRY_CONTEXT = new UmbContextToken< diff --git a/src/packages/block/block/context/block-entry.context.ts b/src/packages/block/block/context/block-entry.context.ts index c338636571..e8fddb2ec3 100644 --- a/src/packages/block/block/context/block-entry.context.ts +++ b/src/packages/block/block/context/block-entry.context.ts @@ -15,7 +15,7 @@ import { encodeFilePath } from '@umbraco-cms/backoffice/utils'; import { umbConfirmModal } from '@umbraco-cms/backoffice/modal'; import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; export abstract class UmbBlockEntryContext< BlockManagerContextTokenType extends UmbContextToken, diff --git a/src/packages/block/block/context/block-manager.context.ts b/src/packages/block/block/context/block-manager.context.ts index df113d9b81..942ef5efe0 100644 --- a/src/packages/block/block/context/block-manager.context.ts +++ b/src/packages/block/block/context/block-manager.context.ts @@ -5,12 +5,12 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbArrayState, UmbBooleanState, UmbClassState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; /** * diff --git a/src/packages/block/block/index.ts b/src/packages/block/block/index.ts index 0e7cb3f0dc..316fbaa517 100644 --- a/src/packages/block/block/index.ts +++ b/src/packages/block/block/index.ts @@ -1,5 +1,5 @@ export * from './context/index.js'; export * from './modals/index.js'; -export * from './types.js'; +export type * from './types.js'; export * from './validation/index.js'; export * from './workspace/index.js'; diff --git a/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts b/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts index d4fbc36096..743d522379 100644 --- a/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts +++ b/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts @@ -1,7 +1,6 @@ -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; import type { UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block'; -import type { UmbBlockTypeGroup } from '@umbraco-cms/backoffice/block-type'; +import type { UmbBlockTypeGroup, UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; export interface UmbBlockCatalogueModalData { blocks: Array; diff --git a/src/packages/block/block/types.ts b/src/packages/block/block/types.ts index 7c11cec0ac..55a2123751 100644 --- a/src/packages/block/block/types.ts +++ b/src/packages/block/block/types.ts @@ -1,5 +1,50 @@ -import type { UmbBlockDataType, UmbBlockLayoutBaseModel } from '@umbraco-cms/backoffice/extension-registry'; -export type { UmbBlockDataType, UmbBlockLayoutBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestBlockEditorCustomView } from './block-editor-custom-view.model.js'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; +export type { ManifestBlockEditorCustomView } from './block-editor-custom-view.model.js'; + +// Shared with the Property Editor +export interface UmbBlockLayoutBaseModel { + contentUdi: string; + settingsUdi?: string | null; +} + +// Shared with the Property Editor +export interface UmbBlockDataType { + udi: string; + contentTypeKey: string; + [key: string]: unknown; +} + +export interface UmbBlockEditorCustomViewConfiguration { + editContentPath?: string; + editSettingsPath?: string; + showContentEdit: boolean; + showSettingsEdit: boolean; +} + +export interface UmbBlockEditorCustomViewProperties< + LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, + BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, +> { + manifest?: ManifestBlockEditorCustomView; + config?: Partial; + blockType?: BlockType; + contentUdi?: string; + label?: string; + icon?: string; + index?: number; + layout?: LayoutType; + content?: UmbBlockDataType; + settings?: UmbBlockDataType; + contentInvalid?: boolean; + settingsInvalid?: boolean; +} + +export interface UmbBlockEditorCustomViewElement< + LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, + BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, +> extends UmbBlockEditorCustomViewProperties, + HTMLElement {} export interface UmbBlockValueType { layout: { [key: string]: Array | undefined }; diff --git a/src/packages/block/custom-view/custom-view.element.ts b/src/packages/block/custom-view/custom-view.element.ts index 9ac9fff679..3160976674 100644 --- a/src/packages/block/custom-view/custom-view.element.ts +++ b/src/packages/block/custom-view/custom-view.element.ts @@ -1,4 +1,4 @@ -import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block'; import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/packages/block/custom-view/manifest.ts b/src/packages/block/custom-view/manifest.ts index 71839f5ac4..f99b3893f1 100644 --- a/src/packages/block/custom-view/manifest.ts +++ b/src/packages/block/custom-view/manifest.ts @@ -1,6 +1,4 @@ -import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifest: ManifestBlockEditorCustomView = { +export const manifest: UmbManifestTypes = { type: 'blockEditorCustomView', alias: 'Umb.blockEditorCustomView.TestView', name: 'Block Editor Custom View Test', diff --git a/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts b/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts deleted file mode 100644 index 35ed551b97..0000000000 --- a/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { ManifestBlockEditorCustomView } from '../index.js'; -import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; -// Shared with the Property Editor -export interface UmbBlockTypeBaseModel { - contentElementTypeKey: string; - settingsElementTypeKey?: string; - label?: string; - thumbnail?: string; - iconColor?: string; - backgroundColor?: string; - editorSize?: UUIModalSidebarSize; - forceHideContentEditorInOverlay: boolean; -} - -// Shared with the Property Editor -export interface UmbBlockLayoutBaseModel { - contentUdi: string; - settingsUdi?: string | null; -} - -// Shared with the Property Editor -export interface UmbBlockDataType { - udi: string; - contentTypeKey: string; - [key: string]: unknown; -} - -export interface UmbBlockEditorCustomViewConfiguration { - editContentPath?: string; - editSettingsPath?: string; - showContentEdit: boolean; - showSettingsEdit: boolean; -} - -export interface UmbBlockEditorCustomViewProperties< - LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, - BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, -> { - manifest?: ManifestBlockEditorCustomView; - config?: Partial; - blockType?: BlockType; - contentUdi?: string; - label?: string; - icon?: string; - index?: number; - layout?: LayoutType; - content?: UmbBlockDataType; - settings?: UmbBlockDataType; - contentInvalid?: boolean; - settingsInvalid?: boolean; -} - -export interface UmbBlockEditorCustomViewElement< - LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, - BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, -> extends UmbBlockEditorCustomViewProperties, - HTMLElement {} diff --git a/src/packages/core/extension-registry/interfaces/index.ts b/src/packages/core/extension-registry/interfaces/index.ts index 7585b5001b..1721b7dfec 100644 --- a/src/packages/core/extension-registry/interfaces/index.ts +++ b/src/packages/core/extension-registry/interfaces/index.ts @@ -1,4 +1,3 @@ -export * from './block-editor-custom-view-element.interface.js'; export * from './dashboard-element.interface.js'; export * from './external-login-provider-element.interface.js'; export * from './menu-item-element.interface.js'; diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts index de089cb774..c3386877ae 100644 --- a/src/packages/core/extension-registry/models/index.ts +++ b/src/packages/core/extension-registry/models/index.ts @@ -1,5 +1,4 @@ import type { ManifestAuthProvider } from './auth-provider.model.js'; -import type { ManifestBlockEditorCustomView } from './block-editor-custom-view.model.js'; import type { ManifestCollection } from './collection.models.js'; import type { ManifestCollectionView } from './collection-view.model.js'; import type { ManifestCurrentUserAction, ManifestCurrentUserActionDefaultKind } from './current-user-action.model.js'; @@ -77,7 +76,6 @@ import type { ManifestBase, ManifestBundle, ManifestCondition } from '@umbraco-c export type * from './app-entry-point.model.js'; export type * from './auth-provider.model.js'; export type * from './backoffice-entry-point.model.js'; -export type * from './block-editor-custom-view.model.js'; export type * from './collection-action.model.js'; export type * from './collection-view.model.js'; export type * from './collection.models.js'; @@ -158,7 +156,6 @@ export type ManifestTypes = | ManifestAppEntryPoint | ManifestAuthProvider | ManifestBackofficeEntryPoint - | ManifestBlockEditorCustomView | ManifestBundle | ManifestCollection | ManifestCollectionAction diff --git a/src/packages/tiny-mce/property-editors/block/property-editor-ui-block-rte-type-configuration.element.ts b/src/packages/tiny-mce/property-editors/block/property-editor-ui-block-rte-type-configuration.element.ts index 2b59427770..264dab15ba 100644 --- a/src/packages/tiny-mce/property-editors/block/property-editor-ui-block-rte-type-configuration.element.ts +++ b/src/packages/tiny-mce/property-editors/block/property-editor-ui-block-rte-type-configuration.element.ts @@ -1,6 +1,6 @@ -import { UmbInputBlockTypeElement } from '@umbraco-cms/backoffice/block-type'; +import { type UmbBlockTypeBaseModel, UmbInputBlockTypeElement } from '@umbraco-cms/backoffice/block-type'; import { UMB_BLOCK_RTE_TYPE } from '@umbraco-cms/backoffice/block-rte'; -import type { UmbBlockTypeBaseModel, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbPropertyValueChangeEvent, From bd571359be333ace6cd2522e9f18f84ba550ee79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 30 Aug 2024 23:25:14 +0200 Subject: [PATCH 016/322] JS Docs --- .../core/extension-registry/models/index.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts index c3386877ae..d2efd62c42 100644 --- a/src/packages/core/extension-registry/models/index.ts +++ b/src/packages/core/extension-registry/models/index.ts @@ -219,8 +219,24 @@ export type ManifestTypes = type UnionOfProperties = T extends object ? T[keyof T] : never; declare global { + /** + * This global type allows to declare manifests types from its own module. + * @example + * ```js + declare global { + interface UmbManifestType { + My_UNIQUE_MANIFEST_NAME: ManifestTypes; + } + } + * ``` + */ interface UmbManifestType { - CORE: ManifestTypes; + UMB_CORE: ManifestTypes; } + + /** + * This global type provides a union of all declared manifest types. + * If this is a local package that declares additional Manifest Types, then these will also be included in this union. + */ type UmbManifestTypes = UnionOfProperties; } From 6fa37940361476acdf5c445d23200a3263cccbcb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 13:11:19 +0200 Subject: [PATCH 017/322] add kind as observable part on user workspace --- src/packages/user/user/workspace/user-workspace.context.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/packages/user/user/workspace/user-workspace.context.ts b/src/packages/user/user/workspace/user-workspace.context.ts index 088d944b4f..69587e191d 100644 --- a/src/packages/user/user/workspace/user-workspace.context.ts +++ b/src/packages/user/user/workspace/user-workspace.context.ts @@ -25,6 +25,7 @@ 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 kind = this.#currentData.asObservablePart((x) => x?.kind); readonly userGroupUniques = this.#currentData.asObservablePart((x) => x?.userGroupUniques || []); readonly documentStartNodeUniques = this.#currentData.asObservablePart( (data) => data?.documentStartNodeUniques || [], From 84ecccb89fd45d7ce8187efaa273d978dfe42dfa Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 13:11:39 +0200 Subject: [PATCH 018/322] observe user kind in user condition base --- .../user-allow-action-base.condition.ts | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/packages/user/user/conditions/user-allow-action-base.condition.ts b/src/packages/user/user/conditions/user-allow-action-base.condition.ts index 161f04d1b4..fb5bf0f8d1 100644 --- a/src/packages/user/user/conditions/user-allow-action-base.condition.ts +++ b/src/packages/user/user/conditions/user-allow-action-base.condition.ts @@ -16,23 +16,45 @@ export abstract class UmbUserActionConditionBase { /** * The unique identifier of the user being edited + * @protected + * @type {string} + * @memberof UmbUserActionConditionBase */ protected userUnique?: string; /** * The state of the user being edited + * @protected + * @type {(UmbUserStateEnum | null)} + * @memberof UmbUserActionConditionBase */ protected userState?: UmbUserStateEnum | null; + /** + * The kind of user being edited + * @protected + * @type {string} + * @memberof UmbUserActionConditionBase + */ + protected userKind?: string; + + /** + * Creates an instance of UmbUserActionConditionBase. + * @param {UmbControllerHost} host The host controller + * @param {UmbConditionControllerArguments} args The condition arguments + * @memberof UmbUserActionConditionBase + */ constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { super(host, args); this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (context) => { + console.log(context); this.observe( - observeMultiple([context.unique, context.state]), - ([unique, state]) => { + observeMultiple([context.unique, context.state, context.kind]), + ([unique, state, kind]) => { this.userUnique = unique; this.userState = state; + this.userKind = kind; this._onUserDataChange(); }, '_umbActiveUser', From c0ae5e8f01ac11a051a65138cca1c9147c81eccd Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 13:12:04 +0200 Subject: [PATCH 019/322] register allow change password condition --- src/packages/user/change-password/manifests.ts | 5 +++++ .../conditions/allow-change-password/manifests.ts | 10 ++++++++++ ...user-allow-change-password-action.condition.ts | 15 +++++++++++++++ src/packages/user/user/conditions/manifests.ts | 6 ++++-- 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 src/packages/user/user/conditions/allow-change-password/manifests.ts create mode 100644 src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts diff --git a/src/packages/user/change-password/manifests.ts b/src/packages/user/change-password/manifests.ts index 083dc29663..0a16bdecd3 100644 --- a/src/packages/user/change-password/manifests.ts +++ b/src/packages/user/change-password/manifests.ts @@ -14,6 +14,11 @@ export const manifests: Array = [ icon: 'icon-key', label: '#user_changePassword', }, + conditions: [ + { + alias: 'Umb.Condition.User.AllowChangePassword', + }, + ], }, { type: 'modal', diff --git a/src/packages/user/user/conditions/allow-change-password/manifests.ts b/src/packages/user/user/conditions/allow-change-password/manifests.ts new file mode 100644 index 0000000000..a144bfcb8e --- /dev/null +++ b/src/packages/user/user/conditions/allow-change-password/manifests.ts @@ -0,0 +1,10 @@ +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'condition', + name: 'User Allow Change Password Condition', + alias: 'Umb.Condition.User.AllowChangePassword', + api: () => import('./user-allow-change-password-action.condition.js'), + }, +]; diff --git a/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts b/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts new file mode 100644 index 0000000000..ed78c34e78 --- /dev/null +++ b/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts @@ -0,0 +1,15 @@ +import { UmbUserModelKind } from '../../utils/index.js'; +import { UmbUserActionConditionBase } from '../user-allow-action-base.condition.js'; + +export class UmbUserAllowChangePasswordActionCondition extends UmbUserActionConditionBase { + async _onUserDataChange() { + // don't allow the current user to delete themselves + if (this.userKind === UmbUserModelKind.DEFAULT) { + this.permitted = true; + } else { + this.permitted = false; + } + } +} + +export { UmbUserAllowChangePasswordActionCondition as api }; diff --git a/src/packages/user/user/conditions/manifests.ts b/src/packages/user/user/conditions/manifests.ts index 23b03f4ec4..4851681f7c 100644 --- a/src/packages/user/user/conditions/manifests.ts +++ b/src/packages/user/user/conditions/manifests.ts @@ -1,3 +1,4 @@ +import { manifests as userAllowChangePasswordActionManifests } from './allow-change-password/manifests.js'; import { manifests as userAllowDeleteActionManifests } from './allow-delete/manifests.js'; import { manifests as userAllowDisableActionManifests } from './allow-disable/manifests.js'; import { manifests as userAllowEnableActionManifests } from './allow-enable/manifests.js'; @@ -7,10 +8,11 @@ import { manifests as userAllowUnlockActionManifests } from './allow-unlock/mani import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ + ...userAllowChangePasswordActionManifests, + ...userAllowDeleteActionManifests, ...userAllowDisableActionManifests, ...userAllowEnableActionManifests, - ...userAllowUnlockActionManifests, ...userAllowExternalLoginActionManifests, ...userAllowMfaActionManifests, - ...userAllowDeleteActionManifests, + ...userAllowUnlockActionManifests, ]; From 5397b8201c913dce797f6d791bacb0eff36e2712 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 14:52:29 +0200 Subject: [PATCH 020/322] add interface for client credentials server data source --- .../client-credential/repository/types.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/packages/user/user/client-credential/repository/types.ts diff --git a/src/packages/user/user/client-credential/repository/types.ts b/src/packages/user/user/client-credential/repository/types.ts new file mode 100644 index 0000000000..4573cc9a33 --- /dev/null +++ b/src/packages/user/user/client-credential/repository/types.ts @@ -0,0 +1,21 @@ +import type { UmbDataSourceErrorResponse, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; + +export interface UmbUserClientCredentialsDataSourceCreateArgs { + user: { unique: string }; + client: { unique: string; secret: string }; +} + +export interface UmbUserClientCredentialsDataSourceReadArgs { + user: { unique: string }; +} + +export interface UmbUserClientCredentialsDataSourceDeleteArgs { + user: { unique: string }; + client: { unique: string }; +} + +export interface UmbUserClientCredentialsDataSource { + create(args: UmbUserClientCredentialsDataSourceCreateArgs): Promise; + read(args: UmbUserClientCredentialsDataSourceReadArgs): Promise>>; + delete: (args: UmbUserClientCredentialsDataSourceDeleteArgs) => Promise; +} From 3e4c34d3832e5f11ec0eecc698c247d103d70486 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 14:52:45 +0200 Subject: [PATCH 021/322] add server client credentials data source --- ...r-client-credentials.server.data-source.ts | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts diff --git a/src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts b/src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts new file mode 100644 index 0000000000..8e795fca35 --- /dev/null +++ b/src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts @@ -0,0 +1,73 @@ +import type { + UmbUserClientCredentialsDataSource, + UmbUserClientCredentialsDataSourceCreateArgs, + UmbUserClientCredentialsDataSourceDeleteArgs, + UmbUserClientCredentialsDataSourceReadArgs, +} from './types.js'; +import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; + +/** + * Server data source for user client credentials + * @export + * @class UmbUserClientCredentialsServerDataSource + * @implements {UmbUserClientCredentialsDataSource} + */ +export class UmbUserClientCredentialsServerDataSource implements UmbUserClientCredentialsDataSource { + #host: UmbControllerHost; + + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Creates a new client credentials for a user + * @param {UmbUserClientCredentialsDataSourceCreateArgs} args - The user and client to create the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialsServerDataSource + */ + create(args: UmbUserClientCredentialsDataSourceCreateArgs) { + return tryExecuteAndNotify( + this.#host, + UserService.postUserByIdClientCredentials({ + id: args.user.unique, + requestBody: { + clientId: args.client.unique, + clientSecret: args.client.secret, + }, + }), + ); + } + + /** + * Reads the client credentials for a user + * @param {UmbUserClientCredentialsDataSourceReadArgs} args - The user to read the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialsServerDataSource + */ + read(args: UmbUserClientCredentialsDataSourceReadArgs) { + return tryExecuteAndNotify( + this.#host, + UserService.getUserByIdClientCredentials({ + id: args.user.unique, + }), + ); + } + + /** + * Deletes the client credentials for a user + * @param {UmbUserClientCredentialsDataSourceDeleteArgs} args - The user and client unique to delete the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialsServerDataSource + */ + delete(args: UmbUserClientCredentialsDataSourceDeleteArgs) { + return tryExecuteAndNotify( + this.#host, + UserService.deleteUserByIdClientCredentialsByClientId({ + id: args.user.unique, + clientId: args.client.unique, + }), + ); + } +} From fc2478c726cbe7e35d1c3ace7bf4e0c5dcf24450 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 14:52:56 +0200 Subject: [PATCH 022/322] Create index.ts --- src/packages/user/user/client-credential/index.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/packages/user/user/client-credential/index.ts diff --git a/src/packages/user/user/client-credential/index.ts b/src/packages/user/user/client-credential/index.ts new file mode 100644 index 0000000000..e69de29bb2 From 0765022dc918ba66c0c994c0306e4858fe95234e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 14:53:06 +0200 Subject: [PATCH 023/322] add repository alias --- src/packages/user/user/client-credential/repository/constants.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/packages/user/user/client-credential/repository/constants.ts diff --git a/src/packages/user/user/client-credential/repository/constants.ts b/src/packages/user/user/client-credential/repository/constants.ts new file mode 100644 index 0000000000..7e4e853a5d --- /dev/null +++ b/src/packages/user/user/client-credential/repository/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_CLIENT_CREDENTIALS_REPOSITORY_ALIAS = 'Umb.Repository.User.ClientCredentials'; From a96e7ee83b4e13243041a0468125b63e6e310ef9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 15:14:55 +0200 Subject: [PATCH 024/322] return credential as an object --- .../repository/data-source/index.ts | 2 ++ .../repository/data-source/types.ts | 24 +++++++++++++++++++ ...r-client-credentials.server.data-source.ts | 14 +++++++++-- 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 src/packages/user/user/client-credential/repository/data-source/index.ts create mode 100644 src/packages/user/user/client-credential/repository/data-source/types.ts rename src/packages/user/user/client-credential/repository/{ => data-source}/user-client-credentials.server.data-source.ts (88%) diff --git a/src/packages/user/user/client-credential/repository/data-source/index.ts b/src/packages/user/user/client-credential/repository/data-source/index.ts new file mode 100644 index 0000000000..16f734cbcb --- /dev/null +++ b/src/packages/user/user/client-credential/repository/data-source/index.ts @@ -0,0 +1,2 @@ +export * from './types.js'; +export * from './user-client-credentials.server.data-source.js'; diff --git a/src/packages/user/user/client-credential/repository/data-source/types.ts b/src/packages/user/user/client-credential/repository/data-source/types.ts new file mode 100644 index 0000000000..14e6dd533e --- /dev/null +++ b/src/packages/user/user/client-credential/repository/data-source/types.ts @@ -0,0 +1,24 @@ +import type { UmbUserClientCredentialModel } from '../types.js'; +import type { UmbDataSourceErrorResponse, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; + +export interface UmbUserClientCredentialsDataSourceCreateArgs { + user: { unique: string }; + client: { unique: string; secret: string }; +} + +export interface UmbUserClientCredentialsDataSourceReadArgs { + user: { unique: string }; +} + +export interface UmbUserClientCredentialsDataSourceDeleteArgs { + user: { unique: string }; + client: { unique: string }; +} + +export interface UmbUserClientCredentialsDataSource { + create(args: UmbUserClientCredentialsDataSourceCreateArgs): Promise; + read( + args: UmbUserClientCredentialsDataSourceReadArgs, + ): Promise>>; + delete: (args: UmbUserClientCredentialsDataSourceDeleteArgs) => Promise; +} diff --git a/src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts b/src/packages/user/user/client-credential/repository/data-source/user-client-credentials.server.data-source.ts similarity index 88% rename from src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts rename to src/packages/user/user/client-credential/repository/data-source/user-client-credentials.server.data-source.ts index 8e795fca35..c140625b7a 100644 --- a/src/packages/user/user/client-credential/repository/user-client-credentials.server.data-source.ts +++ b/src/packages/user/user/client-credential/repository/data-source/user-client-credentials.server.data-source.ts @@ -46,13 +46,23 @@ export class UmbUserClientCredentialsServerDataSource implements UmbUserClientCr * @returns {*} * @memberof UmbUserClientCredentialsServerDataSource */ - read(args: UmbUserClientCredentialsDataSourceReadArgs) { - return tryExecuteAndNotify( + async read(args: UmbUserClientCredentialsDataSourceReadArgs) { + const { data, error } = await tryExecuteAndNotify( this.#host, UserService.getUserByIdClientCredentials({ id: args.user.unique, }), ); + + if (data) { + const credentials = data.map((clientId) => ({ + unique: clientId, + })); + + return { data: credentials }; + } + + return { error }; } /** From ba34d809e9e234c52fe6fa842264df36c387f633 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 15:18:32 +0200 Subject: [PATCH 025/322] add repository --- .../client-credential/repository/index.ts | 2 + .../client-credential/repository/manifests.ts | 11 ++++ .../client-credential/repository/types.ts | 32 ++++------ .../user-client-credentials.repository.ts | 61 +++++++++++++++++++ 4 files changed, 86 insertions(+), 20 deletions(-) create mode 100644 src/packages/user/user/client-credential/repository/index.ts create mode 100644 src/packages/user/user/client-credential/repository/manifests.ts create mode 100644 src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts diff --git a/src/packages/user/user/client-credential/repository/index.ts b/src/packages/user/user/client-credential/repository/index.ts new file mode 100644 index 0000000000..abf2760126 --- /dev/null +++ b/src/packages/user/user/client-credential/repository/index.ts @@ -0,0 +1,2 @@ +export * from './user-client-credentials.repository.js'; +export * from './constants.js'; diff --git a/src/packages/user/user/client-credential/repository/manifests.ts b/src/packages/user/user/client-credential/repository/manifests.ts new file mode 100644 index 0000000000..2c6b56a623 --- /dev/null +++ b/src/packages/user/user/client-credential/repository/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_USER_CLIENT_CREDENTIALS_REPOSITORY_ALIAS } from './constants.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'repository', + alias: UMB_USER_CLIENT_CREDENTIALS_REPOSITORY_ALIAS, + name: 'User Client Credentials Repository', + api: () => import('./user-client-credentials.repository.js'), + }, +]; diff --git a/src/packages/user/user/client-credential/repository/types.ts b/src/packages/user/user/client-credential/repository/types.ts index 4573cc9a33..a27c8121f7 100644 --- a/src/packages/user/user/client-credential/repository/types.ts +++ b/src/packages/user/user/client-credential/repository/types.ts @@ -1,21 +1,13 @@ -import type { UmbDataSourceErrorResponse, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; - -export interface UmbUserClientCredentialsDataSourceCreateArgs { - user: { unique: string }; - client: { unique: string; secret: string }; -} - -export interface UmbUserClientCredentialsDataSourceReadArgs { - user: { unique: string }; -} - -export interface UmbUserClientCredentialsDataSourceDeleteArgs { - user: { unique: string }; - client: { unique: string }; -} - -export interface UmbUserClientCredentialsDataSource { - create(args: UmbUserClientCredentialsDataSourceCreateArgs): Promise; - read(args: UmbUserClientCredentialsDataSourceReadArgs): Promise>>; - delete: (args: UmbUserClientCredentialsDataSourceDeleteArgs) => Promise; +import type { + UmbUserClientCredentialsDataSourceCreateArgs, + UmbUserClientCredentialsDataSourceDeleteArgs, + UmbUserClientCredentialsDataSourceReadArgs, +} from './data-source/index.js'; + +export type UmbUserClientCredentialsRepositoryCreateArgs = UmbUserClientCredentialsDataSourceCreateArgs; +export type UmbUserClientCredentialsRepositoryReadArgs = UmbUserClientCredentialsDataSourceReadArgs; +export type UmbUserClientCredentialsRepositoryDeleteArgs = UmbUserClientCredentialsDataSourceDeleteArgs; + +export interface UmbUserClientCredentialModel { + unique: string; } diff --git a/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts b/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts new file mode 100644 index 0000000000..338de3ab8f --- /dev/null +++ b/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts @@ -0,0 +1,61 @@ +import type { UmbUserClientCredentialsDataSource } from './data-source/index.js'; +import { UmbUserClientCredentialsServerDataSource } from './data-source/user-client-credentials.server.data-source.js'; +import type { + UmbUserClientCredentialsRepositoryCreateArgs, + UmbUserClientCredentialsRepositoryDeleteArgs, + UmbUserClientCredentialsRepositoryReadArgs, +} from './types.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +/** + * UmbUserClientCredentialsRepository + * @export + * @class UmbUserClientCredentialsRepository + * @extends {UmbRepositoryBase} + */ +export class UmbUserClientCredentialsRepository extends UmbRepositoryBase { + #source: UmbUserClientCredentialsDataSource; + + /** + * Creates an instance of UmbUserClientCredentialsRepository. + * @param {UmbControllerHost} host - The controller host + * @memberof UmbUserClientCredentialsRepository + */ + constructor(host: UmbControllerHost) { + super(host); + this.#source = new UmbUserClientCredentialsServerDataSource(host); + } + + /** + * Creates a new client credentials for a user + * @param {UmbUserClientCredentialsRepositoryCreateArgs} args - The user and client to create the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialsRepository + */ + async create(args: UmbUserClientCredentialsRepositoryCreateArgs) { + return this.#source.create(args); + } + + /** + * Reads the client credentials for a user + * @param {UmbUserClientCredentialsRepositoryReadArgs} args - The user to read the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialsRepository + */ + async read(args: UmbUserClientCredentialsRepositoryReadArgs) { + return this.#source.read(args); + } + + /** + * Deletes the client credentials for a user + * @param {UmbUserClientCredentialsRepositoryDeleteArgs} args - The user and client unique to delete the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialsRepository + */ + async delete(args: UmbUserClientCredentialsRepositoryDeleteArgs) { + return this.#source.delete(args); + } +} + +export { UmbUserClientCredentialsRepository as api }; From 6ee638dfad4483221522f43cc3fd21e2cb7681ef Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 16:01:42 +0200 Subject: [PATCH 026/322] clean up --- .../user/user/client-credential/index.ts | 1 + .../user/user/client-credential/manifests.ts | 1 + .../client-credential/repository/constants.ts | 2 +- .../repository/data-source/index.ts | 2 +- .../repository/data-source/types.ts | 31 +++------- ...r-client-credential.server.data-source.ts} | 34 +++++------ .../client-credential/repository/index.ts | 3 +- .../client-credential/repository/manifests.ts | 6 +- .../client-credential/repository/types.ts | 20 +++--- .../user-client-credential.repository.ts | 61 +++++++++++++++++++ .../user-client-credentials.repository.ts | 61 ------------------- src/packages/user/user/manifests.ts | 10 +-- 12 files changed, 115 insertions(+), 117 deletions(-) create mode 100644 src/packages/user/user/client-credential/manifests.ts rename src/packages/user/user/client-credential/repository/data-source/{user-client-credentials.server.data-source.ts => user-client-credential.server.data-source.ts} (55%) create mode 100644 src/packages/user/user/client-credential/repository/user-client-credential.repository.ts delete mode 100644 src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts diff --git a/src/packages/user/user/client-credential/index.ts b/src/packages/user/user/client-credential/index.ts index e69de29bb2..3d76f338dd 100644 --- a/src/packages/user/user/client-credential/index.ts +++ b/src/packages/user/user/client-credential/index.ts @@ -0,0 +1 @@ +export * from './repository/index.js'; diff --git a/src/packages/user/user/client-credential/manifests.ts b/src/packages/user/user/client-credential/manifests.ts new file mode 100644 index 0000000000..0a214139c1 --- /dev/null +++ b/src/packages/user/user/client-credential/manifests.ts @@ -0,0 +1 @@ +export * from './repository/manifests.js'; diff --git a/src/packages/user/user/client-credential/repository/constants.ts b/src/packages/user/user/client-credential/repository/constants.ts index 7e4e853a5d..6cbdba610a 100644 --- a/src/packages/user/user/client-credential/repository/constants.ts +++ b/src/packages/user/user/client-credential/repository/constants.ts @@ -1 +1 @@ -export const UMB_USER_CLIENT_CREDENTIALS_REPOSITORY_ALIAS = 'Umb.Repository.User.ClientCredentials'; +export const UMB_USER_CLIENT_CREDENTIAL_REPOSITORY_ALIAS = 'Umb.Repository.User.ClientCredential'; diff --git a/src/packages/user/user/client-credential/repository/data-source/index.ts b/src/packages/user/user/client-credential/repository/data-source/index.ts index 16f734cbcb..dd7152279d 100644 --- a/src/packages/user/user/client-credential/repository/data-source/index.ts +++ b/src/packages/user/user/client-credential/repository/data-source/index.ts @@ -1,2 +1,2 @@ export * from './types.js'; -export * from './user-client-credentials.server.data-source.js'; +export * from './user-client-credential.server.data-source.js'; diff --git a/src/packages/user/user/client-credential/repository/data-source/types.ts b/src/packages/user/user/client-credential/repository/data-source/types.ts index 14e6dd533e..0bbb27574a 100644 --- a/src/packages/user/user/client-credential/repository/data-source/types.ts +++ b/src/packages/user/user/client-credential/repository/data-source/types.ts @@ -1,24 +1,13 @@ -import type { UmbUserClientCredentialModel } from '../types.js'; +import type { + UmbCreateUserClientCredentialRequestArgs, + UmbDeleteUserClientCredentialRequestArgs, + UmbUserClientCredentialModel, + UmbUserClientCredentialRequestArgs, +} from '../types.js'; import type { UmbDataSourceErrorResponse, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; -export interface UmbUserClientCredentialsDataSourceCreateArgs { - user: { unique: string }; - client: { unique: string; secret: string }; -} - -export interface UmbUserClientCredentialsDataSourceReadArgs { - user: { unique: string }; -} - -export interface UmbUserClientCredentialsDataSourceDeleteArgs { - user: { unique: string }; - client: { unique: string }; -} - -export interface UmbUserClientCredentialsDataSource { - create(args: UmbUserClientCredentialsDataSourceCreateArgs): Promise; - read( - args: UmbUserClientCredentialsDataSourceReadArgs, - ): Promise>>; - delete: (args: UmbUserClientCredentialsDataSourceDeleteArgs) => Promise; +export interface UmbUserClientCredentialDataSource { + create(args: UmbCreateUserClientCredentialRequestArgs): Promise; + read(args: UmbUserClientCredentialRequestArgs): Promise>>; + delete: (args: UmbDeleteUserClientCredentialRequestArgs) => Promise; } diff --git a/src/packages/user/user/client-credential/repository/data-source/user-client-credentials.server.data-source.ts b/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts similarity index 55% rename from src/packages/user/user/client-credential/repository/data-source/user-client-credentials.server.data-source.ts rename to src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts index c140625b7a..f46aa92732 100644 --- a/src/packages/user/user/client-credential/repository/data-source/user-client-credentials.server.data-source.ts +++ b/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts @@ -1,9 +1,9 @@ import type { - UmbUserClientCredentialsDataSource, - UmbUserClientCredentialsDataSourceCreateArgs, - UmbUserClientCredentialsDataSourceDeleteArgs, - UmbUserClientCredentialsDataSourceReadArgs, -} from './types.js'; + UmbCreateUserClientCredentialRequestArgs, + UmbDeleteUserClientCredentialRequestArgs, + UmbUserClientCredentialRequestArgs, +} from '../types.js'; +import type { UmbUserClientCredentialDataSource } from './types.js'; import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; @@ -11,10 +11,10 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; /** * Server data source for user client credentials * @export - * @class UmbUserClientCredentialsServerDataSource - * @implements {UmbUserClientCredentialsDataSource} + * @class UmbUserClientCredentialServerDataSource + * @implements {UmbUserClientCredentialDataSource} */ -export class UmbUserClientCredentialsServerDataSource implements UmbUserClientCredentialsDataSource { +export class UmbUserClientCredentialServerDataSource implements UmbUserClientCredentialDataSource { #host: UmbControllerHost; constructor(host: UmbControllerHost) { @@ -23,11 +23,11 @@ export class UmbUserClientCredentialsServerDataSource implements UmbUserClientCr /** * Creates a new client credentials for a user - * @param {UmbUserClientCredentialsDataSourceCreateArgs} args - The user and client to create the credentials for + * @param {UmbCreateUserClientCredentialRequestArgs} args - The user and client to create the credentials for * @returns {*} - * @memberof UmbUserClientCredentialsServerDataSource + * @memberof UmbUserClientCredentialServerDataSource */ - create(args: UmbUserClientCredentialsDataSourceCreateArgs) { + create(args: UmbCreateUserClientCredentialRequestArgs) { return tryExecuteAndNotify( this.#host, UserService.postUserByIdClientCredentials({ @@ -42,11 +42,11 @@ export class UmbUserClientCredentialsServerDataSource implements UmbUserClientCr /** * Reads the client credentials for a user - * @param {UmbUserClientCredentialsDataSourceReadArgs} args - The user to read the credentials for + * @param {UmbUserClientCredentialRequestArgs} args - The user to read the credentials for * @returns {*} - * @memberof UmbUserClientCredentialsServerDataSource + * @memberof UmbUserClientCredentialServerDataSource */ - async read(args: UmbUserClientCredentialsDataSourceReadArgs) { + async read(args: UmbUserClientCredentialRequestArgs) { const { data, error } = await tryExecuteAndNotify( this.#host, UserService.getUserByIdClientCredentials({ @@ -67,11 +67,11 @@ export class UmbUserClientCredentialsServerDataSource implements UmbUserClientCr /** * Deletes the client credentials for a user - * @param {UmbUserClientCredentialsDataSourceDeleteArgs} args - The user and client unique to delete the credentials for + * @param {UmbDeleteUserClientCredentialRequestArgs} args - The user and client unique to delete the credentials for * @returns {*} - * @memberof UmbUserClientCredentialsServerDataSource + * @memberof UmbUserClientCredentialServerDataSource */ - delete(args: UmbUserClientCredentialsDataSourceDeleteArgs) { + delete(args: UmbDeleteUserClientCredentialRequestArgs) { return tryExecuteAndNotify( this.#host, UserService.deleteUserByIdClientCredentialsByClientId({ diff --git a/src/packages/user/user/client-credential/repository/index.ts b/src/packages/user/user/client-credential/repository/index.ts index abf2760126..ec915a3b12 100644 --- a/src/packages/user/user/client-credential/repository/index.ts +++ b/src/packages/user/user/client-credential/repository/index.ts @@ -1,2 +1,3 @@ -export * from './user-client-credentials.repository.js'; +export * from './user-client-credential.repository.js'; export * from './constants.js'; +export * from './types.js'; diff --git a/src/packages/user/user/client-credential/repository/manifests.ts b/src/packages/user/user/client-credential/repository/manifests.ts index 2c6b56a623..a77e1c8998 100644 --- a/src/packages/user/user/client-credential/repository/manifests.ts +++ b/src/packages/user/user/client-credential/repository/manifests.ts @@ -1,11 +1,11 @@ -import { UMB_USER_CLIENT_CREDENTIALS_REPOSITORY_ALIAS } from './constants.js'; +import { UMB_USER_CLIENT_CREDENTIAL_REPOSITORY_ALIAS } from './constants.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ { type: 'repository', - alias: UMB_USER_CLIENT_CREDENTIALS_REPOSITORY_ALIAS, + alias: UMB_USER_CLIENT_CREDENTIAL_REPOSITORY_ALIAS, name: 'User Client Credentials Repository', - api: () => import('./user-client-credentials.repository.js'), + api: () => import('./user-client-credential.repository.js'), }, ]; diff --git a/src/packages/user/user/client-credential/repository/types.ts b/src/packages/user/user/client-credential/repository/types.ts index a27c8121f7..900d6aadd5 100644 --- a/src/packages/user/user/client-credential/repository/types.ts +++ b/src/packages/user/user/client-credential/repository/types.ts @@ -1,12 +1,16 @@ -import type { - UmbUserClientCredentialsDataSourceCreateArgs, - UmbUserClientCredentialsDataSourceDeleteArgs, - UmbUserClientCredentialsDataSourceReadArgs, -} from './data-source/index.js'; +export interface UmbCreateUserClientCredentialRequestArgs { + user: { unique: string }; + client: { unique: string; secret: string }; +} + +export interface UmbUserClientCredentialRequestArgs { + user: { unique: string }; +} -export type UmbUserClientCredentialsRepositoryCreateArgs = UmbUserClientCredentialsDataSourceCreateArgs; -export type UmbUserClientCredentialsRepositoryReadArgs = UmbUserClientCredentialsDataSourceReadArgs; -export type UmbUserClientCredentialsRepositoryDeleteArgs = UmbUserClientCredentialsDataSourceDeleteArgs; +export interface UmbDeleteUserClientCredentialRequestArgs { + user: { unique: string }; + client: { unique: string }; +} export interface UmbUserClientCredentialModel { unique: string; diff --git a/src/packages/user/user/client-credential/repository/user-client-credential.repository.ts b/src/packages/user/user/client-credential/repository/user-client-credential.repository.ts new file mode 100644 index 0000000000..4d25eedafa --- /dev/null +++ b/src/packages/user/user/client-credential/repository/user-client-credential.repository.ts @@ -0,0 +1,61 @@ +import type { UmbUserClientCredentialDataSource } from './data-source/index.js'; +import { UmbUserClientCredentialServerDataSource } from './data-source/user-client-credential.server.data-source.js'; +import type { + UmbCreateUserClientCredentialRequestArgs, + UmbDeleteUserClientCredentialRequestArgs, + UmbUserClientCredentialRequestArgs, +} from './types.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +/** + * UmbUserClientCredentialRepository + * @export + * @class UmbUserClientCredentialRepository + * @extends {UmbRepositoryBase} + */ +export class UmbUserClientCredentialRepository extends UmbRepositoryBase { + #source: UmbUserClientCredentialDataSource; + + /** + * Creates an instance of UmbUserClientCredentialRepository. + * @param {UmbControllerHost} host - The controller host + * @memberof UmbUserClientCredentialRepository + */ + constructor(host: UmbControllerHost) { + super(host); + this.#source = new UmbUserClientCredentialServerDataSource(host); + } + + /** + * Creates a new client credentials for a user + * @param {UmbCreateUserClientCredentialRequestArgs} args - The user and client to create the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialRepository + */ + async requestCreate(args: UmbCreateUserClientCredentialRequestArgs) { + return this.#source.create(args); + } + + /** + * Reads the client credentials for a user + * @param {UmbUserClientCredentialRequestArgs} args - The user to read the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialRepository + */ + async requestClientCredentials(args: UmbUserClientCredentialRequestArgs) { + return this.#source.read(args); + } + + /** + * Deletes the client credentials for a user + * @param {UmbDeleteUserClientCredentialRequestArgs} args - The user and client unique to delete the credentials for + * @returns {*} + * @memberof UmbUserClientCredentialRepository + */ + async requestDelete(args: UmbDeleteUserClientCredentialRequestArgs) { + return this.#source.delete(args); + } +} + +export { UmbUserClientCredentialRepository as api }; diff --git a/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts b/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts deleted file mode 100644 index 338de3ab8f..0000000000 --- a/src/packages/user/user/client-credential/repository/user-client-credentials.repository.ts +++ /dev/null @@ -1,61 +0,0 @@ -import type { UmbUserClientCredentialsDataSource } from './data-source/index.js'; -import { UmbUserClientCredentialsServerDataSource } from './data-source/user-client-credentials.server.data-source.js'; -import type { - UmbUserClientCredentialsRepositoryCreateArgs, - UmbUserClientCredentialsRepositoryDeleteArgs, - UmbUserClientCredentialsRepositoryReadArgs, -} from './types.js'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; - -/** - * UmbUserClientCredentialsRepository - * @export - * @class UmbUserClientCredentialsRepository - * @extends {UmbRepositoryBase} - */ -export class UmbUserClientCredentialsRepository extends UmbRepositoryBase { - #source: UmbUserClientCredentialsDataSource; - - /** - * Creates an instance of UmbUserClientCredentialsRepository. - * @param {UmbControllerHost} host - The controller host - * @memberof UmbUserClientCredentialsRepository - */ - constructor(host: UmbControllerHost) { - super(host); - this.#source = new UmbUserClientCredentialsServerDataSource(host); - } - - /** - * Creates a new client credentials for a user - * @param {UmbUserClientCredentialsRepositoryCreateArgs} args - The user and client to create the credentials for - * @returns {*} - * @memberof UmbUserClientCredentialsRepository - */ - async create(args: UmbUserClientCredentialsRepositoryCreateArgs) { - return this.#source.create(args); - } - - /** - * Reads the client credentials for a user - * @param {UmbUserClientCredentialsRepositoryReadArgs} args - The user to read the credentials for - * @returns {*} - * @memberof UmbUserClientCredentialsRepository - */ - async read(args: UmbUserClientCredentialsRepositoryReadArgs) { - return this.#source.read(args); - } - - /** - * Deletes the client credentials for a user - * @param {UmbUserClientCredentialsRepositoryDeleteArgs} args - The user and client unique to delete the credentials for - * @returns {*} - * @memberof UmbUserClientCredentialsRepository - */ - async delete(args: UmbUserClientCredentialsRepositoryDeleteArgs) { - return this.#source.delete(args); - } -} - -export { UmbUserClientCredentialsRepository as api }; diff --git a/src/packages/user/user/manifests.ts b/src/packages/user/user/manifests.ts index a5eb9bfeea..3eae6c756b 100644 --- a/src/packages/user/user/manifests.ts +++ b/src/packages/user/user/manifests.ts @@ -1,24 +1,26 @@ +import { manifests as clientCredentialManifests } from './client-credential/manifests.js'; import { manifests as collectionManifests } from './collection/manifests.js'; import { manifests as conditionsManifests } from './conditions/manifests.js'; import { manifests as entityActionsManifests } from './entity-actions/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-actions/manifests.js'; import { manifests as inviteManifests } from './invite/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; +import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as sectionViewManifests } from './section-view/manifests.js'; -import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ +export const manifests: Array = [ + ...clientCredentialManifests, ...collectionManifests, ...conditionsManifests, ...entityActionsManifests, ...entityBulkActionManifests, ...inviteManifests, ...modalManifests, + ...propertyEditorManifests, ...repositoryManifests, ...sectionViewManifests, - ...propertyEditorManifests, ...workspaceManifests, ]; From 445169dc1ac282496db9bc302bafbe0204019aae Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 17:46:46 +0200 Subject: [PATCH 027/322] remove console log --- .../user/user/conditions/user-allow-action-base.condition.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/packages/user/user/conditions/user-allow-action-base.condition.ts b/src/packages/user/user/conditions/user-allow-action-base.condition.ts index fb5bf0f8d1..bdae21f4af 100644 --- a/src/packages/user/user/conditions/user-allow-action-base.condition.ts +++ b/src/packages/user/user/conditions/user-allow-action-base.condition.ts @@ -48,7 +48,6 @@ export abstract class UmbUserActionConditionBase super(host, args); this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (context) => { - console.log(context); this.observe( observeMultiple([context.unique, context.state, context.kind]), ([unique, state, kind]) => { From d902e2c8b7a342bae9b901d02cdc05515ca31709 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 2 Sep 2024 17:18:21 +0100 Subject: [PATCH 028/322] Remove the prepend conditions and rename append to addCondition and addCondtions As the order of conditions is not important, as all conditions set on an extensions must be true/valid --- .../registry/extension.registry.ts | 43 +++---------------- 1 file changed, 5 insertions(+), 38 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 5cd0dbcbe8..26b483b032 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -457,14 +457,14 @@ export class UmbExtensionRegistry< } /** - * Appends a new condition to an existing extension + * Add a new condition to an existing extension * Useful to add a condition for example the Save And Publish workspace action shipped by core * As overwriting the whole extension to simply add an extra condition is not ideal as it causes a lot of duplicated code * and could easily get out of sync from the CMS core implementation if a 3rd party dev was to try and overwrite it * @param alias {string} - The alias of the extension to append the condition to * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. */ - async appendCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { + async addCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { try { // Wait for the extension to be registered (as it could be registered late) const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; @@ -492,46 +492,13 @@ export class UmbExtensionRegistry< } /** - * Appends a collection of conditions to an exsiting extension + * Adds a collection of conditions to an exsiting extension * @param alias {string} - The alias of the extension to append the condition to * @param newConditions {Array} - A collection of conditions to append to an extension. */ - async appendConditions(alias: string, newConditions: Array): Promise { + async addConditions(alias: string, newConditions: Array): Promise { for (const condition of newConditions) { - await this.appendCondition(alias, condition); - } - } - - /** - * Prepends a new condition to an existing extension - * @param alias {string} - The alias of the extension to prepend the condition to - * @param newCondition {UmbConditionConfigBase} - The condition to prepend to the extension. - */ - async prependCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { - try { - // Wait for the extension to be registered (as it could be registered late) - const extensionToUpdate = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - - // Append the condition to the extensions conditions array - if (extensionToUpdate.conditions) { - extensionToUpdate.conditions.unshift(newCondition); - } else { - extensionToUpdate.conditions = [newCondition]; - } - } catch (error) { - // TODO: [WB] Will this ever catch an error? - console.error(`Extension with alias ${alias} was never found and threw ${error}`); - } - } - - /** - * Prepends a collection of conditions to an existing extension - * @param alias {string} - The alias of the extension to prepend the conditions to - * @param newConditions {Array} - A collection of conditions to prepend to an extension. - */ - async prependConditions(alias: string, newConditions: Array): Promise { - for (const condition of newConditions) { - await this.prependCondition(alias, condition); + await this.addCondition(alias, condition); } } } From 17b9ee517da2ba5ab1ec3f6f6951c814fd8d470e Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 2 Sep 2024 20:03:34 +0100 Subject: [PATCH 029/322] Update tests Still need to uncomment & reinvestigate the late loading test --- .../registry/extension.registry.test.ts | 191 +++++------------- 1 file changed, 47 insertions(+), 144 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index b38fdac8b2..feb27191c8 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -461,7 +461,7 @@ describe('UmbExtensionRegistry with exclusions', () => { }); }); -describe('Append Conditions', () => { +describe('Add Conditions', () => { let extensionRegistry: UmbExtensionRegistry; let manifests: Array; @@ -518,7 +518,7 @@ describe('Append Conditions', () => { const conditionToAdd: UmbConditionConfigBase = { alias: 'Umb.Test.Condition.Valid', }; - await extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); + await extensionRegistry.addCondition('Umb.Test.Section.1', conditionToAdd); // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; @@ -535,7 +535,7 @@ describe('Append Conditions', () => { match: 'Umb.Workspace.Document', }; - await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); + await extensionRegistry.addCondition('Umb.Test.Section.2', workspaceCondition); const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); @@ -556,7 +556,7 @@ describe('Append Conditions', () => { } as WorkspaceAliasConditionConfig, ]; - await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.addConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(extUpdated.conditions?.length).to.equal(3); @@ -564,145 +564,48 @@ describe('Append Conditions', () => { expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); }); -}); - -describe('Prepend Conditions', () => { - let extensionRegistry: UmbExtensionRegistry; - let manifests: Array; - - beforeEach(() => { - extensionRegistry = new UmbExtensionRegistry(); - manifests = [ - { - type: 'section', - name: 'test-section-1', - alias: 'Umb.Test.Section.1', - weight: 1, - conditions: [ - { - alias: 'Umb.Test.Condition.Valid', - }, - ], - }, - { - type: 'section', - name: 'test-section-2', - alias: 'Umb.Test.Section.2', - weight: 200, - conditions: [ - { - alias: 'Umb.Test.Condition.Valid', - }, - ], - }, - ]; - - manifests.forEach((manifest) => extensionRegistry.register(manifest)); - }); - - it('should have the extensions registered', () => { - expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.false; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; - }); - - it('allows an extension condition to be prepended', async () => { - const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(1); - expect(ext.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); - - extensionRegistry.register({ - type: 'condition', - name: 'test-condition-invalid', - alias: 'Umb.Test.Condition.Invalid', - }); - - // Prepend the new condition to the extension - const conditionToPrepend: UmbConditionConfigBase = { - alias: 'Umb.Test.Condition.Invalid', - }; - - await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); - - // Check new condition is registered - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; - - // Verify the extension now has two conditions and the new condition is prepended - const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(updatedExt.conditions?.length).to.equal(2); - expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); // Our new one prepended - expect(updatedExt.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); - }); - - it('allows an extension to update with multiple prepended conditions', async () => { - const ext = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(1); - expect(ext.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); - - const conditions: Array = [ - { - alias: 'Umb.Test.Condition.Invalid', - }, - { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document', - } as WorkspaceAliasConditionConfig, - ]; - - await extensionRegistry.prependConditions('Umb.Test.Section.2', conditions); - - const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; - expect(extUpdated.conditions?.length).to.equal(3); - - // The thing to note here our two new conditions is that are prepended in reverse order they are passed in - // as each one is prepended to the front of the array - expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); - expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); - }); - - it('allows conditions to be prepended when an extension is loaded later on', async () => { - const conditions: Array = [ - { - alias: 'Umb.Test.Condition.Invalid', - }, - { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document', - } as WorkspaceAliasConditionConfig, - ]; - console.log('About to go KABOOM..'); - - // Prepend the conditions - // [WB] HELP: Why is this fine when using in in an entrypoint - // /src/packages/property-editors/entry-point.ts - // But this TEST implodes if it can't find the extension that is not yet registered - await extensionRegistry.prependConditions('Late.Extension.To.Be.Loaded', conditions); - - // Make sure the extension is not registered YET - expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; - - // Register the extension LATE/after the conditions have been added - extensionRegistry.register({ - type: 'section', - name: 'Late Section Extension with one condition', - alias: 'Late.Extension.To.Be.Loaded', - weight: 200, - conditions: [ - { - alias: 'Umb.Test.Condition.Valid', - }, - ], - }); - - expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; - - const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; - expect(extUpdated.conditions?.length).to.equal(3); - expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); - expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); - }); + // it('allows conditions to be prepended when an extension is loaded later on', async () => { + // const conditions: Array = [ + // { + // alias: 'Umb.Test.Condition.Invalid', + // }, + // { + // alias: 'Umb.Condition.WorkspaceAlias', + // match: 'Umb.Workspace.Document', + // } as WorkspaceAliasConditionConfig, + // ]; + + // console.log('About to go KABOOM..'); + + // // Prepend the conditions + // // [WB] HELP: Why is this fine when using in in an entrypoint + // // /src/packages/property-editors/entry-point.ts + // // But this TEST implodes if it can't find the extension that is not yet registered + // await extensionRegistry.addConditions('Late.Extension.To.Be.Loaded', conditions); + + // // Make sure the extension is not registered YET + // expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // // Register the extension LATE/after the conditions have been added + // extensionRegistry.register({ + // type: 'section', + // name: 'Late Section Extension with one condition', + // alias: 'Late.Extension.To.Be.Loaded', + // weight: 200, + // conditions: [ + // { + // alias: 'Umb.Test.Condition.Valid', + // }, + // ], + // }); + + // expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + // const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; + // expect(extUpdated.conditions?.length).to.equal(3); + // expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + // expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); + // expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); + // }); }); From 89f8cac18d6cf2bc88683052aa559a765a606457 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 21:48:26 +0200 Subject: [PATCH 030/322] return newly created credential id --- .../user-client-credential.server.data-source.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts b/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts index f46aa92732..af80fd15b6 100644 --- a/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts +++ b/src/packages/user/user/client-credential/repository/data-source/user-client-credential.server.data-source.ts @@ -27,8 +27,8 @@ export class UmbUserClientCredentialServerDataSource implements UmbUserClientCre * @returns {*} * @memberof UmbUserClientCredentialServerDataSource */ - create(args: UmbCreateUserClientCredentialRequestArgs) { - return tryExecuteAndNotify( + async create(args: UmbCreateUserClientCredentialRequestArgs) { + const { error } = await tryExecuteAndNotify( this.#host, UserService.postUserByIdClientCredentials({ id: args.user.unique, @@ -38,6 +38,12 @@ export class UmbUserClientCredentialServerDataSource implements UmbUserClientCre }, }), ); + + if (!error) { + return { data: { unique: args.client.unique } }; + } + + return { error }; } /** From c35990bd3b85f60410cc99821fa1946cc8031864 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 21:50:47 +0200 Subject: [PATCH 031/322] add create modal --- .../client-credential/create/manifests.ts | 5 + .../create/modal/constants.ts | 1 + ...te-user-client-credential-modal.element.ts | 104 ++++++++++++++++++ ...eate-user-client-credential-modal.token.ts | 25 +++++ .../create/modal/manifests.ts | 11 ++ .../user/user/client-credential/manifests.ts | 6 +- ...er-workspace-client-credentials.element.ts | 90 +++++++++++++++ .../user-workspace-editor.element.ts | 2 + 8 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 src/packages/user/user/client-credential/create/manifests.ts create mode 100644 src/packages/user/user/client-credential/create/modal/constants.ts create mode 100644 src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts create mode 100644 src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts create mode 100644 src/packages/user/user/client-credential/create/modal/manifests.ts create mode 100644 src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts diff --git a/src/packages/user/user/client-credential/create/manifests.ts b/src/packages/user/user/client-credential/create/manifests.ts new file mode 100644 index 0000000000..420b53915c --- /dev/null +++ b/src/packages/user/user/client-credential/create/manifests.ts @@ -0,0 +1,5 @@ +import { manifests as modalManifests } from './modal/manifests.js'; + +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...modalManifests]; diff --git a/src/packages/user/user/client-credential/create/modal/constants.ts b/src/packages/user/user/client-credential/create/modal/constants.ts new file mode 100644 index 0000000000..955ffa9cd6 --- /dev/null +++ b/src/packages/user/user/client-credential/create/modal/constants.ts @@ -0,0 +1 @@ +export const UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS = 'Umb.Modal.User.ClientCredential.Create'; diff --git a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts new file mode 100644 index 0000000000..dcd8c703f9 --- /dev/null +++ b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts @@ -0,0 +1,104 @@ +import type { UmbCreateUserClientCredentialRequestArgs } from '../../repository/index.js'; +import { UmbUserClientCredentialRepository } from '../../repository/index.js'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { css, html, customElement, query } from '@umbraco-cms/backoffice/external/lit'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; + +const elementName = 'umb-create-user-client-credential-modal'; +@customElement(elementName) +export class UmbCreateUserModalElement extends UmbModalBaseElement { + @query('#CreateUserClientCredentialForm') + _form?: HTMLFormElement; + + #userClientCredentialRepository = new UmbUserClientCredentialRepository(this); + + #uniquePrefix = 'umbraco-back-office-'; + + async #onSubmit(e: SubmitEvent) { + e.preventDefault(); + + const form = e.target as HTMLFormElement; + if (!form) return; + + const isValid = form.checkValidity(); + if (!isValid) return; + + const formData = new FormData(form); + + const unique = formData.get('unique') as string; + const secret = formData.get('secret') as string; + + const payload: UmbCreateUserClientCredentialRequestArgs = { + user: { unique: this.data.user.unique }, + client: { unique, secret }, + }; + + // TODO: figure out when to use email or username + const { data } = await this.#userClientCredentialRepository.requestCreate(payload); + debugger; + } + + override render() { + return html` +

Lorem

+ + ${this.#renderForm()} + + +
`; + } + + #renderForm() { + return html` + + + Id + +
${this.#uniquePrefix}
+
+
+ + Secret + + + +
`; + } + + static override styles = [ + UmbTextStyles, + css` + uui-input, + uui-input-password { + width: 580px; + } + + .prepend { + user-select: none; + height: 100%; + padding: 0 var(--uui-size-3); + border-right: 1px solid var(--uui-input-border-color, var(--uui-color-border)); + background: #f3f3f3; + color: grey; + display: flex; + justify-content: center; + align-items: center; + white-space: nowrap; + } + `, + ]; +} + +export { UmbCreateUserModalElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbCreateUserModalElement; + } +} diff --git a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts new file mode 100644 index 0000000000..be33567081 --- /dev/null +++ b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts @@ -0,0 +1,25 @@ +import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS } from './constants.js'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbCreateUserClientCredentialModalData { + user: { + unique: string; + }; +} + +export interface UmbBlockCatalogueModalValue { + client: { + unique: string; + secret: string; + }; +} + +export const UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL = new UmbModalToken( + UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS, + { + modal: { + type: 'dialog', + size: 'small', + }, + }, +); diff --git a/src/packages/user/user/client-credential/create/modal/manifests.ts b/src/packages/user/user/client-credential/create/modal/manifests.ts new file mode 100644 index 0000000000..662ecec620 --- /dev/null +++ b/src/packages/user/user/client-credential/create/modal/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS } from './constants.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'modal', + alias: UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS, + name: 'Create User Client Credential Modal', + js: () => import('./create-user-client-credential-modal.element.js'), + }, +]; diff --git a/src/packages/user/user/client-credential/manifests.ts b/src/packages/user/user/client-credential/manifests.ts index 0a214139c1..eba4cdb996 100644 --- a/src/packages/user/user/client-credential/manifests.ts +++ b/src/packages/user/user/client-credential/manifests.ts @@ -1 +1,5 @@ -export * from './repository/manifests.js'; +import { manifests as createManifests } from './create/manifests.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...createManifests, ...repositoryManifests]; diff --git a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts new file mode 100644 index 0000000000..6733014ea1 --- /dev/null +++ b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -0,0 +1,90 @@ +import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; +import type { UmbUserClientCredentialModel } from '../../../client-credential/index.js'; +import { UmbUserClientCredentialRepository } from '../../../client-credential/index.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 { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; + +const elementName = 'umb-user-workspace-client-credentials'; +@customElement(elementName) +export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { + @state() + private _userUnique?: string; + + @state() + private _clientCredentials: UmbUserClientCredentialModel[] = []; + + #userWorkspaceContext?: typeof UMB_USER_WORKSPACE_CONTEXT.TYPE; + #modalManagerContext? = UMB_MODAL_MANAGER_CONTEXT.TYPE; + #userClientCredentialRepository = new UmbUserClientCredentialRepository(this); + + constructor() { + super(); + + this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (instance) => { + this.#userWorkspaceContext = instance; + this.observe( + this.#userWorkspaceContext.unique, + async (unique) => this.#onUserUniqueChange(unique), + 'umbUserUniqueObserver', + ); + }); + + this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => { + this.#modalManagerContext = instance; + }); + } + + async #onUserUniqueChange(unique: string | undefined) { + if (unique && this._userUnique !== unique) { + const { data } = await this.#userClientCredentialRepository.requestClientCredentials({ user: { unique } }); + if (data) { + console.log(data); + } + } + + this._userUnique = unique; + } + + #onAdd() { + if (!this.#modalManagerContext) throw new Error('Modal Manager Context not available'); + + const modalContext = this.#modalManagerContext.open(this, UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL, { + data: { + user: { + unique: this._userUnique, + }, + }, + }); + + modalContext.onSubmit().then((result) => { + console.log('submit', result); + }); + + console.log('add'); + } + + override render() { + return html` +
Client Credentials
+ +
`; + } + + static override styles = [ + UmbTextStyles, + css` + uui-input { + width: 100%; + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserWorkspaceClientCredentialsElement; + } +} diff --git a/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/packages/user/user/workspace/user-workspace-editor.element.ts index 2c9d30f10f..1305454d14 100644 --- a/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -13,6 +13,7 @@ import './components/user-workspace-profile-settings/user-workspace-profile-sett 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'; +import './components/user-workspace-client-credentials/user-workspace-client-credentials.element.js'; @customElement('umb-user-workspace-editor') export class UmbUserWorkspaceEditorElement extends UmbLitElement { @@ -73,6 +74,7 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { return html` + `; From 2abaf21736b46047f4174213867770358a1b0a78 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 2 Sep 2024 21:51:44 +0200 Subject: [PATCH 032/322] clean up --- .../user/modals/create/create-user-modal.element.ts | 12 +++++------- .../create/create-user-success-modal.element.ts | 2 ++ .../detail/user-detail.server.data-source.ts | 4 ++-- src/packages/user/user/repository/item/types.ts | 2 ++ .../repository/item/user-item.server.data-source.ts | 1 + src/packages/user/user/types.ts | 4 ++-- src/packages/user/user/utils/index.ts | 4 ++-- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/packages/user/user/modals/create/create-user-modal.element.ts b/src/packages/user/user/modals/create/create-user-modal.element.ts index 85b6facca1..d3dc9ed3cc 100644 --- a/src/packages/user/user/modals/create/create-user-modal.element.ts +++ b/src/packages/user/user/modals/create/create-user-modal.element.ts @@ -1,5 +1,5 @@ import { UmbUserDetailRepository } from '../../repository/index.js'; -import { UmbUserModelKind, UmbUserModelKindType } from '../../utils/index.js'; +import { UmbUserKind, UmbUserKindType } from '../../utils/index.js'; import { UMB_CREATE_USER_SUCCESS_MODAL } from './create-user-success-modal.token.js'; import type { UmbUserGroupInputElement } from '@umbraco-cms/backoffice/user-group'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -25,7 +25,7 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { const formData = new FormData(form); - const kind = formData.get('kind') as UmbUserModelKindType; + const kind = formData.get('kind') as UmbUserKindType; const name = formData.get('name') as string; const email = formData.get('email') as string; @@ -99,12 +99,10 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement {
Kind - + - ${UmbUserModelKind.DEFAULT} - ${UmbUserModelKind.API} + ${UmbUserKind.DEFAULT} + ${UmbUserKind.API} diff --git a/src/packages/user/user/modals/create/create-user-success-modal.element.ts b/src/packages/user/user/modals/create/create-user-success-modal.element.ts index 8185df073f..03a6872298 100644 --- a/src/packages/user/user/modals/create/create-user-success-modal.element.ts +++ b/src/packages/user/user/modals/create/create-user-success-modal.element.ts @@ -36,6 +36,8 @@ export class UmbCreateUserSuccessModalElement extends UmbModalBaseElement< const unique = this.data?.user.unique; if (!unique) throw new Error('No user unique is provided'); + debugger; + const [userItemResponse, newPasswordResponse] = await Promise.all([ this.#userItemRepository.requestItems([unique]), this.#userNewPasswordRepository.requestNewPassword(unique), diff --git a/src/packages/user/user/repository/detail/user-detail.server.data-source.ts b/src/packages/user/user/repository/detail/user-detail.server.data-source.ts index 0d89ee2a79..88a9c88a09 100644 --- a/src/packages/user/user/repository/detail/user-detail.server.data-source.ts +++ b/src/packages/user/user/repository/detail/user-detail.server.data-source.ts @@ -10,7 +10,7 @@ import type { import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; -import { UmbUserModelKind } from '../../utils/index.js'; +import { UmbUserKind } from '../../utils/index.js'; /** * A data source for the User that fetches data from the server @@ -46,7 +46,7 @@ export class UmbUserServerDataSource implements UmbDetailDataSource; entityType: UmbUserEntityType; + kind: UmbUserKindType; name: string; unique: string; } diff --git a/src/packages/user/user/repository/item/user-item.server.data-source.ts b/src/packages/user/user/repository/item/user-item.server.data-source.ts index 4856549327..d435990d00 100644 --- a/src/packages/user/user/repository/item/user-item.server.data-source.ts +++ b/src/packages/user/user/repository/item/user-item.server.data-source.ts @@ -33,5 +33,6 @@ const mapper = (item: UserItemResponseModel): UmbUserItemModel => { entityType: UMB_USER_ENTITY_TYPE, name: item.name, unique: item.id, + kind: item.kind, }; }; diff --git a/src/packages/user/user/types.ts b/src/packages/user/user/types.ts index b0cbe18174..4c3b9f9935 100644 --- a/src/packages/user/user/types.ts +++ b/src/packages/user/user/types.ts @@ -5,7 +5,7 @@ import { UserStateModel, type UserTwoFactorProviderModel, } from '@umbraco-cms/backoffice/external/backend-api'; -import { UmbUserModelKindType } from './utils/index.js'; +import { UmbUserKindType } from './utils/index.js'; export type UmbUserStateEnum = UserStateModel; export const UmbUserStateEnum = UserStateModel; @@ -27,7 +27,7 @@ export interface UmbUserDetailModel extends UmbUserStartNodesModel { updateDate: string | null; userGroupUniques: Array; userName: string; - kind: UmbUserModelKindType; + kind: UmbUserKindType; } export interface UmbUserStartNodesModel { diff --git a/src/packages/user/user/utils/index.ts b/src/packages/user/user/utils/index.ts index 6189fbcb68..4115ca2bbc 100644 --- a/src/packages/user/user/utils/index.ts +++ b/src/packages/user/user/utils/index.ts @@ -1,8 +1,8 @@ export * from './is-user.function.js'; -export type UmbUserModelKindType = 'Default' | 'Api'; +export type UmbUserKindType = 'Default' | 'Api'; -export const UmbUserModelKind = Object.freeze({ +export const UmbUserKind = Object.freeze({ DEFAULT: 'Default', API: 'Api', }); From fe69a01689187c38380251782ff6df0a061b8a0f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 09:20:56 +0200 Subject: [PATCH 033/322] map kind --- .../collection/repository/user-collection.server.data-source.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/packages/user/user/collection/repository/user-collection.server.data-source.ts b/src/packages/user/user/collection/repository/user-collection.server.data-source.ts index 57af3559cc..de1a3a767f 100644 --- a/src/packages/user/user/collection/repository/user-collection.server.data-source.ts +++ b/src/packages/user/user/collection/repository/user-collection.server.data-source.ts @@ -86,6 +86,7 @@ export class UmbUserCollectionServerDataSource implements UmbCollectionDataSourc lastLockoutDate: item.lastLockoutDate || null, lastPasswordChangeDate: item.lastPasswordChangeDate || null, isAdmin: item.isAdmin, + kind: item.kind, }; return userDetail; From d9c71b2ee86989cbea5f692bf9339141040ffa7f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 09:21:30 +0200 Subject: [PATCH 034/322] move client credentials to the sidebar + stack the elements --- .../user-workspace-avatar.element.ts | 1 - ...er-workspace-client-credentials.element.ts | 6 +++++- .../user-workspace-info.element.ts | 8 ++++---- .../user-workspace-editor.element.ts | 19 ++++++++++--------- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts b/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts index a7ceaacf4c..307900260b 100644 --- a/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts @@ -143,7 +143,6 @@ export class UmbUserAvatarElement extends UmbLitElement { css` :host { display: block; - margin-bottom: var(--uui-size-space-4); } #Avatar { diff --git a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index 6733014ea1..c5dd062e8b 100644 --- a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -1,11 +1,11 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; import type { UmbUserClientCredentialModel } from '../../../client-credential/index.js'; import { UmbUserClientCredentialRepository } from '../../../client-credential/index.js'; +import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.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 { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; -import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; const elementName = 'umb-user-workspace-client-credentials'; @customElement(elementName) @@ -76,6 +76,10 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { static override styles = [ UmbTextStyles, css` + :host { + display: block; + } + uui-input { width: 100%; } diff --git a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts index 471781d27e..27c46e106a 100644 --- a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts @@ -104,12 +104,12 @@ export class UmbUserWorkspaceInfoElement extends UmbLitElement { static override styles = [ UmbTextStyles, css` - uui-tag { - width: fit-content; + :host { + display: block; } - #user-info { - margin-bottom: var(--uui-size-space-4); + uui-tag { + width: fit-content; } #state { diff --git a/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/packages/user/user/workspace/user-workspace-editor.element.ts index 1305454d14..54458b0d19 100644 --- a/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -74,7 +74,6 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { return html` - `; @@ -84,14 +83,16 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { if (!this._user) return nothing; return html` - - - - - - + + + + + + + + `; } From 85f6e3fb8320d3dfa59e25dbdac446764850a9eb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 09:21:35 +0200 Subject: [PATCH 035/322] Update user-allow-change-password-action.condition.ts --- .../user-allow-change-password-action.condition.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts b/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts index ed78c34e78..d82ad989ae 100644 --- a/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts +++ b/src/packages/user/user/conditions/allow-change-password/user-allow-change-password-action.condition.ts @@ -1,10 +1,10 @@ -import { UmbUserModelKind } from '../../utils/index.js'; +import { UmbUserKind } from '../../utils/index.js'; import { UmbUserActionConditionBase } from '../user-allow-action-base.condition.js'; export class UmbUserAllowChangePasswordActionCondition extends UmbUserActionConditionBase { async _onUserDataChange() { // don't allow the current user to delete themselves - if (this.userKind === UmbUserModelKind.DEFAULT) { + if (this.userKind === UmbUserKind.DEFAULT) { this.permitted = true; } else { this.permitted = false; From 5104b1c9c1b5719ddc58961402bd3158463c1e53 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 09:21:53 +0200 Subject: [PATCH 036/322] return data from create --- ...eate-user-client-credential-modal.element.ts | 17 +++++++++++++++-- ...create-user-client-credential-modal.token.ts | 2 +- .../repository/data-source/types.ts | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts index dcd8c703f9..6a8c9ab5f6 100644 --- a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts +++ b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts @@ -1,12 +1,19 @@ import type { UmbCreateUserClientCredentialRequestArgs } from '../../repository/index.js'; import { UmbUserClientCredentialRepository } from '../../repository/index.js'; +import type { + UmbCreateUserClientCredentialModalData, + UmbCreateUserClientCredentialModalValue, +} from './create-user-client-credential-modal.token.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, query } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; const elementName = 'umb-create-user-client-credential-modal'; @customElement(elementName) -export class UmbCreateUserModalElement extends UmbModalBaseElement { +export class UmbCreateUserModalElement extends UmbModalBaseElement< + UmbCreateUserClientCredentialModalData, + UmbCreateUserClientCredentialModalValue +> { @query('#CreateUserClientCredentialForm') _form?: HTMLFormElement; @@ -17,6 +24,8 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { async #onSubmit(e: SubmitEvent) { e.preventDefault(); + if (this.data?.user?.unique === undefined) throw new Error('User unique is required'); + const form = e.target as HTMLFormElement; if (!form) return; @@ -35,7 +44,11 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { // TODO: figure out when to use email or username const { data } = await this.#userClientCredentialRepository.requestCreate(payload); - debugger; + + if (data) { + this.updateValue({ client: { unique: data.unique, secret } }); + this._submitModal(); + } } override render() { diff --git a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts index be33567081..be0a6e9c6e 100644 --- a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts +++ b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts @@ -7,7 +7,7 @@ export interface UmbCreateUserClientCredentialModalData { }; } -export interface UmbBlockCatalogueModalValue { +export interface UmbCreateUserClientCredentialModalValue { client: { unique: string; secret: string; diff --git a/src/packages/user/user/client-credential/repository/data-source/types.ts b/src/packages/user/user/client-credential/repository/data-source/types.ts index 0bbb27574a..6b3356f8f5 100644 --- a/src/packages/user/user/client-credential/repository/data-source/types.ts +++ b/src/packages/user/user/client-credential/repository/data-source/types.ts @@ -7,7 +7,7 @@ import type { import type { UmbDataSourceErrorResponse, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; export interface UmbUserClientCredentialDataSource { - create(args: UmbCreateUserClientCredentialRequestArgs): Promise; + create(args: UmbCreateUserClientCredentialRequestArgs): Promise>; read(args: UmbUserClientCredentialRequestArgs): Promise>>; delete: (args: UmbDeleteUserClientCredentialRequestArgs) => Promise; } From 85bce3c0392bbfa659f79b506fab1d24c1f6f1e9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 09:25:28 +0200 Subject: [PATCH 037/322] style add button --- .../user-workspace-client-credentials.element.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index c5dd062e8b..4259feea7c 100644 --- a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -69,7 +69,11 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { override render() { return html`
Client Credentials
- +
`; } @@ -83,6 +87,10 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { uui-input { width: 100%; } + + #add-button { + width: 100%; + } `, ]; } From c2c4ec4f6b9871b5c617bb6f6380a1039c392ff3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 09:56:46 +0200 Subject: [PATCH 038/322] wire up delete --- ...er-workspace-client-credentials.element.ts | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index 4259feea7c..c2a6aba25c 100644 --- a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -1,11 +1,14 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserClientCredentialModel } from '../../../client-credential/index.js'; +import type { + UmbDeleteUserClientCredentialRequestArgs, + UmbUserClientCredentialModel, +} from '../../../client-credential/index.js'; import { UmbUserClientCredentialRepository } from '../../../client-credential/index.js'; import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.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 { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT, umbConfirmModal } from '@umbraco-cms/backoffice/modal'; const elementName = 'umb-user-workspace-client-credentials'; @customElement(elementName) @@ -41,15 +44,17 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { if (unique && this._userUnique !== unique) { const { data } = await this.#userClientCredentialRepository.requestClientCredentials({ user: { unique } }); if (data) { - console.log(data); + this._clientCredentials = data; } } this._userUnique = unique; } - #onAdd() { + #onAdd(event: Event) { + event.stopPropagation(); if (!this.#modalManagerContext) throw new Error('Modal Manager Context not available'); + if (!this._userUnique) throw new Error('User unique not available'); const modalContext = this.#modalManagerContext.open(this, UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL, { data: { @@ -62,13 +67,36 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { modalContext.onSubmit().then((result) => { console.log('submit', result); }); + } + + async #onDelete(event: Event, client: UmbUserClientCredentialModel) { + event.stopPropagation(); + if (!this._userUnique) throw new Error('User unique not available'); + + await umbConfirmModal(this, { + headline: `Delete ${client.unique}`, + content: `Are you sure you want to delete ${client.unique}?`, + confirmLabel: 'Delete', + color: 'danger', + }); + + const payload: UmbDeleteUserClientCredentialRequestArgs = { + user: { unique: this._userUnique }, + client: { unique: client.unique }, + }; - console.log('add'); + this.#userClientCredentialRepository.requestDelete(payload); } override render() { return html`
Client Credentials
+ ${this._clientCredentials.map( + (client) => + html`
+ ${client.unique} this.#onDelete(event, client)}>Delete +
`, + )} Date: Tue, 3 Sep 2024 10:39:11 +0200 Subject: [PATCH 039/322] only render client credentials for api kinds --- ...er-workspace-client-credentials.element.ts | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index c2a6aba25c..5177dbf7d0 100644 --- a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -5,7 +5,8 @@ import type { } from '../../../client-credential/index.js'; import { UmbUserClientCredentialRepository } from '../../../client-credential/index.js'; import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; -import { html, customElement, state, css } from '@umbraco-cms/backoffice/external/lit'; +import { UmbUserKind } from '../../../utils/index.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 { UMB_MODAL_MANAGER_CONTEXT, umbConfirmModal } from '@umbraco-cms/backoffice/modal'; @@ -16,6 +17,9 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { @state() private _userUnique?: string; + @state() + private _userKind?: string; + @state() private _clientCredentials: UmbUserClientCredentialModel[] = []; @@ -28,6 +32,9 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (instance) => { this.#userWorkspaceContext = instance; + + this.observe(this.#userWorkspaceContext.kind, (kind) => (this._userKind = kind), 'umbUserKindObserver'); + this.observe( this.#userWorkspaceContext.unique, async (unique) => this.#onUserUniqueChange(unique), @@ -89,14 +96,11 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { } override render() { + if (this._userKind !== UmbUserKind.API) return nothing; + return html`
Client Credentials
- ${this._clientCredentials.map( - (client) => - html`
- ${client.unique} this.#onDelete(event, client)}>Delete -
`, - )} + ${this._clientCredentials.map((client) => html` ${this.#renderItem(client)} `)} `; } + #renderItem(client: UmbUserClientCredentialModel) { + return html` + + + this.#onDelete(event, client)} + label="Delete ${client.unique}" + compact + > + + `; + } + static override styles = [ UmbTextStyles, css` From 68195199bdf3d793c89705663079f658877a32a3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 10:53:25 +0200 Subject: [PATCH 040/322] set modal types --- .../create-user-client-credential-modal.token.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts index be0a6e9c6e..a0179a2ea7 100644 --- a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts +++ b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.token.ts @@ -14,12 +14,12 @@ export interface UmbCreateUserClientCredentialModalValue { }; } -export const UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL = new UmbModalToken( - UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS, - { - modal: { - type: 'dialog', - size: 'small', - }, +export const UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL = new UmbModalToken< + UmbCreateUserClientCredentialModalData, + UmbCreateUserClientCredentialModalValue +>(UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL_ALIAS, { + modal: { + type: 'dialog', + size: 'small', }, -); +}); From 10841e1d1aa14f8d531fd288940a45ddec79faf7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 10:53:44 +0200 Subject: [PATCH 041/322] reload when creating and deleting --- ...er-workspace-client-credentials.element.ts | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index 5177dbf7d0..7d3fa116f9 100644 --- a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -47,15 +47,26 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { }); } - async #onUserUniqueChange(unique: string | undefined) { + #onUserUniqueChange(unique: string | undefined) { if (unique && this._userUnique !== unique) { - const { data } = await this.#userClientCredentialRepository.requestClientCredentials({ user: { unique } }); - if (data) { - this._clientCredentials = data; - } + this._userUnique = unique; + this.#loadClientCredentials(); + } + + if (!unique) { + this._userUnique = undefined; + this._clientCredentials = []; } + } + + async #loadClientCredentials() { + if (!this._userUnique) throw new Error('User unique not available'); - this._userUnique = unique; + const { data } = await this.#userClientCredentialRepository.requestClientCredentials({ + user: { unique: this._userUnique }, + }); + + this._clientCredentials = data ?? []; } #onAdd(event: Event) { @@ -71,9 +82,7 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { }, }); - modalContext.onSubmit().then((result) => { - console.log('submit', result); - }); + modalContext.onSubmit().then(() => this.#loadClientCredentials()); } async #onDelete(event: Event, client: UmbUserClientCredentialModel) { @@ -92,7 +101,11 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { client: { unique: client.unique }, }; - this.#userClientCredentialRepository.requestDelete(payload); + const { error } = await this.#userClientCredentialRepository.requestDelete(payload); + + if (!error) { + this.#loadClientCredentials(); + } } override render() { From 5f1dbf019fc05125fe3efce5c793e72d74d582c3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 11:00:03 +0200 Subject: [PATCH 042/322] add kind to info --- src/assets/lang/da-dk.ts | 1 + src/assets/lang/en-us.ts | 1 + .../user-workspace-info/user-workspace-info.element.ts | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/src/assets/lang/da-dk.ts b/src/assets/lang/da-dk.ts index 29ba011438..6546006c07 100644 --- a/src/assets/lang/da-dk.ts +++ b/src/assets/lang/da-dk.ts @@ -1857,6 +1857,7 @@ export default { inviteAnotherUser: 'Invitér anden bruger', inviteUserHelp: 'Invitér nye brugere til at give dem adgang til Umbraco. En invitation vil blive sendt\n via e-mail til brugeren med oplysninger om, hvordan man logger ind i Umbraco.\n ', + kind: 'Slags', language: 'Sprog', languageHelp: 'Indstil det sprog, du vil se i menuer og dialoger', lastLockoutDate: 'Senest låst ude', diff --git a/src/assets/lang/en-us.ts b/src/assets/lang/en-us.ts index a212371ec1..4905ce13d9 100644 --- a/src/assets/lang/en-us.ts +++ b/src/assets/lang/en-us.ts @@ -1849,6 +1849,7 @@ export default { ? 'The email address is used for notifications, password recovery, and as the username for logging in' : 'The email address is used for notifications and password recovery'; }, + kind: 'Kind', newPassword: 'New password', newPasswordFormatLengthTip: 'Minimum %0% character(s) to go!', newPasswordFormatNonAlphaTip: 'There should be at least %0% special character(s) in there.', diff --git a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts index 27c46e106a..da83d0569b 100644 --- a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts @@ -42,6 +42,10 @@ export class UmbUserWorkspaceInfoElement extends UmbLitElement { } this._userInfo = [ + { + labelKey: 'user_kind', + value: user.kind, + }, { labelKey: 'user_lastLogin', value: user.lastLoginDate From ae55b57a6a5c6432b1c4f8846440b80b0162f1de Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 11:05:53 +0200 Subject: [PATCH 043/322] use stack component --- .../user-workspace-access.element.ts | 6 +++--- .../user-workspace-assign-access.element.ts | 11 +++++++++-- .../user-workspace-profile-settings.element.ts | 4 ++++ .../user/workspace/user-workspace-editor.element.ts | 8 +++++--- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts b/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts index 6be3f5d9b4..7177e91909 100644 --- a/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts @@ -28,7 +28,7 @@ export class UmbUserWorkspaceAccessElement extends UmbLitElement { } override render() { - return html` + return html`
Based on the assigned groups and start nodes, the user has access to the following nodes - - + + + + + `; } From a9f53e3060b63e22f5cbc2e1cefac5a07cc70b8c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 11:06:52 +0200 Subject: [PATCH 044/322] Update collection-view-bundle.element.ts --- .../core/collection/components/collection-view-bundle.element.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/packages/core/collection/components/collection-view-bundle.element.ts b/src/packages/core/collection/components/collection-view-bundle.element.ts index 9936840c15..651f524f46 100644 --- a/src/packages/core/collection/components/collection-view-bundle.element.ts +++ b/src/packages/core/collection/components/collection-view-bundle.element.ts @@ -159,6 +159,7 @@ export class UmbCollectionViewBundleElement extends UmbLitElement { :host { --uui-button-content-align: left; --uui-menu-item-flat-structure: 1; + display: contents; } .filter-dropdown { From 9d39ce5905b5622470d9e133f209c1ab3b1c444d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 11:08:50 +0200 Subject: [PATCH 045/322] Update create-user-client-credential-modal.element.ts --- .../modal/create-user-client-credential-modal.element.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts index 6a8c9ab5f6..6907dd828b 100644 --- a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts +++ b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts @@ -52,9 +52,7 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement< } override render() { - return html` -

Lorem

- + return html` ${this.#renderForm()} Date: Tue, 3 Sep 2024 12:57:41 +0200 Subject: [PATCH 046/322] add description --- .../create/modal/create-user-client-credential-modal.element.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts index 6907dd828b..dc48873e55 100644 --- a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts +++ b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts @@ -74,7 +74,9 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement<
${this.#uniquePrefix}
+ +
The secret cannot be retrieved again.
Secret
From e61154820f96906d6523b49b8c9861c398da7eac Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 12:58:08 +0200 Subject: [PATCH 047/322] clean up ui --- .../user-workspace-client-credentials.element.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index 7d3fa116f9..512d97f2d6 100644 --- a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -113,7 +113,7 @@ export class UmbUserWorkspaceClientCredentialsElement extends UmbLitElement { return html`
Client Credentials
- ${this._clientCredentials.map((client) => html` ${this.#renderItem(client)} `)} + ${this._clientCredentials.map((client) => html` ${this.#renderItem(client)} `)} - + this.#onDelete(event, client)} label="Delete ${client.unique}" compact - > `; From 6475b8522d3e81379f37b42c47d20450a9e3b842 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 14:30:12 +0200 Subject: [PATCH 048/322] link to workspace --- .../name/user-table-name-column-layout.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts b/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts index b97ef2232e..849f47e095 100644 --- a/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts +++ b/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts @@ -40,7 +40,7 @@ export class UmbUserTableNameColumnLayoutElement extends LitElement { .name=${this.value.name || 'Unknown'} img-src=${ifDefined(this.value.avatarUrls.length > 0 ? avatarUrls[0].url : undefined)} img-srcset=${ifDefined(this.value.avatarUrls.length > 0 ? avatarSrcset : undefined)}> - ${this.value.name}
`; From 42d0222fb1072be8a38b88c241a1a5440da87a33 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 14:35:31 +0200 Subject: [PATCH 049/322] link to workspace --- .../views/grid/user-grid-collection-view.element.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index 7de4d20ea5..5f97e6f361 100644 --- a/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -50,12 +50,6 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { this._loading = false; } - //TODO How should we handle url stuff? - private _handleOpenCard(unique: string) { - //TODO this will not be needed when cards works as links with href - history.pushState(null, '', 'section/user-management/view/users/user/edit/' + unique); //TODO Change to a tag with href and make dynamic - } - #onSelect(user: UmbUserDetailModel) { this.#collectionContext?.selection.select(user.unique ?? ''); } @@ -102,10 +96,10 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { return html` 0} ?selected=${this.#collectionContext?.selection.isSelected(user.unique)} - @open=${() => this._handleOpenCard(user.unique)} @selected=${() => this.#onSelect(user)} @deselected=${() => this.#onDeselect(user)}> ${this.#renderUserTag(user)} ${this.#renderUserGroupNames(user)} ${this.#renderUserLoginDate(user)} From 605a05288e793fba1773953b224c959f0c17bae9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 15:02:03 +0200 Subject: [PATCH 050/322] add user section paths --- src/packages/user/user-section/paths.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/packages/user/user-section/paths.ts diff --git a/src/packages/user/user-section/paths.ts b/src/packages/user/user-section/paths.ts new file mode 100644 index 0000000000..f61a643ac5 --- /dev/null +++ b/src/packages/user/user-section/paths.ts @@ -0,0 +1,7 @@ +import { UMB_SECTION_PATH_PATTERN } from '@umbraco-cms/backoffice/section'; + +export const UMB_USER_SECTION_PATHNAME = 'user-management'; + +export const UMB_USER_SECTION_PATH = UMB_SECTION_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_USER_SECTION_PATHNAME, +}); From 7fb546290bebfbc391a1c338262294d3f346e702 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 15:02:11 +0200 Subject: [PATCH 051/322] add user workspace paths --- src/packages/user/user/paths.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/packages/user/user/paths.ts diff --git a/src/packages/user/user/paths.ts b/src/packages/user/user/paths.ts new file mode 100644 index 0000000000..e9040e7270 --- /dev/null +++ b/src/packages/user/user/paths.ts @@ -0,0 +1,8 @@ +import { UMB_USER_SECTION_PATHNAME } from '../user-section/paths.js'; +import { UMB_USER_ENTITY_TYPE } from './entity.js'; +import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; + +export const UMB_USER_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_USER_SECTION_PATHNAME, + entityType: UMB_USER_ENTITY_TYPE, +}); From 30238059be6f23b84042074772f13072db414056 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 15:02:29 +0200 Subject: [PATCH 052/322] use paths consts --- .../views/grid/user-grid-collection-view.element.ts | 5 ++++- .../name/user-table-name-column-layout.element.ts | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index 5f97e6f361..4a5aba82e4 100644 --- a/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -2,6 +2,7 @@ import { getDisplayStateFromUserStatus } from '../../../utils.js'; import type { UmbUserCollectionContext } from '../../user-collection.context.js'; import type { UmbUserDetailModel } from '../../../types.js'; import { UMB_USER_COLLECTION_CONTEXT } from '../../user-collection.context-token.js'; +import { UMB_USER_WORKSPACE_PATH } from '../../../paths.js'; import { css, html, nothing, customElement, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @@ -93,10 +94,12 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { avatarSrcset += `${url.url} ${url.scale},`; }); + const href = UMB_USER_WORKSPACE_PATH + '/edit/' + user.unique; + return html` 0} ?selected=${this.#collectionContext?.selection.isSelected(user.unique)} diff --git a/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts b/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts index 849f47e095..0e10cad16b 100644 --- a/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts +++ b/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts @@ -1,3 +1,4 @@ +import { UMB_USER_WORKSPACE_PATH } from '../../../../../paths.js'; import { html, LitElement, customElement, property, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import type { UmbTableColumn, UmbTableItem } from '@umbraco-cms/backoffice/components'; @@ -34,15 +35,15 @@ export class UmbUserTableNameColumnLayoutElement extends LitElement { avatarSrcset += `${url.url} ${url.scale},`; }); + const href = UMB_USER_WORKSPACE_PATH + '/edit/' + this.value.unique; + return html`
0 ? avatarUrls[0].url : undefined)} img-srcset=${ifDefined(this.value.avatarUrls.length > 0 ? avatarSrcset : undefined)}> - ${this.value.name} + ${this.value.name}
`; } } From 7b29e8817740db0edac415354f78d4e79f9e9423 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 15:07:44 +0200 Subject: [PATCH 053/322] fix mock data --- src/mocks/data/user/user.data.ts | 107 ++++++++++++++++--------------- src/mocks/data/user/user.db.ts | 31 +++++---- 2 files changed, 73 insertions(+), 65 deletions(-) diff --git a/src/mocks/data/user/user.data.ts b/src/mocks/data/user/user.data.ts index a1657a2531..2043e9d216 100644 --- a/src/mocks/data/user/user.data.ts +++ b/src/mocks/data/user/user.data.ts @@ -3,115 +3,120 @@ import type { UserResponseModel, UserTwoFactorProviderModel, } from '@umbraco-cms/backoffice/external/backend-api'; -import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api'; +import { UserKindModel, UserStateModel } from '@umbraco-cms/backoffice/external/backend-api'; export type UmbMockUserModel = UserResponseModel & UserItemResponseModel; export const data: Array = [ { - id: 'bca6c733-a63d-4353-a271-9a8b6bcca8bd', + avatarUrls: [], + createDate: '3/13/2022', documentStartNodeIds: [], + email: 'noreply@umbraco.com', + failedLoginAttempts: 946, hasDocumentRootAccess: true, - mediaStartNodeIds: [], hasMediaRootAccess: true, - name: 'Umbraco User', - email: 'noreply@umbraco.com', + id: 'bca6c733-a63d-4353-a271-9a8b6bcca8bd', + isAdmin: true, + kind: UserKindModel.DEFAULT, languageIsoCode: 'en-us', - state: UserStateModel.ACTIVE, - lastLoginDate: '9/10/2022', lastLockoutDate: '11/23/2021', + lastLoginDate: '9/10/2022', lastPasswordChangeDate: '1/10/2022', + mediaStartNodeIds: [], + name: 'Umbraco User', + state: UserStateModel.ACTIVE, updateDate: '2/10/2022', - createDate: '3/13/2022', - failedLoginAttempts: 946, userGroupIds: [{ id: 'user-group-administrators-id' }, { id: 'user-group-editors-id' }], userName: '', - avatarUrls: [], - isAdmin: true, }, { - id: '82e11d3d-b91d-43c9-9071-34d28e62e81d', + avatarUrls: [], + createDate: '2023-10-12T18:30:32.879Z', documentStartNodeIds: [{ id: 'simple-document-id' }], + email: 'awalker1@domain.com', + failedLoginAttempts: 0, hasDocumentRootAccess: true, - mediaStartNodeIds: [{ id: 'f2f81a40-c989-4b6b-84e2-057cecd3adc1' }], hasMediaRootAccess: true, - name: 'Amelie Walker', - email: 'awalker1@domain.com', + id: '82e11d3d-b91d-43c9-9071-34d28e62e81d', + isAdmin: true, + kind: UserKindModel.DEFAULT, languageIsoCode: 'da-dk', - state: UserStateModel.INACTIVE, - lastLoginDate: '2023-10-12T18:30:32.879Z', lastLockoutDate: null, + lastLoginDate: '2023-10-12T18:30:32.879Z', lastPasswordChangeDate: '2023-10-12T18:30:32.879Z', + mediaStartNodeIds: [{ id: 'f2f81a40-c989-4b6b-84e2-057cecd3adc1' }], + name: 'Amelie Walker', + state: UserStateModel.INACTIVE, updateDate: '2023-10-12T18:30:32.879Z', - createDate: '2023-10-12T18:30:32.879Z', - failedLoginAttempts: 0, userGroupIds: [{ id: 'user-group-administrators-id' }], userName: '', - avatarUrls: [], - isAdmin: true, }, { - id: 'aa1d83a9-bc7f-47d2-b288-58d8a31f5017', + avatarUrls: [], + createDate: '2023-10-12T18:30:32.879Z', documentStartNodeIds: [], - mediaStartNodeIds: [], + email: 'okim1@domain.com', + failedLoginAttempts: 0, hasDocumentRootAccess: true, hasMediaRootAccess: true, - name: 'Oliver Kim', - email: 'okim1@domain.com', + id: 'aa1d83a9-bc7f-47d2-b288-58d8a31f5017', + isAdmin: false, + kind: UserKindModel.DEFAULT, languageIsoCode: 'da-dk', - state: UserStateModel.ACTIVE, - lastLoginDate: '2023-10-12T18:30:32.879Z', lastLockoutDate: null, + lastLoginDate: '2023-10-12T18:30:32.879Z', lastPasswordChangeDate: '2023-10-12T18:30:32.879Z', + mediaStartNodeIds: [], + name: 'Oliver Kim', + state: UserStateModel.ACTIVE, updateDate: '2023-10-12T18:30:32.879Z', - createDate: '2023-10-12T18:30:32.879Z', - failedLoginAttempts: 0, userGroupIds: [{ id: 'user-group-editors-id' }], userName: '', - avatarUrls: [], - isAdmin: false, }, { - id: 'ff2f4a50-d3d4-4bc4-869d-c7948c160e54', + avatarUrls: [], + createDate: '2023-10-12T18:30:32.879Z', documentStartNodeIds: [], - mediaStartNodeIds: [], + email: 'enieves1@domain.com', + failedLoginAttempts: 0, hasDocumentRootAccess: true, hasMediaRootAccess: true, - name: 'Eliana Nieves', - email: 'enieves1@domain.com', + id: 'ff2f4a50-d3d4-4bc4-869d-c7948c160e54', + isAdmin: false, + kind: UserKindModel.DEFAULT, languageIsoCode: 'en-us', - state: UserStateModel.INVITED, - lastLoginDate: '2023-10-12T18:30:32.879Z', lastLockoutDate: null, + lastLoginDate: '2023-10-12T18:30:32.879Z', lastPasswordChangeDate: null, + mediaStartNodeIds: [], + name: 'Eliana Nieves', + state: UserStateModel.INVITED, updateDate: '2023-10-12T18:30:32.879Z', - createDate: '2023-10-12T18:30:32.879Z', - failedLoginAttempts: 0, userGroupIds: [{ id: 'user-group-editors-id' }], userName: '', - avatarUrls: [], - isAdmin: false, }, { - id: 'c290c6d9-9f12-4838-8567-621b52a178de', + avatarUrls: [], + createDate: '2023-10-12T18:30:32.879Z', documentStartNodeIds: [], - mediaStartNodeIds: [], + email: 'jpatel1@domain.com', + failedLoginAttempts: 25, hasDocumentRootAccess: true, hasMediaRootAccess: true, - name: 'Jasmine Patel', - email: 'jpatel1@domain.com', + id: 'c290c6d9-9f12-4838-8567-621b52a178de', + isAdmin: false, + kind: UserKindModel.DEFAULT, languageIsoCode: 'en-us', - state: UserStateModel.LOCKED_OUT, - lastLoginDate: '2023-10-12T18:30:32.879Z', lastLockoutDate: '2023-10-12T18:30:32.879Z', + lastLoginDate: '2023-10-12T18:30:32.879Z', lastPasswordChangeDate: null, + mediaStartNodeIds: [], + name: 'Jasmine Patel', + state: UserStateModel.LOCKED_OUT, updateDate: '2023-10-12T18:30:32.879Z', - createDate: '2023-10-12T18:30:32.879Z', - failedLoginAttempts: 25, userGroupIds: [{ id: 'user-group-editors-id' }, { id: 'user-group-sensitive-data-id' }], userName: '', - avatarUrls: [], - isAdmin: false, }, ]; diff --git a/src/mocks/data/user/user.db.ts b/src/mocks/data/user/user.db.ts index 414f584edf..2416aeb899 100644 --- a/src/mocks/data/user/user.db.ts +++ b/src/mocks/data/user/user.db.ts @@ -195,9 +195,10 @@ class UmbUserMockDB extends UmbEntityMockDbBase { const itemMapper = (item: UmbMockUserModel): UserItemResponseModel => { return { + avatarUrls: item.avatarUrls, id: item.id, + kind: item.kind, name: item.name, - avatarUrls: item.avatarUrls, }; }; @@ -222,30 +223,32 @@ const createMockMapper = (item: CreateUserRequestModel): UmbMockUserModel => { lastLockoutDate: null, lastPasswordChangeDate: null, isAdmin: item.userGroupIds.map((reference) => reference.id).includes(umbUserGroupMockDb.getAll()[0].id), + kind: item.kind, }; }; const detailResponseMapper = (item: UmbMockUserModel): UserResponseModel => { return { + avatarUrls: item.avatarUrls, + createDate: item.createDate, + documentStartNodeIds: item.documentStartNodeIds, email: item.email, - userName: item.userName, - name: item.name, - userGroupIds: item.userGroupIds, + failedLoginAttempts: item.failedLoginAttempts, + hasDocumentRootAccess: item.hasDocumentRootAccess, + hasMediaRootAccess: item.hasMediaRootAccess, id: item.id, + isAdmin: item.isAdmin, + kind: item.kind, languageIsoCode: item.languageIsoCode, - documentStartNodeIds: item.documentStartNodeIds, + lastLockoutDate: item.lastLockoutDate, + lastLoginDate: item.lastLoginDate, + lastPasswordChangeDate: item.lastPasswordChangeDate, mediaStartNodeIds: item.mediaStartNodeIds, - hasDocumentRootAccess: item.hasDocumentRootAccess, - hasMediaRootAccess: item.hasMediaRootAccess, - avatarUrls: item.avatarUrls, + name: item.name, state: item.state, - failedLoginAttempts: item.failedLoginAttempts, - createDate: item.createDate, updateDate: item.updateDate, - lastLoginDate: item.lastLoginDate, - lastLockoutDate: item.lastLockoutDate, - lastPasswordChangeDate: item.lastPasswordChangeDate, - isAdmin: item.isAdmin, + userGroupIds: item.userGroupIds, + userName: item.userName, }; }; From de84b0b2866b1a42071527a03acb2ca18ef50f3e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 15:10:28 +0200 Subject: [PATCH 054/322] update mock data --- src/mocks/data/member/member.data.ts | 9 ++++++++- src/mocks/data/member/member.db.ts | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/mocks/data/member/member.data.ts b/src/mocks/data/member/member.data.ts index d82092d4a2..ee2d5c0e1d 100644 --- a/src/mocks/data/member/member.data.ts +++ b/src/mocks/data/member/member.data.ts @@ -1,4 +1,8 @@ -import type { MemberResponseModel, MemberItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; +import { + type MemberResponseModel, + type MemberItemResponseModel, + MemberKindModel, +} from '@umbraco-cms/backoffice/external/backend-api'; export type UmbMockMemberModel = MemberResponseModel & MemberItemResponseModel; @@ -26,6 +30,7 @@ export const data: Array = [ updateDate: '2023-02-06T15:32:24.957009', }, ], + kind: MemberKindModel.DEFAULT, }, { email: 'member2@member.com', @@ -50,6 +55,7 @@ export const data: Array = [ updateDate: '2023-02-06T15:32:24.957009', }, ], + kind: MemberKindModel.DEFAULT, }, { email: 'member3@member.com', @@ -74,5 +80,6 @@ export const data: Array = [ updateDate: '2023-02-06T15:31:51.354764', }, ], + kind: MemberKindModel.DEFAULT, }, ]; diff --git a/src/mocks/data/member/member.db.ts b/src/mocks/data/member/member.db.ts index 59b36d0ead..c97ec93af9 100644 --- a/src/mocks/data/member/member.db.ts +++ b/src/mocks/data/member/member.db.ts @@ -66,6 +66,7 @@ const detailResponseMapper = (item: UmbMockMemberModel): MemberResponseModel => isApproved: item.isApproved, isLockedOut: item.isLockedOut, isTwoFactorEnabled: item.isTwoFactorEnabled, + kind: item.kind, lastLockoutDate: item.lastLockoutDate, lastLoginDate: item.lastLoginDate, lastPasswordChangeDate: item.lastPasswordChangeDate, @@ -79,6 +80,7 @@ const detailResponseMapper = (item: UmbMockMemberModel): MemberResponseModel => const itemResponseMapper = (item: UmbMockMemberModel): MemberItemResponseModel => { return { id: item.id, + kind: item.kind, memberType: item.memberType, variants: item.variants, }; From c2d22e9a822c8bab6607ad5e01e892aaad7afca3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 16:14:58 +0200 Subject: [PATCH 055/322] filter info on api users --- .../user-workspace-info/user-workspace-info.element.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts index da83d0569b..3294e78ac2 100644 --- a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts @@ -2,6 +2,7 @@ import type { UmbUserDisplayStatus } from '../../../utils.js'; import { TimeFormatOptions, getDisplayStateFromUserStatus } from '../../../utils.js'; import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; import type { UmbUserDetailModel } from '../../../types.js'; +import { UmbUserKind } from '../../../utils/index.js'; import { html, customElement, state, css, repeat, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -69,6 +70,11 @@ export class UmbUserWorkspaceInfoElement extends UmbLitElement { { labelKey: 'user_updateDate', value: this.localize.date(user.updateDate!, TimeFormatOptions) }, { labelKey: 'general_id', value: user.unique }, ]; + + if (user.kind === UmbUserKind.API) { + const include = ['user_kind', 'user_createDate', 'user_updateDate', 'general_id']; + this._userInfo = this._userInfo.filter((item) => include.includes(item.labelKey)); + } }; override render() { From e244b08da2b3845831ccd218a0944d69c27b6f08 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 16:25:45 +0200 Subject: [PATCH 056/322] hide UI language when editing an api user --- .../user-workspace-profile-settings.element.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts b/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts index 6a672827cc..fd4e67c615 100644 --- a/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts @@ -5,6 +5,7 @@ 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 { UmbUiCultureInputElement } from '@umbraco-cms/backoffice/localization'; +import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-workspace-profile-settings') export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { @@ -84,9 +85,7 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { } #renderUsernameProperty() { - if (this._usernameIsEmail) { - return nothing; - } + if (this._usernameIsEmail) return nothing; return html` Date: Tue, 3 Sep 2024 19:38:45 +0100 Subject: [PATCH 057/322] Fix up code so test passes & my rough entrypoint demo of usage works --- src/packages/property-editors/entry-point.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/property-editors/entry-point.ts b/src/packages/property-editors/entry-point.ts index 64d64bc9c4..f83895ac9b 100644 --- a/src/packages/property-editors/entry-point.ts +++ b/src/packages/property-editors/entry-point.ts @@ -22,9 +22,9 @@ export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'), ); - _extensionRegistry.appendCondition('Umb.Dashboard.UmbracoNewsLATE', condition); + _extensionRegistry.addCondition('Umb.Dashboard.UmbracoNewsLATE', condition); - console.log('I HAZ APPENED CONDITIONS'); + console.log('I HAZ ADDED CONDITION'); const ext: ManifestWithDynamicConditions = { alias: 'Umb.Dashboard.UmbracoNewsLATE', From 9cdea2999eb7bc49e7fc651ad2de7d97f194c51d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 3 Sep 2024 21:17:17 +0200 Subject: [PATCH 058/322] add dropdown to user collection create --- .../create-user-collection-action.element.ts | 80 +++++++++++++++++++ .../action/create-user.collection-action.ts | 32 -------- .../user/user/collection/action/manifests.ts | 7 +- 3 files changed, 81 insertions(+), 38 deletions(-) create mode 100644 src/packages/user/user/collection/action/create-user-collection-action.element.ts delete mode 100644 src/packages/user/user/collection/action/create-user.collection-action.ts diff --git a/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/packages/user/user/collection/action/create-user-collection-action.element.ts new file mode 100644 index 0000000000..183a0bf573 --- /dev/null +++ b/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -0,0 +1,80 @@ +import { UMB_CREATE_USER_MODAL } from '../../modals/create/create-user-modal.token.js'; +import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; + +const elementName = 'umb-create-user-collection-action-button'; +@customElement(elementName) +export class UmbCollectionActionButtonElement extends UmbLitElement { + @state() + private _popoverOpen = false; + + async #onClick(event: Event) { + event.stopPropagation(); + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); + + const unique = entityContext.getUnique(); + const entityType = entityContext.getEntityType(); + + if (unique === undefined) throw new Error('Missing unique'); + if (!entityType) throw new Error('Missing entityType'); + + const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL); + modalContext?.onSubmit().catch(async () => { + // modal is closed after creation instead of navigating to the new user. + // We therefore need to reload the children of the entity + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadChildrenOfEntityEvent({ + entityType, + unique, + }); + + eventContext.dispatchEvent(event); + }); + } + + #onPopoverToggle(event: ToggleEvent) { + // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this._popoverOpen = event.newState === 'open'; + } + + override render() { + const label = this.localize.term('general_create'); + + return html` + + ${label} + + + + + + + + + + + + + + + `; + } +} + +export { UmbCollectionActionButtonElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbCollectionActionButtonElement; + } +} diff --git a/src/packages/user/user/collection/action/create-user.collection-action.ts b/src/packages/user/user/collection/action/create-user.collection-action.ts deleted file mode 100644 index 73ac577b54..0000000000 --- a/src/packages/user/user/collection/action/create-user.collection-action.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { UMB_CREATE_USER_MODAL } from '../../modals/create/create-user-modal.token.js'; -import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; -import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; - -export class UmbCreateUserCollectionAction extends UmbControllerBase { - async execute() { - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); - - const unique = entityContext.getUnique(); - const entityType = entityContext.getEntityType(); - - if (unique === undefined) throw new Error('Missing unique'); - if (!entityType) throw new Error('Missing entityType'); - - const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL); - modalContext?.onSubmit().catch(async () => { - // modal is closed after creation instead of navigating to the new user. - // We therefore need to reload the children of the entity - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadChildrenOfEntityEvent({ - entityType, - unique, - }); - - eventContext.dispatchEvent(event); - }); - } -} diff --git a/src/packages/user/user/collection/action/manifests.ts b/src/packages/user/user/collection/action/manifests.ts index 7d2451635c..204d4cd117 100644 --- a/src/packages/user/user/collection/action/manifests.ts +++ b/src/packages/user/user/collection/action/manifests.ts @@ -1,17 +1,12 @@ -import { UmbCreateUserCollectionAction } from './create-user.collection-action.js'; import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const createManifest: ManifestTypes = { type: 'collectionAction', - kind: 'button', name: 'Create User Collection Action', alias: 'Umb.CollectionAction.User.Create', - api: UmbCreateUserCollectionAction, + element: () => import('./create-user-collection-action.element.js'), weight: 200, - meta: { - label: '#general_create', - }, conditions: [ { alias: UMB_COLLECTION_ALIAS_CONDITION, From 1697c33fe4773be1a574b7cef241e95e5b6b2229 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 10:25:40 +0200 Subject: [PATCH 059/322] add user avatar component --- .../grid/user-grid-collection-view.element.ts | 29 +------ src/packages/user/user/components/index.ts | 3 +- .../user-avatar/user-avatar.element.ts | 80 +++++++++++++++++++ 3 files changed, 83 insertions(+), 29 deletions(-) create mode 100644 src/packages/user/user/components/user-avatar/user-avatar.element.ts diff --git a/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index 4a5aba82e4..f80fa2d9b4 100644 --- a/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -73,27 +73,6 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { } #renderUserCard(user: UmbUserDetailModel) { - const avatarUrls = [ - { - scale: '1x', - url: user.avatarUrls?.[1], - }, - { - scale: '2x', - url: user.avatarUrls?.[2], - }, - { - scale: '3x', - url: user.avatarUrls?.[3], - }, - ]; - - let avatarSrcset = ''; - - avatarUrls.forEach((url) => { - avatarSrcset += `${url.url} ${url.scale},`; - }); - const href = UMB_USER_WORKSPACE_PATH + '/edit/' + user.unique; return html` @@ -106,13 +85,7 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { @selected=${() => this.#onSelect(user)} @deselected=${() => this.#onDeselect(user)}> ${this.#renderUserTag(user)} ${this.#renderUserGroupNames(user)} ${this.#renderUserLoginDate(user)} - - 0 ? avatarUrls[0].url : undefined)} - img-srcset=${ifDefined(user.avatarUrls.length > 0 ? avatarSrcset : undefined)}> +
`; } diff --git a/src/packages/user/user/components/index.ts b/src/packages/user/user/components/index.ts index 6f97b68e0a..a3e23b4c87 100644 --- a/src/packages/user/user/components/index.ts +++ b/src/packages/user/user/components/index.ts @@ -1,5 +1,6 @@ -import './user-input/user-input.element.js'; +import './user-avatar/user-avatar.element.js'; import './user-document-start-node/user-document-start-node.element.js'; +import './user-input/user-input.element.js'; import './user-media-start-node/user-media-start-node.element.js'; export * from './user-input/index.js'; diff --git a/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/packages/user/user/components/user-avatar/user-avatar.element.ts new file mode 100644 index 0000000000..56705be737 --- /dev/null +++ b/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -0,0 +1,80 @@ +import type { UmbUserItemModel } from '../../repository/index.js'; +import { css, html, customElement, property, nothing, ifDefined, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbUserKind } from '../../utils/index.js'; + +const elementName = 'umb-user-avatar'; +@customElement(elementName) +export class UmbUserAvatarElement extends UmbLitElement { + @property({ type: Object }) + public get user(): UmbUserItemModel | undefined { + return this.#user; + } + public set user(value: UmbUserItemModel | undefined) { + this.#user = value; + this.#setUrls(); + } + #user?: UmbUserItemModel | undefined; + + @state() + private _urls: Array<{ scale: string; url: string }> = []; + + @state() + private _srcset = ''; + + #setUrls() { + const urls = this.user?.avatarUrls ?? []; + this._srcset = ''; + + if (urls.length === 0) { + this._urls = []; + return; + } + + this._urls = [ + { + scale: '1x', + url: urls[1], + }, + { + scale: '2x', + url: urls[2], + }, + { + scale: '3x', + url: urls[3], + }, + ]; + + this._urls.forEach((url) => (this._srcset += `${url.url} ${url.scale},`)); + } + + override render() { + if (!this.user) return nothing; + + return html` 0 ? this._urls[0].url : undefined)} + img-srcset=${ifDefined(this._urls.length > 0 ? this._srcset : undefined)} + class="${this.user.kind === UmbUserKind.API ? 'api' : 'default'}">`; + } + + static override styles = [ + css` + uui-avatar { + background-color: transparent; + border: 1.5px solid var(--uui-color-divider-standalone); + } + + uui-avatar.api { + border-radius: var(--uui-border-radius); + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserAvatarElement; + } +} From e8228c566434fadac7b2a75ceff46c1ab7b9ce5c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 10:42:42 +0200 Subject: [PATCH 060/322] hide log in data for api users --- .../views/grid/user-grid-collection-view.element.ts | 7 ++++++- .../user/components/user-avatar/user-avatar.element.ts | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index f80fa2d9b4..50e9b8ca83 100644 --- a/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -9,6 +9,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbUserGroupDetailModel } from '@umbraco-cms/backoffice/user-group'; import { UmbUserGroupCollectionRepository } from '@umbraco-cms/backoffice/user-group'; +import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-grid-collection-view') export class UmbUserGridCollectionViewElement extends UmbLitElement { @@ -115,12 +116,14 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { } #renderUserLoginDate(user: UmbUserDetailModel) { + if (user.kind === UmbUserKind.API) return nothing; + if (!user.lastLoginDate) { return html``; } return html``; } @@ -142,6 +145,8 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { uui-card-user { width: 100%; height: 180px; + justify-content: normal; + padding-top: var(--uui-size-space-5); } .user-login-time { diff --git a/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/packages/user/user/components/user-avatar/user-avatar.element.ts index 56705be737..95834ad9a2 100644 --- a/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -1,7 +1,7 @@ import type { UmbUserItemModel } from '../../repository/index.js'; +import { UmbUserKind } from '../../utils/index.js'; import { css, html, customElement, property, nothing, ifDefined, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbUserKind } from '../../utils/index.js'; const elementName = 'umb-user-avatar'; @customElement(elementName) From 6b8cf656e8db22365f77c7032ccd02efac15b3e8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 11:13:05 +0200 Subject: [PATCH 061/322] split user into individual properties --- .../current-user-header-app.element.ts | 49 ++------------ .../grid/user-grid-collection-view.element.ts | 7 +- .../user-avatar/user-avatar.element.ts | 66 ++++++++++++------- 3 files changed, 52 insertions(+), 70 deletions(-) diff --git a/src/packages/user/current-user/current-user-header-app.element.ts b/src/packages/user/current-user/current-user-header-app.element.ts index 4349a8bec9..362d2d1e37 100644 --- a/src/packages/user/current-user/current-user-header-app.element.ts +++ b/src/packages/user/current-user/current-user-header-app.element.ts @@ -1,6 +1,6 @@ import { UMB_CURRENT_USER_MODAL } from './modals/current-user/current-user-modal.token.js'; import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; -import { css, html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { UMB_CURRENT_USER_CONTEXT, type UmbCurrentUserModel } from '@umbraco-cms/backoffice/current-user'; import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; @@ -10,9 +10,6 @@ export class UmbCurrentUserHeaderAppElement extends UmbHeaderAppButtonElement { @state() private _currentUser?: UmbCurrentUserModel; - @state() - private _userAvatarUrls: Array<{ url: string; descriptor: string }> = []; - #currentUserContext?: typeof UMB_CURRENT_USER_CONTEXT.TYPE; constructor() { @@ -31,8 +28,6 @@ export class UmbCurrentUserHeaderAppElement extends UmbHeaderAppButtonElement { this.#currentUserContext.currentUser, (currentUser) => { this._currentUser = currentUser; - if (!currentUser) return; - this.#setUserAvatarUrls(currentUser); }, 'umbCurrentUserObserver', ); @@ -43,41 +38,6 @@ export class UmbCurrentUserHeaderAppElement extends UmbHeaderAppButtonElement { modalManager.open(this, UMB_CURRENT_USER_MODAL); } - #setUserAvatarUrls = async (user: UmbCurrentUserModel | undefined) => { - if (!user || !user.avatarUrls || user.avatarUrls.length === 0) { - this._userAvatarUrls = []; - return; - } - - this._userAvatarUrls = [ - { - descriptor: '1x', - url: user.avatarUrls?.[0], - }, - { - descriptor: '2x', - url: user.avatarUrls?.[1], - }, - { - descriptor: '3x', - url: user.avatarUrls?.[2], - }, - ]; - }; - - #getAvatarSrcset() { - let string = ''; - - this._userAvatarUrls?.forEach((url) => { - string += `${url.url} ${url.descriptor},`; - }); - return string; - } - - #hasAvatar() { - return this._userAvatarUrls.length > 0; - } - override render() { return html` - + .name=${this._currentUser?.name} + .imgUrls=${this._currentUser?.avatarUrls || []}> `; } diff --git a/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index 50e9b8ca83..9bf21d2dfa 100644 --- a/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -86,7 +86,12 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { @selected=${() => this.#onSelect(user)} @deselected=${() => this.#onDeselect(user)}> ${this.#renderUserTag(user)} ${this.#renderUserGroupNames(user)} ${this.#renderUserLoginDate(user)} - +
`; } diff --git a/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/packages/user/user/components/user-avatar/user-avatar.element.ts index 95834ad9a2..b1c5354955 100644 --- a/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -1,62 +1,76 @@ -import type { UmbUserItemModel } from '../../repository/index.js'; +import type { UmbUserKindType } from '../../utils/index.js'; import { UmbUserKind } from '../../utils/index.js'; -import { css, html, customElement, property, nothing, ifDefined, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, property, ifDefined, state, classMap } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; const elementName = 'umb-user-avatar'; @customElement(elementName) export class UmbUserAvatarElement extends UmbLitElement { - @property({ type: Object }) - public get user(): UmbUserItemModel | undefined { - return this.#user; + @property({ type: String }) + name?: string; + + @property({ type: String }) + kind: UmbUserKindType = UmbUserKind.DEFAULT; + + @property({ type: Array, attribute: 'img-urls' }) + public get imgUrls(): Array { + return this.#imgUrls; } - public set user(value: UmbUserItemModel | undefined) { - this.#user = value; + public set imgUrls(value: Array) { + this.#imgUrls = value; this.#setUrls(); } - #user?: UmbUserItemModel | undefined; + #imgUrls: Array = []; + + @state() + private _imgSrc: Array<{ scale: string; url: string }> = []; @state() - private _urls: Array<{ scale: string; url: string }> = []; + private _imbSrcSet = ''; @state() - private _srcset = ''; + private hasImgUrls = false; #setUrls() { - const urls = this.user?.avatarUrls ?? []; - this._srcset = ''; + this._imbSrcSet = ''; - if (urls.length === 0) { - this._urls = []; + if (this.#imgUrls.length === 0) { + this._imgSrc = []; + this.hasImgUrls = false; return; } - this._urls = [ + this._imgSrc = [ { scale: '1x', - url: urls[1], + url: this.#imgUrls[1], }, { scale: '2x', - url: urls[2], + url: this.#imgUrls[2], }, { scale: '3x', - url: urls[3], + url: this.#imgUrls[3], }, ]; - this._urls.forEach((url) => (this._srcset += `${url.url} ${url.scale},`)); + this._imgSrc.forEach((url) => (this._imbSrcSet += `${url.url} ${url.scale},`)); + this.hasImgUrls = true; } override render() { - if (!this.user) return nothing; + const classes = { + default: this.kind === UmbUserKind.API, + api: this.kind === UmbUserKind.API, + 'has-image': this.hasImgUrls, + }; return html` 0 ? this._urls[0].url : undefined)} - img-srcset=${ifDefined(this._urls.length > 0 ? this._srcset : undefined)} - class="${this.user.kind === UmbUserKind.API ? 'api' : 'default'}">`; + .name=${this.name || 'Unknown'} + img-src=${ifDefined(this.hasImgUrls ? this._imgSrc[0].url : undefined)} + img-srcset=${ifDefined(this.hasImgUrls ? this._imbSrcSet : undefined)} + class=${classMap(classes)}>`; } static override styles = [ @@ -66,6 +80,10 @@ export class UmbUserAvatarElement extends UmbLitElement { border: 1.5px solid var(--uui-color-divider-standalone); } + uui-avatar.has-image { + border-color: transparent; + } + uui-avatar.api { border-radius: var(--uui-border-radius); } From 1b9b7ec99e1763109af25f533deeff062589f488 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 11:26:25 +0200 Subject: [PATCH 062/322] use umb avatar in table --- .../user-table-name-column-layout.element.ts | 33 ++++--------------- .../user-table-collection-view.element.ts | 1 + .../user-avatar/user-avatar.element.ts | 2 +- 3 files changed, 9 insertions(+), 27 deletions(-) diff --git a/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts b/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts index 0e10cad16b..15292958c7 100644 --- a/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts +++ b/src/packages/user/user/collection/views/table/column-layouts/name/user-table-name-column-layout.element.ts @@ -1,6 +1,7 @@ import { UMB_USER_WORKSPACE_PATH } from '../../../../../paths.js'; -import { html, LitElement, customElement, property, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { html, LitElement, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import type { UmbTableColumn, UmbTableItem } from '@umbraco-cms/backoffice/components'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @customElement('umb-user-table-name-column-layout') export class UmbUserTableNameColumnLayoutElement extends LitElement { @@ -14,38 +15,18 @@ export class UmbUserTableNameColumnLayoutElement extends LitElement { value!: any; override render() { - const avatarUrls = [ - { - scale: '1x', - url: this.value.avatarUrls?.[0], - }, - { - scale: '2x', - url: this.value.avatarUrls?.[1], - }, - { - scale: '3x', - url: this.value.avatarUrls?.[2], - }, - ]; - - let avatarSrcset = ''; - - avatarUrls.forEach((url) => { - avatarSrcset += `${url.url} ${url.scale},`; - }); - const href = UMB_USER_WORKSPACE_PATH + '/edit/' + this.value.unique; return html`
- 0 ? avatarUrls[0].url : undefined)} - img-srcset=${ifDefined(this.value.avatarUrls.length > 0 ? avatarSrcset : undefined)}> + name=${this.value.name} + kind=${this.value.kind} + .imgUrls=${this.value.avatarUrls}> ${this.value.name}
`; } + static override styles = [UmbTextStyles]; } export default UmbUserTableNameColumnLayoutElement; diff --git a/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts b/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts index 375ca885b3..94e6f08a49 100644 --- a/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts +++ b/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts @@ -122,6 +122,7 @@ export class UmbUserTableCollectionViewElement extends UmbLitElement { unique: user.unique, name: user.name, avatarUrls: user.avatarUrls, + kind: user.kind, }, }, { diff --git a/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/packages/user/user/components/user-avatar/user-avatar.element.ts index b1c5354955..e655ed1161 100644 --- a/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -12,7 +12,7 @@ export class UmbUserAvatarElement extends UmbLitElement { @property({ type: String }) kind: UmbUserKindType = UmbUserKind.DEFAULT; - @property({ type: Array, attribute: 'img-urls' }) + @property({ type: Array, attribute: false }) public get imgUrls(): Array { return this.#imgUrls; } From 78d4e4fa861196511ead373c167ffd33cd3fc497 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 11:59:19 +0200 Subject: [PATCH 063/322] user avatar in document + media history --- .../document-workspace-view-info-history.element.ts | 10 ++++++---- .../info/media-workspace-view-info-history.element.ts | 8 +++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts b/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts index a7745267f2..c4ab3b3dd8 100644 --- a/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts +++ b/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts @@ -120,13 +120,15 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement { (item) => { const { text, style } = getDocumentHistoryTagStyleAndText(item.logType); const user = this.#userMap.get(item.user.unique); - const userName = user?.name ?? 'Unknown'; - const avatarUrl = user && Array.isArray(user.avatarUrls) ? user.avatarUrls[1] : undefined; return html` - + diff --git a/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts b/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts index f8b464808d..46edfce147 100644 --- a/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts +++ b/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts @@ -102,13 +102,15 @@ export class UmbMediaWorkspaceViewInfoHistoryElement extends UmbLitElement { (item) => { const { text, style } = getMediaHistoryTagStyleAndText(item.logType); const user = this.#userMap.get(item.user.unique); - const userName = user?.name ?? 'Unknown'; - const avatarUrl = user && Array.isArray(user.avatarUrls) ? user.avatarUrls[1] : undefined; return html` - + From 5265b6eb58bfc95077bef034a0ae4058f5a99d21 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 12:08:22 +0200 Subject: [PATCH 064/322] use umb avatar in user workspace --- ...ent-workspace-view-info-history.element.ts | 2 +- ...dia-workspace-view-info-history.element.ts | 2 +- .../user-avatar/user-avatar.element.ts | 2 +- .../user-workspace-avatar.element.ts | 51 ++++--------------- 4 files changed, 12 insertions(+), 45 deletions(-) diff --git a/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts b/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts index c4ab3b3dd8..9388014614 100644 --- a/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts +++ b/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts @@ -127,7 +127,7 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement { diff --git a/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts b/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts index 46edfce147..f13d1de9ac 100644 --- a/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts +++ b/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts @@ -109,7 +109,7 @@ export class UmbMediaWorkspaceViewInfoHistoryElement extends UmbLitElement { diff --git a/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/packages/user/user/components/user-avatar/user-avatar.element.ts index e655ed1161..a70b088bee 100644 --- a/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -10,7 +10,7 @@ export class UmbUserAvatarElement extends UmbLitElement { name?: string; @property({ type: String }) - kind: UmbUserKindType = UmbUserKind.DEFAULT; + kind?: UmbUserKindType = UmbUserKind.DEFAULT; @property({ type: Array, attribute: false }) public get imgUrls(): Array { diff --git a/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts b/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts index 307900260b..b3c7317d12 100644 --- a/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts @@ -1,6 +1,6 @@ import type { UmbUserDetailModel } from '../../../types.js'; import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import { css, html, customElement, query, nothing, ifDefined, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, query, nothing, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-user-workspace-avatar') @@ -8,9 +8,6 @@ export class UmbUserAvatarElement extends UmbLitElement { @state() private _user?: UmbUserDetailModel; - @state() - private _userAvatarUrls: Array<{ url: string; scale: string }> = []; - @query('#AvatarFileField') _avatarFileField?: HTMLInputElement; @@ -38,30 +35,11 @@ export class UmbUserAvatarElement extends UmbLitElement { this.#userWorkspaceContext!.data, async (user) => { this._user = user; - this.#setUserAvatarUrls(user); }, 'umbUserObserver', ); }; - #setUserAvatarUrls = async (user: UmbUserDetailModel | undefined) => { - if (!user || !user.avatarUrls || user.avatarUrls.length === 0) { - this._userAvatarUrls = []; - return; - } - - this._userAvatarUrls = [ - { - scale: '1x', - url: user.avatarUrls?.[3], - }, - { - scale: '2x', - url: user.avatarUrls?.[4], - }, - ]; - }; - #uploadAvatar = async () => { try { const selectedFile = await this.#selectAvatar(); @@ -95,35 +73,24 @@ export class UmbUserAvatarElement extends UmbLitElement { #deleteAvatar = async () => { if (!this.#userWorkspaceContext) return; - const { error } = await this.#userWorkspaceContext.deleteAvatar(); - - if (!error) { - this._userAvatarUrls = []; - } + this.#userWorkspaceContext.deleteAvatar(); }; - #getAvatarSrcset() { - let string = ''; - - this._userAvatarUrls?.forEach((url) => { - string += `${url.url} ${url.scale},`; - }); - return string; - } - #hasAvatar() { - return this._userAvatarUrls.length > 0; + if (!this._user) return false; + return this._user.avatarUrls.length > 0; } override render() { + if (!this._user) return nothing; return html` - + .name=${this._user.name} + .kind=${this._user.kind} + .imgUrls=${this._user.avatarUrls ?? []}> ${this.#hasAvatar() From aeb4927319d1598ac80c64747fee36dcfc725324 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 12:29:28 +0200 Subject: [PATCH 065/322] use umb-user-avatar in user picker --- .../user/components/user-input/user-input.element.ts | 8 ++++++-- .../user/modals/user-picker/user-picker-modal.element.ts | 9 ++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/packages/user/user/components/user-input/user-input.element.ts b/src/packages/user/user/components/user-input/user-input.element.ts index 0ca83e9a7d..118cdc4a36 100644 --- a/src/packages/user/user/components/user-input/user-input.element.ts +++ b/src/packages/user/user/components/user-input/user-input.element.ts @@ -157,7 +157,11 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '') if (!item.unique) return nothing; return html` - + this.#removeItem(item)}> @@ -171,7 +175,7 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '') width: 100%; } - uui-avatar { + umb-user-avatar { font-size: var(--uui-size-4); } `, diff --git a/src/packages/user/user/modals/user-picker/user-picker-modal.element.ts b/src/packages/user/user/modals/user-picker/user-picker-modal.element.ts index 57c1262614..76356d5956 100644 --- a/src/packages/user/user/modals/user-picker/user-picker-modal.element.ts +++ b/src/packages/user/user/modals/user-picker/user-picker-modal.element.ts @@ -58,7 +58,11 @@ export class UmbUserPickerModalElement extends UmbModalBaseElement this.#selectionManager.select(user.unique)} @deselected=${() => this.#selectionManager.deselect(user.unique)} ?selected=${this.#selectionManager.isSelected(user.unique)}> - + `, )} @@ -74,8 +78,7 @@ export class UmbUserPickerModalElement extends UmbModalBaseElement Date: Wed, 4 Sep 2024 14:19:05 +0200 Subject: [PATCH 066/322] set img src based on element width --- .../user-avatar/user-avatar.element.ts | 73 +++++++++++++++---- 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/packages/user/user/components/user-avatar/user-avatar.element.ts index a70b088bee..b146e43a0f 100644 --- a/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -1,6 +1,17 @@ import type { UmbUserKindType } from '../../utils/index.js'; import { UmbUserKind } from '../../utils/index.js'; -import { css, html, customElement, property, ifDefined, state, classMap } from '@umbraco-cms/backoffice/external/lit'; +import type { UUIAvatarElement } from '@umbraco-cms/backoffice/external/uui'; +import type { PropertyValues } from '@umbraco-cms/backoffice/external/lit'; +import { + css, + html, + customElement, + property, + ifDefined, + state, + classMap, + query, +} from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; const elementName = 'umb-user-avatar'; @@ -18,45 +29,76 @@ export class UmbUserAvatarElement extends UmbLitElement { } public set imgUrls(value: Array) { this.#imgUrls = value; - this.#setUrls(); + this.hasImgUrls = value.length > 0; + this.#setImgSrcSizes(); } #imgUrls: Array = []; @state() - private _imgSrc: Array<{ scale: string; url: string }> = []; + private _imgSrcSizes: Array<{ w: number; url: string }> = []; @state() - private _imbSrcSet = ''; + private _imgSrc = ''; @state() private hasImgUrls = false; - #setUrls() { - this._imbSrcSet = ''; + @query('uui-avatar') + avatarElement!: UUIAvatarElement; + #setImgSrcSizes() { if (this.#imgUrls.length === 0) { - this._imgSrc = []; - this.hasImgUrls = false; + this._imgSrcSizes = []; return; } - this._imgSrc = [ + this._imgSrcSizes = [ { - scale: '1x', + w: 30, + url: this.#imgUrls[0], + }, + { + w: 60, url: this.#imgUrls[1], }, { - scale: '2x', + w: 90, url: this.#imgUrls[2], }, { - scale: '3x', + w: 150, url: this.#imgUrls[3], }, + { + w: 300, + url: this.#imgUrls[4], + }, ]; - this._imgSrc.forEach((url) => (this._imbSrcSet += `${url.url} ${url.scale},`)); - this.hasImgUrls = true; + this.#setImgSrc(); + } + + protected override firstUpdated(): void { + this.#setImgSrc(); + } + + async #setImgSrc() { + if (!this.hasImgUrls) return; + if (!this.avatarElement) return; + + setTimeout(() => { + // TODO: look into img sizes="auto" to let the browser handle the correct image size based on the element size + const elementSize = this.avatarElement.getBoundingClientRect(); + const elementWidth = elementSize.width; + + const matchingSizes = this._imgSrcSizes.filter((size) => { + // we multiply the element width to make sure we have a good quality image + return elementWidth * 1.5 <= size.w; + }); + + // We use the smallest image that is larger than the element width + this._imgSrc = matchingSizes[0]?.url; + }, 0); } override render() { @@ -68,8 +110,7 @@ export class UmbUserAvatarElement extends UmbLitElement { return html``; } From 7619c49df06cb4f4bc9a815b6385dbc4f8fce812 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 14:30:37 +0200 Subject: [PATCH 067/322] add better translations --- src/assets/lang/da-dk.ts | 2 ++ src/assets/lang/en-us.ts | 2 ++ .../action/create-user-collection-action.element.ts | 4 ++-- .../user-workspace-info/user-workspace-info.element.ts | 5 ++++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/assets/lang/da-dk.ts b/src/assets/lang/da-dk.ts index 6546006c07..f975e527f1 100644 --- a/src/assets/lang/da-dk.ts +++ b/src/assets/lang/da-dk.ts @@ -1953,6 +1953,8 @@ export default { sortNameDescending: 'Navn (Å-A)', sortCreateDateAscending: 'Nyeste', sortCreateDateDescending: 'Ældste', + userKindDefault: 'Bruger', + userKindApi: 'API Bruger', sortLastLoginDateDescending: 'Sidst logget ind', noUserGroupsAdded: 'Ingen brugere er blevet tilføjet', '2faDisableText': 'Hvis du ønsker at slå denne totrinsbekræftelse fra, så skal du nu indtaste koden fra din enhed:', diff --git a/src/assets/lang/en-us.ts b/src/assets/lang/en-us.ts index 4905ce13d9..413a54ab63 100644 --- a/src/assets/lang/en-us.ts +++ b/src/assets/lang/en-us.ts @@ -1983,6 +1983,8 @@ export default { sortCreateDateDescending: 'Newest', sortCreateDateAscending: 'Oldest', sortLastLoginDateDescending: 'Last login', + userKindDefault: 'User', + userKindApi: 'API User', noUserGroupsAdded: 'No user groups have been added', '2faDisableText': 'If you wish to disable this two-factor provider, then you must enter the code shown on your authentication device:', diff --git a/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/packages/user/user/collection/action/create-user-collection-action.element.ts index 183a0bf573..3b5ba95990 100644 --- a/src/packages/user/user/collection/action/create-user-collection-action.element.ts +++ b/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -58,10 +58,10 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { @toggle=${this.#onPopoverToggle}> - + - + diff --git a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts index 3294e78ac2..3be3786c98 100644 --- a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts @@ -45,7 +45,10 @@ export class UmbUserWorkspaceInfoElement extends UmbLitElement { this._userInfo = [ { labelKey: 'user_kind', - value: user.kind, + value: + user.kind === UmbUserKind.API + ? this.localize.term('user_userKindApi') + : this.localize.term('user_userKindDefault'), }, { labelKey: 'user_lastLogin', From e0ebcfb68eb6cb8c60c5a1f3d591c58a9b3c909b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 14:48:01 +0200 Subject: [PATCH 068/322] add unplug icon from lucide --- .../core/icon-registry/icon-dictionary.json | 4 ++++ src/packages/core/icon-registry/icons.ts | 4 ++++ .../core/icon-registry/icons/icon-unplug.ts | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 src/packages/core/icon-registry/icons/icon-unplug.ts diff --git a/src/packages/core/icon-registry/icon-dictionary.json b/src/packages/core/icon-registry/icon-dictionary.json index 4288bb4b7d..63d7dcceae 100644 --- a/src/packages/core/icon-registry/icon-dictionary.json +++ b/src/packages/core/icon-registry/icon-dictionary.json @@ -2308,6 +2308,10 @@ "name": "icon-unlocked", "file": "lock-open.svg" }, + { + "name": "icon-unplug", + "file": "unplug.svg" + }, { "name": "icon-untitled", "file": "box.svg", diff --git a/src/packages/core/icon-registry/icons.ts b/src/packages/core/icon-registry/icons.ts index 5b8e14cb97..1300eed95e 100644 --- a/src/packages/core/icon-registry/icons.ts +++ b/src/packages/core/icon-registry/icons.ts @@ -1967,6 +1967,10 @@ name: "icon-unlocked", path: () => import("./icons/icon-unlocked.js"), },{ +name: "icon-unplug", + +path: () => import("./icons/icon-unplug.js"), +},{ name: "icon-untitled", legacy: true, path: () => import("./icons/icon-untitled.js"), diff --git a/src/packages/core/icon-registry/icons/icon-unplug.ts b/src/packages/core/icon-registry/icons/icon-unplug.ts new file mode 100644 index 0000000000..be9a5e7702 --- /dev/null +++ b/src/packages/core/icon-registry/icons/icon-unplug.ts @@ -0,0 +1,19 @@ +export default ` + + + + + + + + +`; \ No newline at end of file From a10a2d51adfc998815a668c3c36696004669a8fe Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 14:48:55 +0200 Subject: [PATCH 069/322] use unplug icon for api user --- .../collection/action/create-user-collection-action.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/packages/user/user/collection/action/create-user-collection-action.element.ts index 3b5ba95990..11092189ec 100644 --- a/src/packages/user/user/collection/action/create-user-collection-action.element.ts +++ b/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -62,7 +62,7 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { - + From 8f7e76c5027f803e917922188bc908d84cc9f15d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 14:50:25 +0200 Subject: [PATCH 070/322] use unplug icon in table --- .../views/table/user-table-collection-view.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts b/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts index 94e6f08a49..b0f1ab7fc2 100644 --- a/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts +++ b/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts @@ -19,6 +19,7 @@ import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import './column-layouts/name/user-table-name-column-layout.element.js'; import './column-layouts/status/user-table-status-column-layout.element.js'; +import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-table-collection-view') export class UmbUserTableCollectionViewElement extends UmbLitElement { @@ -114,7 +115,7 @@ export class UmbUserTableCollectionViewElement extends UmbLitElement { this._tableItems = this._users.map((user) => { return { id: user.unique, - icon: 'icon-user', + icon: user.kind === UmbUserKind.API ? 'icon-unplug' : 'icon-user', data: [ { columnAlias: 'userName', From 1b165cbea58edd21c740fa30debfe2f6abe974b7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 14:56:25 +0200 Subject: [PATCH 071/322] simplify transaltions --- src/assets/lang/en-us.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/assets/lang/en-us.ts b/src/assets/lang/en-us.ts index 413a54ab63..bb471cf0f9 100644 --- a/src/assets/lang/en-us.ts +++ b/src/assets/lang/en-us.ts @@ -1839,8 +1839,8 @@ export default { assignAccess: 'Assign access', administrators: 'Administrator', categoryField: 'Category field', - createDate: 'User created', - changePassword: 'Change your password', + createDate: 'Created', + changePassword: 'Change password', changePhoto: 'Change photo', configureMfa: 'Configure MFA', emailRequired: 'Required - enter an email address for this user', @@ -1936,7 +1936,7 @@ export default { startnodehelp: 'Limit the content tree to a specific start node', startnodes: 'Content start nodes', startnodeshelp: 'Limit the content tree to specific start nodes', - updateDate: 'User last updated', + updateDate: 'Updated', userCreated: 'has been created', userCreatedSuccessHelp: 'The new user has successfully been created. To log in to Umbraco use the\n password below.\n ', From bbbd452ac3e51d693db01bcd10dd38bdef01019d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 15:11:32 +0200 Subject: [PATCH 072/322] align entity actions position with content workspace --- .../user/user/workspace/user-workspace-editor.element.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/packages/user/user/workspace/user-workspace-editor.element.ts index f7eaa4b38f..2526f44b14 100644 --- a/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -66,6 +66,7 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { + `; } @@ -89,11 +90,6 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { - - - `; } From 114d2d57c4a4b36c67b9ac4228e348ed0537f61a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 4 Sep 2024 15:17:13 +0200 Subject: [PATCH 073/322] align entity action position --- .../user-group-workspace-editor.element.ts | 93 +++++++------------ 1 file changed, 35 insertions(+), 58 deletions(-) diff --git a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts b/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts index 4888285574..613d012475 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts +++ b/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts @@ -174,11 +174,7 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { alias="Umb.Workspace.UserGroup" class="uui-text" back-path="/section/user-management/view/user-groups"> - ${this.#renderHeader()} -
-
${this.#renderLeftColumn()}
-
${this.#renderRightColumn()}
-
+ ${this.#renderHeader()} ${this.#renderMain()} `; } @@ -225,40 +221,46 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { ${umbFocus()}> + + `; } - #renderLeftColumn() { + #renderMain() { if (!this._unique) return nothing; return html` - -
- - - - - - ${this.#renderLanguageAccess()} ${this.#renderDocumentAccess()} ${this.#renderMediaAccess()} -
- - -
- - - - -
- - -
- -
+
+ + +
+ + + + + + ${this.#renderLanguageAccess()} ${this.#renderDocumentAccess()} ${this.#renderMediaAccess()} +
+ + +
+ + + + +
+ + +
+ +
+
+
`; } @@ -338,15 +340,6 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { `; } - #renderRightColumn() { - return html` - - - - - `; - } - static override styles = [ UmbTextStyles, css` @@ -375,25 +368,9 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { } #main { - display: grid; - grid-template-columns: 1fr 350px; - gap: var(--uui-size-layout-1); padding: var(--uui-size-layout-1); } - #left-column, - #right-column { - display: flex; - flex-direction: column; - gap: var(--uui-size-space-4); - } - - #right-column > uui-box > div { - display: flex; - flex-direction: column; - gap: var(--uui-size-space-2); - } - uui-input { width: 100%; } From 1afb5d3fee029e706f12badd9a6ea836667231ac Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 08:41:05 +0200 Subject: [PATCH 074/322] add user group paths --- src/packages/user/user-group/paths.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/packages/user/user-group/paths.ts diff --git a/src/packages/user/user-group/paths.ts b/src/packages/user/user-group/paths.ts new file mode 100644 index 0000000000..6fc1f8cc7e --- /dev/null +++ b/src/packages/user/user-group/paths.ts @@ -0,0 +1,8 @@ +import { UMB_USER_SECTION_PATHNAME } from '../user-section/paths.js'; +import { UMB_USER_GROUP_ENTITY_TYPE } from './entity.js'; +import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; + +export const UMB_USER_GROUP_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_USER_SECTION_PATHNAME, + entityType: UMB_USER_GROUP_ENTITY_TYPE, +}); From a70c2c23ff8fa2c130e73e45232cbb4ca0c38aa9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 08:55:57 +0200 Subject: [PATCH 075/322] link card to workspace --- .../components/user-group-table-name-column-layout.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user-group/collection/components/user-group-table-name-column-layout.element.ts b/src/packages/user/user-group/collection/components/user-group-table-name-column-layout.element.ts index 1a1274620d..f320f8ef79 100644 --- a/src/packages/user/user-group/collection/components/user-group-table-name-column-layout.element.ts +++ b/src/packages/user/user-group/collection/components/user-group-table-name-column-layout.element.ts @@ -1,3 +1,4 @@ +import { UMB_USER_GROUP_WORKSPACE_PATH } from '../../paths.js'; import { css, html, LitElement, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import type { UmbTableItem } from '@umbraco-cms/backoffice/components'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -11,7 +12,7 @@ export class UmbUserGroupTableNameColumnLayoutElement extends LitElement { value!: any; override render() { - const href = `section/user-management/view/user-groups/user-group/edit/${this.item.id}`; + const href = UMB_USER_GROUP_WORKSPACE_PATH + '/edit/' + this.item.id; return html`${this.value.name}`; } From fd2ae17b54c1ea047b1edc6142047c9f62e68e6f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 10:37:25 +0200 Subject: [PATCH 076/322] add kind to modal data --- .../user/user/modals/create/create-user-modal.token.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user/modals/create/create-user-modal.token.ts b/src/packages/user/user/modals/create/create-user-modal.token.ts index d8e2edf546..4486b12f4f 100644 --- a/src/packages/user/user/modals/create/create-user-modal.token.ts +++ b/src/packages/user/user/modals/create/create-user-modal.token.ts @@ -1,7 +1,14 @@ +import type { UmbUserKindType } from '../../utils/index.js'; import { UMB_CREATE_USER_MODAL_ALIAS } from './constants.js'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; -export const UMB_CREATE_USER_MODAL = new UmbModalToken(UMB_CREATE_USER_MODAL_ALIAS, { +export interface UmbCreateUserModalData { + user: { + kind?: UmbUserKindType; + }; +} + +export const UMB_CREATE_USER_MODAL = new UmbModalToken(UMB_CREATE_USER_MODAL_ALIAS, { modal: { type: 'dialog', size: 'small', From 871ae132e57460db2fde7fe98b031de48352f41a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 10:37:45 +0200 Subject: [PATCH 077/322] pass kind to modal --- .../create-user-collection-action.element.ts | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/packages/user/user/collection/action/create-user-collection-action.element.ts index 11092189ec..437243ed26 100644 --- a/src/packages/user/user/collection/action/create-user-collection-action.element.ts +++ b/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -1,4 +1,6 @@ import { UMB_CREATE_USER_MODAL } from '../../modals/create/create-user-modal.token.js'; +import type { UmbUserKindType } from '../../utils/index.js'; +import { UmbUserKind } from '../../utils/index.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; @@ -12,7 +14,7 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { @state() private _popoverOpen = false; - async #onClick(event: Event) { + async #onClick(event: Event, kind: UmbUserKindType) { event.stopPropagation(); const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); @@ -23,7 +25,13 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { if (unique === undefined) throw new Error('Missing unique'); if (!entityType) throw new Error('Missing entityType'); - const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL); + const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { + data: { + user: { + kind, + }, + }, + }); modalContext?.onSubmit().catch(async () => { // modal is closed after creation instead of navigating to the new user. // We therefore need to reload the children of the entity @@ -58,10 +66,14 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { @toggle=${this.#onPopoverToggle}> - + this.#onClick(event, UmbUserKind.DEFAULT)}> - + this.#onClick(event, UmbUserKind.API)}> From 05e169fca625bf1b676928b742a2d4c6233258bf Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 10:44:54 +0200 Subject: [PATCH 078/322] remove debugger --- .../user/modals/create/create-user-success-modal.element.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/packages/user/user/modals/create/create-user-success-modal.element.ts b/src/packages/user/user/modals/create/create-user-success-modal.element.ts index 03a6872298..8185df073f 100644 --- a/src/packages/user/user/modals/create/create-user-success-modal.element.ts +++ b/src/packages/user/user/modals/create/create-user-success-modal.element.ts @@ -36,8 +36,6 @@ export class UmbCreateUserSuccessModalElement extends UmbModalBaseElement< const unique = this.data?.user.unique; if (!unique) throw new Error('No user unique is provided'); - debugger; - const [userItemResponse, newPasswordResponse] = await Promise.all([ this.#userItemRepository.requestItems([unique]), this.#userNewPasswordRepository.requestNewPassword(unique), From e9bec8c5a3b24a6f3e4be90694c7b459914ca16b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 10:45:09 +0200 Subject: [PATCH 079/322] pass kind to repo --- .../create/create-user-modal.element.ts | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/packages/user/user/modals/create/create-user-modal.element.ts b/src/packages/user/user/modals/create/create-user-modal.element.ts index d3dc9ed3cc..3a2c03ba82 100644 --- a/src/packages/user/user/modals/create/create-user-modal.element.ts +++ b/src/packages/user/user/modals/create/create-user-modal.element.ts @@ -1,6 +1,8 @@ import { UmbUserDetailRepository } from '../../repository/index.js'; -import { UmbUserKind, UmbUserKindType } from '../../utils/index.js'; +import type { UmbUserKindType } from '../../utils/index.js'; +import { UmbUserKind } from '../../utils/index.js'; import { UMB_CREATE_USER_SUCCESS_MODAL } from './create-user-success-modal.token.js'; +import type { UmbCreateUserModalData } from './create-user-modal.token.js'; import type { UmbUserGroupInputElement } from '@umbraco-cms/backoffice/user-group'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, query } from '@umbraco-cms/backoffice/external/lit'; @@ -8,7 +10,7 @@ import { UmbModalBaseElement, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/bac import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; @customElement('umb-create-user-modal') -export class UmbCreateUserModalElement extends UmbModalBaseElement { +export class UmbCreateUserModalElement extends UmbModalBaseElement { #userDetailRepository = new UmbUserDetailRepository(this); @query('#CreateUserForm') @@ -25,7 +27,6 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { const formData = new FormData(form); - const kind = formData.get('kind') as UmbUserKindType; const name = formData.get('name') as string; const email = formData.get('email') as string; @@ -37,7 +38,7 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { const { data: userScaffold } = await this.#userDetailRepository.createScaffold(); if (!userScaffold) return; - userScaffold.kind = kind; + userScaffold.kind = this.data?.user.kind ?? UmbUserKind.DEFAULT; userScaffold.name = name; userScaffold.email = email; userScaffold.userName = email; @@ -47,7 +48,11 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { const { data } = await this.#userDetailRepository.create(userScaffold); if (data) { - this.#openSuccessModal(data.unique); + if (data.kind === UmbUserKind.DEFAULT) { + this.#openSuccessModal(data.unique); + } else { + this._submitModal(); + } } } @@ -97,15 +102,6 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement { #renderForm() { return html` - - Kind - - - ${UmbUserKind.DEFAULT} - ${UmbUserKind.API} - - - Name From 058fe95e39a34befa4d647c561f5683164e9e6f1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 11:07:44 +0200 Subject: [PATCH 080/322] use href --- .../modals/create/create-user-success-modal.element.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/packages/user/user/modals/create/create-user-success-modal.element.ts b/src/packages/user/user/modals/create/create-user-success-modal.element.ts index 8185df073f..bb5bcef6bb 100644 --- a/src/packages/user/user/modals/create/create-user-success-modal.element.ts +++ b/src/packages/user/user/modals/create/create-user-success-modal.element.ts @@ -11,6 +11,7 @@ import type { UUIInputPasswordElement } from '@umbraco-cms/backoffice/external/u import type { UmbNotificationDefaultData, UmbNotificationContext } from '@umbraco-cms/backoffice/notification'; import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import { UMB_USER_WORKSPACE_PATH } from '../../paths.js'; @customElement('umb-create-user-success-modal') export class UmbCreateUserSuccessModalElement extends UmbModalBaseElement< @@ -69,10 +70,8 @@ export class UmbCreateUserSuccessModalElement extends UmbModalBaseElement< this._rejectModal({ type: 'createAnotherUser' }); }; - #onGoToProfile = (event: Event) => { - event.stopPropagation(); + #onGoToProfile = () => { this._submitModal(); - history.pushState(null, '', 'section/user-management/view/users/user/edit/' + this.data?.user.unique); //TODO: URL Should be dynamic }; override render() { @@ -98,7 +97,8 @@ export class UmbCreateUserSuccessModalElement extends UmbModalBaseElement< slot="actions" label="Go to profile" look="primary" - color="positive">
+ color="positive" + href=${UMB_USER_WORKSPACE_PATH + '/edit/' + this.data?.user.unique}>
`; } From 7fea6d466714fdef498b54d4e813679147d6454f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 15:20:30 +0200 Subject: [PATCH 081/322] translate create dialog headline and description --- src/assets/lang/da-dk.ts | 3 +++ src/assets/lang/en-us.ts | 8 ++++++++ .../user/user/modals/create/create-user-modal.element.ts | 7 ++----- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/assets/lang/da-dk.ts b/src/assets/lang/da-dk.ts index f975e527f1..d60320fb16 100644 --- a/src/assets/lang/da-dk.ts +++ b/src/assets/lang/da-dk.ts @@ -1831,6 +1831,9 @@ export default { administrators: 'Administrator', categoryField: 'Kategorifelt', createDate: 'Bruger oprettet', + createUserHeadline: (kind: string) => { + return kind === 'Api' ? 'Opret API bruger' : 'Opret bruger'; + }, changePassword: 'Skift dit kodeord', changePhoto: 'Skift billede', newPassword: 'Nyt kodeord', diff --git a/src/assets/lang/en-us.ts b/src/assets/lang/en-us.ts index bb471cf0f9..5e0d3f266e 100644 --- a/src/assets/lang/en-us.ts +++ b/src/assets/lang/en-us.ts @@ -1840,6 +1840,14 @@ export default { administrators: 'Administrator', categoryField: 'Category field', createDate: 'Created', + createUserHeadline: (kind: string) => { + return kind === 'Api' ? 'Create API user' : 'Create user'; + }, + createUserDescription: (kind: string) => { + const defaultUserText = `Create a user to give them access to Umbraco. When a user is created a password will be generated that you can share with them.`; + const apiUserText = `Create an Api User to allow external services to authenticate with the Umbraco Management API.`; + return kind === 'Api' ? apiUserText : defaultUserText; + }, changePassword: 'Change password', changePhoto: 'Change photo', configureMfa: 'Configure MFA', diff --git a/src/packages/user/user/modals/create/create-user-modal.element.ts b/src/packages/user/user/modals/create/create-user-modal.element.ts index 3a2c03ba82..adc53caec4 100644 --- a/src/packages/user/user/modals/create/create-user-modal.element.ts +++ b/src/packages/user/user/modals/create/create-user-modal.element.ts @@ -81,11 +81,8 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement -

- Create new users to give them access to Umbraco. When a user is created a password will be generated that you - can share with the user. -

+ return html` +

${this.localize.term('user_createUserDescription', this.data?.user.kind)}

${this.#renderForm()} From bdcb6459f7f4e352154a2e26fa27c5ef2372abb0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 15:21:14 +0200 Subject: [PATCH 082/322] remove unused --- .../user/user/modals/create/create-user-modal.element.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/packages/user/user/modals/create/create-user-modal.element.ts b/src/packages/user/user/modals/create/create-user-modal.element.ts index adc53caec4..863fc88bec 100644 --- a/src/packages/user/user/modals/create/create-user-modal.element.ts +++ b/src/packages/user/user/modals/create/create-user-modal.element.ts @@ -1,5 +1,4 @@ import { UmbUserDetailRepository } from '../../repository/index.js'; -import type { UmbUserKindType } from '../../utils/index.js'; import { UmbUserKind } from '../../utils/index.js'; import { UMB_CREATE_USER_SUCCESS_MODAL } from './create-user-success-modal.token.js'; import type { UmbCreateUserModalData } from './create-user-modal.token.js'; From 75259b50402acd6624aa681d2c1dac666ddef557 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 15:23:02 +0200 Subject: [PATCH 083/322] fix order --- .../user/modals/create/create-user-success-modal.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user/modals/create/create-user-success-modal.element.ts b/src/packages/user/user/modals/create/create-user-success-modal.element.ts index bb5bcef6bb..f30bf145be 100644 --- a/src/packages/user/user/modals/create/create-user-success-modal.element.ts +++ b/src/packages/user/user/modals/create/create-user-success-modal.element.ts @@ -1,6 +1,7 @@ import { UmbUserItemRepository } from '../../repository/item/index.js'; import { UmbNewUserPasswordRepository } from '../../repository/new-password/index.js'; import type { UmbUserItemModel } from '../../repository/item/types.js'; +import { UMB_USER_WORKSPACE_PATH } from '../../paths.js'; import type { UmbCreateUserSuccessModalData, UmbCreateUserSuccessModalValue, @@ -11,7 +12,6 @@ import type { UUIInputPasswordElement } from '@umbraco-cms/backoffice/external/u import type { UmbNotificationDefaultData, UmbNotificationContext } from '@umbraco-cms/backoffice/notification'; import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; -import { UMB_USER_WORKSPACE_PATH } from '../../paths.js'; @customElement('umb-create-user-success-modal') export class UmbCreateUserSuccessModalElement extends UmbModalBaseElement< From 149fcceab53a21e2923a98bb99b8b75c5f16ebe8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 5 Sep 2024 15:42:27 +0200 Subject: [PATCH 084/322] reload collection after user creation --- .../create-user-collection-action.element.ts | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/packages/user/user/collection/action/create-user-collection-action.element.ts index 437243ed26..4ffcc353d0 100644 --- a/src/packages/user/user/collection/action/create-user-collection-action.element.ts +++ b/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -4,6 +4,7 @@ import { UmbUserKind } from '../../utils/index.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; @@ -32,17 +33,27 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { }, }, }); - modalContext?.onSubmit().catch(async () => { - // modal is closed after creation instead of navigating to the new user. - // We therefore need to reload the children of the entity - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadChildrenOfEntityEvent({ - entityType, - unique, + + modalContext + ?.onSubmit() + .then(() => { + this.#requestReloadChildrenOfEntity({ entityType, unique }); + }) + .catch(async () => { + // modal is closed after creation instead of navigating to the new user. + // We therefore need to reload the children of the entity + this.#requestReloadChildrenOfEntity({ entityType, unique }); }); + } - eventContext.dispatchEvent(event); + async #requestReloadChildrenOfEntity({ entityType, unique }: UmbEntityModel) { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadChildrenOfEntityEvent({ + entityType, + unique, }); + + eventContext.dispatchEvent(event); } #onPopoverToggle(event: ToggleEvent) { From c6f3d1cf28a8a5bf81395cc86140127a0f0f1028 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 14:00:08 +0200 Subject: [PATCH 085/322] add a more generic description of username --- src/assets/lang/da-dk.ts | 2 +- src/assets/lang/en-us.ts | 2 +- src/assets/lang/en.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/assets/lang/da-dk.ts b/src/assets/lang/da-dk.ts index d60320fb16..1ffcb224a6 100644 --- a/src/assets/lang/da-dk.ts +++ b/src/assets/lang/da-dk.ts @@ -1868,7 +1868,7 @@ export default { lastPasswordChangeDate: 'Kodeord sidst ændret', loginname: 'Brugernavn', loginnameRequired: 'Påkrævet - indtast et brugernavn for denne bruger', - loginnameDescription: 'Brugernavnet bruges til at logge ind og til at identificere brugeren', + loginnameDescription: 'Et unikt navn til at identificere brugeren', mediastartnode: 'Startnode i mediearkivet', mediastartnodehelp: 'Begræns mediebiblioteket til en bestemt startnode', mediastartnodes: 'Medie startnoder', diff --git a/src/assets/lang/en-us.ts b/src/assets/lang/en-us.ts index 5e0d3f266e..45ed7d1318 100644 --- a/src/assets/lang/en-us.ts +++ b/src/assets/lang/en-us.ts @@ -1890,7 +1890,7 @@ export default { lastPasswordChangeDate: 'Password last changed', loginname: 'Username', loginnameRequired: 'Required - enter a username for this user', - loginnameDescription: 'The username is used for logging in', + loginnameDescription: 'A unique name that identifies the user', mediastartnode: 'Media start node', mediastartnodehelp: 'Limit the media library to a specific start node', mediastartnodes: 'Media start nodes', diff --git a/src/assets/lang/en.ts b/src/assets/lang/en.ts index 551e778e96..43eb4cf416 100644 --- a/src/assets/lang/en.ts +++ b/src/assets/lang/en.ts @@ -1939,7 +1939,7 @@ export default { lastPasswordChangeDate: 'Password last changed', loginname: 'Username', loginnameRequired: 'Required - enter a username for this user', - loginnameDescription: 'The username is used for logging in', + loginnameDescription: 'A unique name that identifies the user', mediastartnode: 'Media start node', mediastartnodehelp: 'Limit the media library to a specific start node', mediastartnodes: 'Media start nodes', From ab61fd5f77faccefa137f1d16c93e3f206ef2e91 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 14:08:01 +0200 Subject: [PATCH 086/322] always show email on username --- ...user-workspace-profile-settings.element.ts | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts b/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts index fd4e67c615..b37b11d69b 100644 --- a/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts @@ -1,11 +1,11 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; import type { UmbUserDetailModel } from '../../../types.js'; +import { UmbUserKind } from '../../../utils/index.js'; import { html, customElement, state, ifDefined, 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 { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbUiCultureInputElement } from '@umbraco-cms/backoffice/localization'; -import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-workspace-profile-settings') export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { @@ -31,7 +31,7 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { }); } - #onEmailChange(event: UmbChangeEvent) { + #onEmailInput(event: UmbChangeEvent) { const target = event.target as HTMLInputElement; if (typeof target?.value === 'string') { @@ -43,7 +43,7 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { } } - #onUsernameChange(event: UmbChangeEvent) { + #onUsernameInput(event: UmbChangeEvent) { const target = event.target as HTMLInputElement; if (typeof target?.value === 'string') { @@ -62,44 +62,44 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { override render() { return html`
Profile
- ${this.#renderEmailProperty()} ${this.#renderUsernameProperty()} ${this.#renderUILanguageProperty()} + ${this.#renderUsernameProperty()}${this.#renderEmailProperty()} ${this.#renderUILanguageProperty()}
`; } - #renderEmailProperty() { + #renderUsernameProperty() { return html` + label="${this.localize.term('user_loginname')}" + description=${this.localize.term('user_loginnameDescription')}> + required-message=${this.localize.term('user_loginnameRequired')} + value=${ifDefined(this._user?.userName)} + ?readonly=${this._usernameIsEmail}> `; } - #renderUsernameProperty() { - if (this._usernameIsEmail) return nothing; - + #renderEmailProperty() { return html` + ?mandatory=${this._usernameIsEmail} + label="${this.localize.term('general_email')}" + .description=${this.localize.term('user_emailDescription', this._usernameIsEmail)}> + required-message=${this.localize.term('user_emailRequired')} + value=${ifDefined(this._user?.email)}> `; } From 6d249982aec36a1c5d5a2ed535f7b70c9a4a04e4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 15:42:43 +0200 Subject: [PATCH 087/322] Revert "add a more generic description of username" This reverts commit c6f3d1cf28a8a5bf81395cc86140127a0f0f1028. --- src/assets/lang/da-dk.ts | 2 +- src/assets/lang/en-us.ts | 2 +- src/assets/lang/en.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/assets/lang/da-dk.ts b/src/assets/lang/da-dk.ts index 1ffcb224a6..d60320fb16 100644 --- a/src/assets/lang/da-dk.ts +++ b/src/assets/lang/da-dk.ts @@ -1868,7 +1868,7 @@ export default { lastPasswordChangeDate: 'Kodeord sidst ændret', loginname: 'Brugernavn', loginnameRequired: 'Påkrævet - indtast et brugernavn for denne bruger', - loginnameDescription: 'Et unikt navn til at identificere brugeren', + loginnameDescription: 'Brugernavnet bruges til at logge ind og til at identificere brugeren', mediastartnode: 'Startnode i mediearkivet', mediastartnodehelp: 'Begræns mediebiblioteket til en bestemt startnode', mediastartnodes: 'Medie startnoder', diff --git a/src/assets/lang/en-us.ts b/src/assets/lang/en-us.ts index 45ed7d1318..5e0d3f266e 100644 --- a/src/assets/lang/en-us.ts +++ b/src/assets/lang/en-us.ts @@ -1890,7 +1890,7 @@ export default { lastPasswordChangeDate: 'Password last changed', loginname: 'Username', loginnameRequired: 'Required - enter a username for this user', - loginnameDescription: 'A unique name that identifies the user', + loginnameDescription: 'The username is used for logging in', mediastartnode: 'Media start node', mediastartnodehelp: 'Limit the media library to a specific start node', mediastartnodes: 'Media start nodes', diff --git a/src/assets/lang/en.ts b/src/assets/lang/en.ts index 43eb4cf416..551e778e96 100644 --- a/src/assets/lang/en.ts +++ b/src/assets/lang/en.ts @@ -1939,7 +1939,7 @@ export default { lastPasswordChangeDate: 'Password last changed', loginname: 'Username', loginnameRequired: 'Required - enter a username for this user', - loginnameDescription: 'A unique name that identifies the user', + loginnameDescription: 'The username is used for logging in', mediastartnode: 'Media start node', mediastartnodehelp: 'Limit the media library to a specific start node', mediastartnodes: 'Media start nodes', From d204d582d49ee8b9cbf501fbb6786f4fe4e32785 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 15:42:49 +0200 Subject: [PATCH 088/322] Revert "always show email on username" This reverts commit ab61fd5f77faccefa137f1d16c93e3f206ef2e91. --- ...user-workspace-profile-settings.element.ts | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts b/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts index b37b11d69b..fd4e67c615 100644 --- a/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts @@ -1,11 +1,11 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; import type { UmbUserDetailModel } from '../../../types.js'; -import { UmbUserKind } from '../../../utils/index.js'; import { html, customElement, state, ifDefined, 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 { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbUiCultureInputElement } from '@umbraco-cms/backoffice/localization'; +import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-workspace-profile-settings') export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { @@ -31,7 +31,7 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { }); } - #onEmailInput(event: UmbChangeEvent) { + #onEmailChange(event: UmbChangeEvent) { const target = event.target as HTMLInputElement; if (typeof target?.value === 'string') { @@ -43,7 +43,7 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { } } - #onUsernameInput(event: UmbChangeEvent) { + #onUsernameChange(event: UmbChangeEvent) { const target = event.target as HTMLInputElement; if (typeof target?.value === 'string') { @@ -62,44 +62,44 @@ export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { override render() { return html`
Profile
- ${this.#renderUsernameProperty()}${this.#renderEmailProperty()} ${this.#renderUILanguageProperty()} + ${this.#renderEmailProperty()} ${this.#renderUsernameProperty()} ${this.#renderUILanguageProperty()}
`; } - #renderUsernameProperty() { + #renderEmailProperty() { return html` + label="${this.localize.term('general_email')}" + .description=${this.localize.term('user_emailDescription', this._usernameIsEmail)}> + required-message=${this.localize.term('user_emailRequired')} + value=${ifDefined(this._user?.email)}> `; } - #renderEmailProperty() { + #renderUsernameProperty() { + if (this._usernameIsEmail) return nothing; + return html` + mandatory + label="${this.localize.term('user_loginname')}" + description=${this.localize.term('user_loginnameDescription')}> + required-message=${this.localize.term('user_loginnameRequired')} + value=${ifDefined(this._user?.userName)}> `; } From eb8a170e8923967caa2a37ec1196332cecbfd32a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 16:33:03 +0200 Subject: [PATCH 089/322] Update types.gen.ts --- src/external/backend-api/src/types.gen.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/external/backend-api/src/types.gen.ts b/src/external/backend-api/src/types.gen.ts index 224bc0862b..8a194b70f5 100644 --- a/src/external/backend-api/src/types.gen.ts +++ b/src/external/backend-api/src/types.gen.ts @@ -1081,7 +1081,6 @@ export type InviteUserRequestModel = { name: string; userGroupIds: Array<(ReferenceByIdModel)>; id?: string | null; - kind: UserKindModel; message?: string | null; }; From 73553752b3820eb137202b93700c55a103499df2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 16:35:58 +0200 Subject: [PATCH 090/322] Update ApiRequestOptions.ts --- .../backend-api/src/core/ApiRequestOptions.ts | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/external/backend-api/src/core/ApiRequestOptions.ts b/src/external/backend-api/src/core/ApiRequestOptions.ts index 939a0aa4c8..1758d98c4d 100644 --- a/src/external/backend-api/src/core/ApiRequestOptions.ts +++ b/src/external/backend-api/src/core/ApiRequestOptions.ts @@ -1,21 +1,14 @@ export type ApiRequestOptions = { - readonly body?: any; + readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; + readonly url: string; + readonly path?: Record; readonly cookies?: Record; - readonly errors?: Record; - readonly formData?: Record | any[] | Blob | File; readonly headers?: Record; - readonly mediaType?: string; - readonly method: - | 'DELETE' - | 'GET' - | 'HEAD' - | 'OPTIONS' - | 'PATCH' - | 'POST' - | 'PUT'; - readonly path?: Record; readonly query?: Record; + readonly formData?: Record; + readonly body?: any; + readonly mediaType?: string; readonly responseHeader?: string; readonly responseTransformer?: (data: unknown) => Promise; - readonly url: string; + readonly errors?: Record; }; \ No newline at end of file From 448f0951bce553689f51d337824f65c8ec421042 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 16:36:57 +0200 Subject: [PATCH 091/322] Delete index.ts --- src/packages/user/user/collection/action/index.ts | 1 - 1 file changed, 1 deletion(-) delete mode 100644 src/packages/user/user/collection/action/index.ts diff --git a/src/packages/user/user/collection/action/index.ts b/src/packages/user/user/collection/action/index.ts deleted file mode 100644 index 807c9a6fee..0000000000 --- a/src/packages/user/user/collection/action/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { UmbCreateUserCollectionAction } from './create-user.collection-action.js'; From c2bdc9f84f95f813827a6f30c998f8aacd0f9342 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 16:38:30 +0200 Subject: [PATCH 092/322] Update member.db.ts --- src/mocks/data/member/member.db.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/mocks/data/member/member.db.ts b/src/mocks/data/member/member.db.ts index c97ec93af9..ca5fb77e98 100644 --- a/src/mocks/data/member/member.db.ts +++ b/src/mocks/data/member/member.db.ts @@ -6,10 +6,11 @@ import { UmbMockContentCollectionManager } from '../utils/content/content-collec import type { UmbMockMemberModel } from './member.data.js'; import { data } from './member.data.js'; import { UmbId } from '@umbraco-cms/backoffice/id'; -import type { - CreateMemberRequestModel, - MemberItemResponseModel, - MemberResponseModel, +import { + MemberKindModel, + type CreateMemberRequestModel, + type MemberItemResponseModel, + type MemberResponseModel, } from '@umbraco-cms/backoffice/external/backend-api'; class UmbMemberMockDB extends UmbEntityMockDbBase { @@ -39,6 +40,7 @@ const createDetailMockMapper = (request: CreateMemberRequestModel): UmbMockMembe lastLockoutDate: null, lastLoginDate: null, lastPasswordChangeDate: null, + kind: MemberKindModel.DEFAULT, memberType: { id: memberType.id, icon: memberType.icon, From 7bccbf90a2001ade6fa4af0542484b68926cacdc Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 16:42:22 +0200 Subject: [PATCH 093/322] inherit color --- .../user/user/components/user-avatar/user-avatar.element.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/packages/user/user/components/user-avatar/user-avatar.element.ts index b146e43a0f..e36bf586a7 100644 --- a/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -119,6 +119,7 @@ export class UmbUserAvatarElement extends UmbLitElement { uui-avatar { background-color: transparent; border: 1.5px solid var(--uui-color-divider-standalone); + color: inherit; } uui-avatar.has-image { From 235fc3eab06642015c9357007dffd68651b35766 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 16:53:36 +0200 Subject: [PATCH 094/322] Update types.ts --- src/packages/user/user/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user/types.ts b/src/packages/user/user/types.ts index 4c3b9f9935..cbb8fe2fe2 100644 --- a/src/packages/user/user/types.ts +++ b/src/packages/user/user/types.ts @@ -1,11 +1,11 @@ import type { UmbUserEntityType } from './entity.js'; +import type { UmbUserKindType } from './utils/index.js'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import { type UserConfigurationResponseModel, UserStateModel, type UserTwoFactorProviderModel, } from '@umbraco-cms/backoffice/external/backend-api'; -import { UmbUserKindType } from './utils/index.js'; export type UmbUserStateEnum = UserStateModel; export const UmbUserStateEnum = UserStateModel; From f4b86a489f732eeb61dd8ed733179993af86af11 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 17:59:20 +0200 Subject: [PATCH 095/322] scaffold help package + header app --- src/apps/backoffice/backoffice.element.ts | 1 + src/packages/help/help-header-app.element.ts | 21 ++++++++++++++++++++ src/packages/help/manifests.ts | 16 +++++++++++++++ src/packages/help/umbraco-package.ts | 9 +++++++++ src/packages/help/vite.config.ts | 12 +++++++++++ 5 files changed, 59 insertions(+) create mode 100644 src/packages/help/help-header-app.element.ts create mode 100644 src/packages/help/manifests.ts create mode 100644 src/packages/help/umbraco-package.ts create mode 100644 src/packages/help/vite.config.ts diff --git a/src/apps/backoffice/backoffice.element.ts b/src/apps/backoffice/backoffice.element.ts index d59e98126c..cdaffce824 100644 --- a/src/apps/backoffice/backoffice.element.ts +++ b/src/apps/backoffice/backoffice.element.ts @@ -18,6 +18,7 @@ const CORE_PACKAGES = [ import('../../packages/dictionary/umbraco-package.js'), import('../../packages/documents/umbraco-package.js'), import('../../packages/health-check/umbraco-package.js'), + import('../../packages/help/umbraco-package.js'), import('../../packages/language/umbraco-package.js'), import('../../packages/log-viewer/umbraco-package.js'), import('../../packages/markdown-editor/umbraco-package.js'), diff --git a/src/packages/help/help-header-app.element.ts b/src/packages/help/help-header-app.element.ts new file mode 100644 index 0000000000..e34b0d906b --- /dev/null +++ b/src/packages/help/help-header-app.element.ts @@ -0,0 +1,21 @@ +import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; + +const elementName = 'umb-help-header-app'; +@customElement(elementName) +export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { + override render() { + return html`
My Header App
`; + } + + static override styles: CSSResultGroup = [UmbHeaderAppButtonElement.styles, css``]; +} + +export { UmbHelpHeaderAppElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbHelpHeaderAppElement; + } +} diff --git a/src/packages/help/manifests.ts b/src/packages/help/manifests.ts new file mode 100644 index 0000000000..9504557d0d --- /dev/null +++ b/src/packages/help/manifests.ts @@ -0,0 +1,16 @@ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'headerApp', + alias: 'Umb.HeaderApp.Help', + name: 'Help Header App', + element: () => import('./help-header-app.element.js'), + weight: 0, + meta: { + label: 'TODO: how should we enable this to not be set.', + icon: 'TODO: how should we enable this to not be set.', + pathname: 'help', + }, + }, +]; diff --git a/src/packages/help/umbraco-package.ts b/src/packages/help/umbraco-package.ts new file mode 100644 index 0000000000..bbf3a996b9 --- /dev/null +++ b/src/packages/help/umbraco-package.ts @@ -0,0 +1,9 @@ +export const name = 'Umbraco.Core.Help'; +export const extensions = [ + { + name: 'Help Bundle', + alias: 'Umb.Bundle.Help', + type: 'bundle', + js: () => import('./manifests.js'), + }, +]; diff --git a/src/packages/help/vite.config.ts b/src/packages/help/vite.config.ts new file mode 100644 index 0000000000..a320e9a053 --- /dev/null +++ b/src/packages/help/vite.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vite'; +import { rmSync } from 'fs'; +import { getDefaultConfig } from '../../vite-config-base'; + +const dist = '../../../dist-cms/packages/help'; + +// delete the unbundled dist folder +rmSync(dist, { recursive: true, force: true }); + +export default defineConfig({ + ...getDefaultConfig({ dist, entry: ['manifests.ts', 'umbraco-package.ts'] }), +}); From fc0f5c84ec5022d907bce8f9ad7fb9a4c6691206 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 18:04:44 +0200 Subject: [PATCH 096/322] render button with icon --- src/packages/help/help-header-app.element.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/packages/help/help-header-app.element.ts b/src/packages/help/help-header-app.element.ts index e34b0d906b..bafddc24b0 100644 --- a/src/packages/help/help-header-app.element.ts +++ b/src/packages/help/help-header-app.element.ts @@ -6,7 +6,11 @@ const elementName = 'umb-help-header-app'; @customElement(elementName) export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { override render() { - return html`
My Header App
`; + return html` + + + + `; } static override styles: CSSResultGroup = [UmbHeaderAppButtonElement.styles, css``]; From 67ed209ba7b6eab8e44afae9096ad48a6fe9ed68 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 19:07:43 +0200 Subject: [PATCH 097/322] split into header app and menu + register two menu items --- .../header-app/help-header-app.element.ts | 48 +++++++++++++++++++ src/packages/help/header-app/manifests.ts | 11 +++++ src/packages/help/help-header-app.element.ts | 25 ---------- src/packages/help/manifests.ts | 17 ++----- src/packages/help/menu/constants.ts | 1 + src/packages/help/menu/index.ts | 1 + src/packages/help/menu/manifests.ts | 32 +++++++++++++ 7 files changed, 96 insertions(+), 39 deletions(-) create mode 100644 src/packages/help/header-app/help-header-app.element.ts create mode 100644 src/packages/help/header-app/manifests.ts delete mode 100644 src/packages/help/help-header-app.element.ts create mode 100644 src/packages/help/menu/constants.ts create mode 100644 src/packages/help/menu/index.ts create mode 100644 src/packages/help/menu/manifests.ts diff --git a/src/packages/help/header-app/help-header-app.element.ts b/src/packages/help/header-app/help-header-app.element.ts new file mode 100644 index 0000000000..7b0b767d13 --- /dev/null +++ b/src/packages/help/header-app/help-header-app.element.ts @@ -0,0 +1,48 @@ +import { UMB_HELP_MENU_ALIAS } from '../menu/index.js'; +import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; +import type { ManifestMenu } from '@umbraco-cms/backoffice/extension-registry'; + +const elementName = 'umb-help-header-app'; +@customElement(elementName) +export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { + @state() + private _popoverOpen = false; + + #onPopoverToggle(event: ToggleEvent) { + // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this._popoverOpen = event.newState === 'open'; + } + + override render() { + return html` + + + + + + + + + + + + `; + } + + static override styles: CSSResultGroup = [UmbHeaderAppButtonElement.styles, css``]; +} + +export { UmbHelpHeaderAppElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbHelpHeaderAppElement; + } +} diff --git a/src/packages/help/header-app/manifests.ts b/src/packages/help/header-app/manifests.ts new file mode 100644 index 0000000000..46bb441c2c --- /dev/null +++ b/src/packages/help/header-app/manifests.ts @@ -0,0 +1,11 @@ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'headerApp', + alias: 'Umb.HeaderApp.Help', + name: 'Help Header App', + element: () => import('./help-header-app.element.js'), + weight: 500, + }, +]; diff --git a/src/packages/help/help-header-app.element.ts b/src/packages/help/help-header-app.element.ts deleted file mode 100644 index bafddc24b0..0000000000 --- a/src/packages/help/help-header-app.element.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; - -const elementName = 'umb-help-header-app'; -@customElement(elementName) -export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { - override render() { - return html` - - - - `; - } - - static override styles: CSSResultGroup = [UmbHeaderAppButtonElement.styles, css``]; -} - -export { UmbHelpHeaderAppElement as element }; - -declare global { - interface HTMLElementTagNameMap { - [elementName]: UmbHelpHeaderAppElement; - } -} diff --git a/src/packages/help/manifests.ts b/src/packages/help/manifests.ts index 9504557d0d..223544e6db 100644 --- a/src/packages/help/manifests.ts +++ b/src/packages/help/manifests.ts @@ -1,16 +1,5 @@ +import { manifests as headerAppManifests } from './header-app/manifests.js'; +import { manifests as menuManifests } from './menu/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ - { - type: 'headerApp', - alias: 'Umb.HeaderApp.Help', - name: 'Help Header App', - element: () => import('./help-header-app.element.js'), - weight: 0, - meta: { - label: 'TODO: how should we enable this to not be set.', - icon: 'TODO: how should we enable this to not be set.', - pathname: 'help', - }, - }, -]; +export const manifests: Array = [...menuManifests, ...headerAppManifests]; diff --git a/src/packages/help/menu/constants.ts b/src/packages/help/menu/constants.ts new file mode 100644 index 0000000000..cae4c017c3 --- /dev/null +++ b/src/packages/help/menu/constants.ts @@ -0,0 +1 @@ +export const UMB_HELP_MENU_ALIAS = 'Umb.Menu.Help'; diff --git a/src/packages/help/menu/index.ts b/src/packages/help/menu/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/help/menu/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/help/menu/manifests.ts b/src/packages/help/menu/manifests.ts new file mode 100644 index 0000000000..06cab3d506 --- /dev/null +++ b/src/packages/help/menu/manifests.ts @@ -0,0 +1,32 @@ +import { UMB_HELP_MENU_ALIAS } from './constants.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'menu', + alias: UMB_HELP_MENU_ALIAS, + name: 'Help Menu', + }, + { + type: 'menuItem', + alias: 'Umb.MenuItem.Help.LearningBase', + name: 'Learning Base Help Menu Item', + weight: 200, + meta: { + label: 'Umbraco Learning Base', + icon: 'icon-movie-alt', + menus: [UMB_HELP_MENU_ALIAS], + }, + }, + { + type: 'menuItem', + alias: 'Umb.MenuItem.Help.CommunityWebsite', + name: 'Community Website Help Menu Item', + weight: 100, + meta: { + label: 'Community Website', + icon: 'icon-hearts', + menus: [UMB_HELP_MENU_ALIAS], + }, + }, +]; From f1d442faa7f13ab567e2e21b36989751269c9ac1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 21:43:54 +0200 Subject: [PATCH 098/322] register user sidebar menu --- src/packages/settings/advanced/manifests.ts | 6 ++-- src/packages/user/manifests.ts | 2 +- .../{user-section => section}/constants.ts | 0 .../user/{user-section => section}/index.ts | 0 src/packages/user/section/manifests.ts | 31 +++++++++++++++++++ src/packages/user/section/menu/constants.ts | 1 + src/packages/user/section/menu/index.ts | 1 + src/packages/user/section/menu/manifests.ts | 9 ++++++ .../user/section/sidebar-app/index.ts | 1 + .../user/section/sidebar-app/manifests.ts | 23 ++++++++++++++ .../user/user-group/section-view/manifests.ts | 2 +- src/packages/user/user-section/manifests.ts | 21 ------------- .../user/user/section-view/manifests.ts | 2 +- 13 files changed, 72 insertions(+), 27 deletions(-) rename src/packages/user/{user-section => section}/constants.ts (100%) rename src/packages/user/{user-section => section}/index.ts (100%) create mode 100644 src/packages/user/section/manifests.ts create mode 100644 src/packages/user/section/menu/constants.ts create mode 100644 src/packages/user/section/menu/index.ts create mode 100644 src/packages/user/section/menu/manifests.ts create mode 100644 src/packages/user/section/sidebar-app/index.ts create mode 100644 src/packages/user/section/sidebar-app/manifests.ts delete mode 100644 src/packages/user/user-section/manifests.ts diff --git a/src/packages/settings/advanced/manifests.ts b/src/packages/settings/advanced/manifests.ts index 5a452d9e3d..3931a9edb9 100644 --- a/src/packages/settings/advanced/manifests.ts +++ b/src/packages/settings/advanced/manifests.ts @@ -10,11 +10,11 @@ export const manifests = [ { type: 'sectionSidebarApp', kind: 'menu', - alias: 'Umb.SectionSidebarMenu.AdvancedSettings', - name: 'Advanced Settings Sidebar Menu', + alias: 'Umb.SectionSidebarApp.Menu.Users', + name: 'Users Section Sidebar Menu', weight: 100, meta: { - label: '#treeHeaders_advancedGroup', + label: 'Users', menu: UMB_ADVANCED_SETTINGS_MENU_ALIAS, }, conditions: [ diff --git a/src/packages/user/manifests.ts b/src/packages/user/manifests.ts index 96353d28f7..d649d8f06f 100644 --- a/src/packages/user/manifests.ts +++ b/src/packages/user/manifests.ts @@ -1,6 +1,6 @@ import { manifests as userGroupManifests } from './user-group/manifests.js'; import { manifests as userManifests } from './user/manifests.js'; -import { manifests as userSectionManifests } from './user-section/manifests.js'; +import { manifests as userSectionManifests } from './section/manifests.js'; import { manifests as currentUserManifests } from './current-user/manifests.js'; import { manifests as userPermissionManifests } from './user-permission/manifests.js'; import { manifests as changePasswordManifests } from './change-password/manifests.js'; diff --git a/src/packages/user/user-section/constants.ts b/src/packages/user/section/constants.ts similarity index 100% rename from src/packages/user/user-section/constants.ts rename to src/packages/user/section/constants.ts diff --git a/src/packages/user/user-section/index.ts b/src/packages/user/section/index.ts similarity index 100% rename from src/packages/user/user-section/index.ts rename to src/packages/user/section/index.ts diff --git a/src/packages/user/section/manifests.ts b/src/packages/user/section/manifests.ts new file mode 100644 index 0000000000..bb49da5322 --- /dev/null +++ b/src/packages/user/section/manifests.ts @@ -0,0 +1,31 @@ +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from './constants.js'; +import { manifests as sectionSidebarAppManifests } from './sidebar-app/manifests.js'; +import { manifests as menuManifests } from './menu/manifests.js'; +import type { + ManifestSection, + ManifestTypes, + UmbBackofficeManifestKind, +} from '@umbraco-cms/backoffice/extension-registry'; + +const section: ManifestSection = { + type: 'section', + alias: UMB_USER_MANAGEMENT_SECTION_ALIAS, + name: 'User Management Section', + weight: 600, + meta: { + label: '#sections_users', + pathname: 'user-management', + }, + conditions: [ + { + alias: 'Umb.Condition.SectionUserPermission', + match: UMB_USER_MANAGEMENT_SECTION_ALIAS, + }, + ], +}; + +export const manifests: Array = [ + section, + ...sectionSidebarAppManifests, + ...menuManifests, +]; diff --git a/src/packages/user/section/menu/constants.ts b/src/packages/user/section/menu/constants.ts new file mode 100644 index 0000000000..7bf050d53c --- /dev/null +++ b/src/packages/user/section/menu/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_MANAGEMENT_MENU_ALIAS = 'Umb.Menu.UserManagement'; diff --git a/src/packages/user/section/menu/index.ts b/src/packages/user/section/menu/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/user/section/menu/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/user/section/menu/manifests.ts b/src/packages/user/section/menu/manifests.ts new file mode 100644 index 0000000000..f5852aa534 --- /dev/null +++ b/src/packages/user/section/menu/manifests.ts @@ -0,0 +1,9 @@ +import { UMB_USER_MANAGEMENT_MENU_ALIAS } from './constants.js'; + +export const manifests = [ + { + type: 'menu', + alias: UMB_USER_MANAGEMENT_MENU_ALIAS, + name: 'User Management Menu', + }, +]; diff --git a/src/packages/user/section/sidebar-app/index.ts b/src/packages/user/section/sidebar-app/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/user/section/sidebar-app/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/user/section/sidebar-app/manifests.ts b/src/packages/user/section/sidebar-app/manifests.ts new file mode 100644 index 0000000000..f21d698bc2 --- /dev/null +++ b/src/packages/user/section/sidebar-app/manifests.ts @@ -0,0 +1,23 @@ +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../constants.js'; +import { UMB_USER_MANAGEMENT_MENU_ALIAS } from '../menu/index.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'sectionSidebarApp', + kind: 'menu', + alias: 'Umb.SectionSidebarApp.Menu.UserManagement', + name: 'User Management Menu Sidebar App', + weight: 100, + meta: { + label: '#treeHeaders_users', + menu: UMB_USER_MANAGEMENT_MENU_ALIAS, + }, + conditions: [ + { + alias: 'Umb.Condition.SectionAlias', + match: UMB_USER_MANAGEMENT_SECTION_ALIAS, + }, + ], + }, +]; diff --git a/src/packages/user/user-group/section-view/manifests.ts b/src/packages/user/user-group/section-view/manifests.ts index 3780224244..f4549d458f 100644 --- a/src/packages/user/user-group/section-view/manifests.ts +++ b/src/packages/user/user-group/section-view/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../user-section/index.js'; +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/index.js'; import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; const sectionsViews: Array = [ diff --git a/src/packages/user/user-section/manifests.ts b/src/packages/user/user-section/manifests.ts deleted file mode 100644 index 74bb597e28..0000000000 --- a/src/packages/user/user-section/manifests.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from './constants.js'; -import type { ManifestSection, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; - -const section: ManifestSection = { - type: 'section', - alias: UMB_USER_MANAGEMENT_SECTION_ALIAS, - name: 'User Management Section', - weight: 600, - meta: { - label: '#sections_users', - pathname: 'user-management', - }, - conditions: [ - { - alias: 'Umb.Condition.SectionUserPermission', - match: UMB_USER_MANAGEMENT_SECTION_ALIAS, - }, - ], -}; - -export const manifests: Array = [section]; diff --git a/src/packages/user/user/section-view/manifests.ts b/src/packages/user/user/section-view/manifests.ts index a9dbcd430b..8af99c6b24 100644 --- a/src/packages/user/user/section-view/manifests.ts +++ b/src/packages/user/user/section-view/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../user-section/index.js'; +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/index.js'; import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; const sectionsViews: Array = [ From 1e3f82f75f8d660e17c230e65d8ae53cc76ebc79 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 21:56:10 +0200 Subject: [PATCH 099/322] register root workspace --- src/packages/user/user/manifests.ts | 7 +- src/packages/user/user/menu-item/manifests.ts | 18 +++++ .../user/user/section-view/manifests.ts | 27 +++----- .../user-root-workspace-view.element.ts | 21 ++++++ .../users-section-view.element.ts | 67 ------------------- 5 files changed, 52 insertions(+), 88 deletions(-) create mode 100644 src/packages/user/user/menu-item/manifests.ts create mode 100644 src/packages/user/user/section-view/user-root-workspace-view.element.ts delete mode 100644 src/packages/user/user/section-view/users-section-view.element.ts diff --git a/src/packages/user/user/manifests.ts b/src/packages/user/user/manifests.ts index a5eb9bfeea..88fe76cfcd 100644 --- a/src/packages/user/user/manifests.ts +++ b/src/packages/user/user/manifests.ts @@ -8,9 +8,11 @@ import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import { manifests as menuItemManifests } from './menu-item/manifests.js'; -export const manifests: Array = [ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ ...collectionManifests, ...conditionsManifests, ...entityActionsManifests, @@ -21,4 +23,5 @@ export const manifests: Array = [ ...sectionViewManifests, ...propertyEditorManifests, ...workspaceManifests, + ...menuItemManifests, ]; diff --git a/src/packages/user/user/menu-item/manifests.ts b/src/packages/user/user/menu-item/manifests.ts new file mode 100644 index 0000000000..2239c2fe0f --- /dev/null +++ b/src/packages/user/user/menu-item/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_USER_MANAGEMENT_MENU_ALIAS } from '../../section/menu/constants.js'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'menuItem', + alias: 'Umb.MenuItem.Users', + name: 'Users Menu Item', + weight: 100, + meta: { + label: '#treeHeaders_users', + icon: 'icon-user', + entityType: UMB_USER_ROOT_ENTITY_TYPE, + menus: [UMB_USER_MANAGEMENT_MENU_ALIAS], + }, + }, +]; diff --git a/src/packages/user/user/section-view/manifests.ts b/src/packages/user/user/section-view/manifests.ts index 8af99c6b24..aef4c6370e 100644 --- a/src/packages/user/user/section-view/manifests.ts +++ b/src/packages/user/user/section-view/manifests.ts @@ -1,25 +1,14 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/index.js'; -import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -const sectionsViews: Array = [ +export const manifests: Array = [ { - type: 'sectionView', - alias: 'Umb.SectionView.Users', - name: 'Users Section View', - js: () => import('./users-section-view.element.js'), - weight: 200, + type: 'workspace', + alias: 'Umb.Workspace.UserRoot', + name: 'User Root Workspace View', + element: () => import('./user-root-workspace-view.element.js'), meta: { - label: '#general_users', - pathname: 'users', - icon: 'icon-user', + entityType: UMB_USER_ROOT_ENTITY_TYPE, }, - conditions: [ - { - alias: 'Umb.Condition.SectionAlias', - match: UMB_USER_MANAGEMENT_SECTION_ALIAS, - }, - ], }, ]; - -export const manifests: Array = [...sectionsViews]; diff --git a/src/packages/user/user/section-view/user-root-workspace-view.element.ts b/src/packages/user/user/section-view/user-root-workspace-view.element.ts new file mode 100644 index 0000000000..6e286dada3 --- /dev/null +++ b/src/packages/user/user/section-view/user-root-workspace-view.element.ts @@ -0,0 +1,21 @@ +import { UMB_USER_COLLECTION_ALIAS } from '../collection/index.js'; +import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +const elementName = 'umb-user-root-workspace'; +@customElement(elementName) +export class UmbUserRootWorkspaceElement extends UmbLitElement { + override render() { + return html` + ; + `; + } +} + +export { UmbUserRootWorkspaceElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserRootWorkspaceElement; + } +} diff --git a/src/packages/user/user/section-view/users-section-view.element.ts b/src/packages/user/user/section-view/users-section-view.element.ts deleted file mode 100644 index 22f9d5069d..0000000000 --- a/src/packages/user/user/section-view/users-section-view.element.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { UMB_USER_COLLECTION_ALIAS } from '../collection/index.js'; -import { UMB_USER_ENTITY_TYPE, UMB_USER_ROOT_ENTITY_TYPE } from '../entity.js'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbRoute } from '@umbraco-cms/backoffice/router'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbCollectionElement } from '@umbraco-cms/backoffice/collection'; -import { UmbWorkspaceElement } from '@umbraco-cms/backoffice/workspace'; -import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; - -@customElement('umb-section-view-users') -export class UmbSectionViewUsersElement extends UmbLitElement { - #routes: UmbRoute[] = [ - { - path: 'collection', - component: () => { - const element = new UmbCollectionElement(); - const entityContext = new UmbEntityContext(element); - entityContext.setEntityType(UMB_USER_ROOT_ENTITY_TYPE); - entityContext.setUnique(null); - element.setAttribute('alias', UMB_USER_COLLECTION_ALIAS); - return element; - }, - }, - { - path: 'user', - component: () => { - const element = new UmbWorkspaceElement(); - element.setAttribute('entity-type', UMB_USER_ENTITY_TYPE); - return element; - }, - }, - { - path: '', - redirectTo: 'collection', - }, - { - path: `**`, - component: async () => (await import('@umbraco-cms/backoffice/router')).UmbRouteNotFoundElement, - }, - ]; - - override render() { - return html` `; - } - - static override styles = [ - UmbTextStyles, - css` - :host { - height: 100%; - } - - #router-slot { - height: calc(100% - var(--umb-header-layout-height)); - } - `, - ]; -} - -export default UmbSectionViewUsersElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-section-view-users': UmbSectionViewUsersElement; - } -} From 28aa71bb07cfb87c911cda6e9ed1311e680b57af Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 08:53:01 +0200 Subject: [PATCH 100/322] register user group menu item --- src/packages/user/user-group/entity.ts | 2 + src/packages/user/user-group/manifests.ts | 19 +++--- .../user/user-group/menu-item/manifests.ts | 18 ++++++ .../user/user-group/section-view/manifests.ts | 27 +++----- .../user-group-root-workspace.element.ts | 21 +++++++ .../user-group-section-view.element.ts | 63 ------------------- src/packages/user/user/menu-item/manifests.ts | 2 +- .../user/user/section-view/manifests.ts | 2 +- ...ment.ts => user-root-workspace.element.ts} | 0 9 files changed, 62 insertions(+), 92 deletions(-) create mode 100644 src/packages/user/user-group/menu-item/manifests.ts create mode 100644 src/packages/user/user-group/section-view/user-group-root-workspace.element.ts delete mode 100644 src/packages/user/user-group/section-view/user-group-section-view.element.ts rename src/packages/user/user/section-view/{user-root-workspace-view.element.ts => user-root-workspace.element.ts} (100%) diff --git a/src/packages/user/user-group/entity.ts b/src/packages/user/user-group/entity.ts index 40fc592fed..3978bfa6a5 100644 --- a/src/packages/user/user-group/entity.ts +++ b/src/packages/user/user-group/entity.ts @@ -1,3 +1,5 @@ export const UMB_USER_GROUP_ENTITY_TYPE = 'user-group'; +export const UMB_USER_GROUP_ROOT_ENTITY_TYPE = 'user-group-root'; export type UmbUserGroupEntityType = typeof UMB_USER_GROUP_ENTITY_TYPE; +export type UmbUserGroupRootEntityType = typeof UMB_USER_GROUP_ROOT_ENTITY_TYPE; diff --git a/src/packages/user/user-group/manifests.ts b/src/packages/user/user-group/manifests.ts index 4a03fbb339..1ac88d4e75 100644 --- a/src/packages/user/user-group/manifests.ts +++ b/src/packages/user/user-group/manifests.ts @@ -1,18 +1,21 @@ import { manifests as collectionManifests } from './collection/manifests.js'; -import { manifests as repositoryManifests } from './repository/manifests.js'; -import { manifests as workspaceManifests } from './workspace/manifests.js'; -import { manifests as modalManifests } from './modals/manifests.js'; -import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as entityActionManifests } from './entity-actions/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-actions/manifests.js'; +import { manifests as menuItemManifests } from './menu-item/manifests.js'; +import { manifests as modalManifests } from './modals/manifests.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import { manifests as sectionViewManifests } from './section-view/manifests.js'; +import { manifests as workspaceManifests } from './workspace/manifests.js'; + import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ ...collectionManifests, - ...repositoryManifests, - ...workspaceManifests, - ...modalManifests, - ...sectionViewManifests, ...entityActionManifests, ...entityBulkActionManifests, + ...menuItemManifests, + ...modalManifests, + ...repositoryManifests, + ...sectionViewManifests, + ...workspaceManifests, ]; diff --git a/src/packages/user/user-group/menu-item/manifests.ts b/src/packages/user/user-group/menu-item/manifests.ts new file mode 100644 index 0000000000..1c770acdae --- /dev/null +++ b/src/packages/user/user-group/menu-item/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_USER_MANAGEMENT_MENU_ALIAS } from '../../section/menu/constants.js'; +import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'menuItem', + alias: 'Umb.MenuItem.UserGroups', + name: 'User Groups Menu Item', + weight: 100, + meta: { + label: '#user_usergroups', + icon: 'icon-users', + entityType: UMB_USER_GROUP_ROOT_ENTITY_TYPE, + menus: [UMB_USER_MANAGEMENT_MENU_ALIAS], + }, + }, +]; diff --git a/src/packages/user/user-group/section-view/manifests.ts b/src/packages/user/user-group/section-view/manifests.ts index f4549d458f..ade0536011 100644 --- a/src/packages/user/user-group/section-view/manifests.ts +++ b/src/packages/user/user-group/section-view/manifests.ts @@ -1,25 +1,14 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/index.js'; -import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -const sectionsViews: Array = [ +export const manifests: Array = [ { - type: 'sectionView', - alias: 'Umb.SectionView.UserGroup', - name: 'User Group Section View', - js: () => import('./user-group-section-view.element.js'), - weight: 100, + type: 'workspace', + alias: 'Umb.Workspace.UserGroupRoot', + name: 'User Group Root Workspace View', + element: () => import('./user-group-root-workspace.element.js'), meta: { - label: '#user_usergroups', - pathname: 'user-groups', - icon: 'icon-users', + entityType: UMB_USER_GROUP_ROOT_ENTITY_TYPE, }, - conditions: [ - { - alias: 'Umb.Condition.SectionAlias', - match: UMB_USER_MANAGEMENT_SECTION_ALIAS, - }, - ], }, ]; - -export const manifests: Array = [...sectionsViews]; diff --git a/src/packages/user/user-group/section-view/user-group-root-workspace.element.ts b/src/packages/user/user-group/section-view/user-group-root-workspace.element.ts new file mode 100644 index 0000000000..f02687d62d --- /dev/null +++ b/src/packages/user/user-group/section-view/user-group-root-workspace.element.ts @@ -0,0 +1,21 @@ +import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../collection/index.js'; +import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +const elementName = 'umb-user-group-root-workspace'; +@customElement(elementName) +export class UmbUserGroupRootWorkspaceElement extends UmbLitElement { + override render() { + return html` + ; + `; + } +} + +export { UmbUserGroupRootWorkspaceElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserGroupRootWorkspaceElement; + } +} diff --git a/src/packages/user/user-group/section-view/user-group-section-view.element.ts b/src/packages/user/user-group/section-view/user-group-section-view.element.ts deleted file mode 100644 index 4611f0962d..0000000000 --- a/src/packages/user/user-group/section-view/user-group-section-view.element.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../collection/index.js'; -import { UMB_USER_GROUP_ENTITY_TYPE } from '../entity.js'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbRoute } from '@umbraco-cms/backoffice/router'; -import { UmbCollectionElement } from '@umbraco-cms/backoffice/collection'; -import { UmbWorkspaceElement } from '@umbraco-cms/backoffice/workspace'; - -@customElement('umb-user-group-section-view') -export class UmbUserGroupSectionViewElement extends UmbLitElement { - #routes: UmbRoute[] = [ - { - path: 'collection', - component: () => { - const element = new UmbCollectionElement(); - element.setAttribute('alias', UMB_USER_GROUP_COLLECTION_ALIAS); - return element; - }, - }, - { - path: 'user-group', - component: () => { - const element = new UmbWorkspaceElement(); - element.setAttribute('entity-type', UMB_USER_GROUP_ENTITY_TYPE); - return element; - }, - }, - { - path: '', - redirectTo: 'collection', - }, - { - path: `**`, - component: async () => (await import('@umbraco-cms/backoffice/router')).UmbRouteNotFoundElement, - }, - ]; - - override render() { - return html``; - } - - static override styles = [ - UmbTextStyles, - css` - :host { - height: 100%; - } - - #router-slot { - height: calc(100% - var(--umb-header-layout-height)); - } - `, - ]; -} - -export default UmbUserGroupSectionViewElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-user-group-section-view': UmbUserGroupSectionViewElement; - } -} diff --git a/src/packages/user/user/menu-item/manifests.ts b/src/packages/user/user/menu-item/manifests.ts index 2239c2fe0f..c1980c58ef 100644 --- a/src/packages/user/user/menu-item/manifests.ts +++ b/src/packages/user/user/menu-item/manifests.ts @@ -7,7 +7,7 @@ export const manifests: Array = [ type: 'menuItem', alias: 'Umb.MenuItem.Users', name: 'Users Menu Item', - weight: 100, + weight: 200, meta: { label: '#treeHeaders_users', icon: 'icon-user', diff --git a/src/packages/user/user/section-view/manifests.ts b/src/packages/user/user/section-view/manifests.ts index aef4c6370e..96eea28eda 100644 --- a/src/packages/user/user/section-view/manifests.ts +++ b/src/packages/user/user/section-view/manifests.ts @@ -6,7 +6,7 @@ export const manifests: Array = [ type: 'workspace', alias: 'Umb.Workspace.UserRoot', name: 'User Root Workspace View', - element: () => import('./user-root-workspace-view.element.js'), + element: () => import('./user-root-workspace.element.js'), meta: { entityType: UMB_USER_ROOT_ENTITY_TYPE, }, diff --git a/src/packages/user/user/section-view/user-root-workspace-view.element.ts b/src/packages/user/user/section-view/user-root-workspace.element.ts similarity index 100% rename from src/packages/user/user/section-view/user-root-workspace-view.element.ts rename to src/packages/user/user/section-view/user-root-workspace.element.ts From af2b663b0569a527dc3dccc25ec059735cad92b6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 08:53:36 +0200 Subject: [PATCH 101/322] add link menu item kind --- .../core/extension-registry/models/index.ts | 3 +- .../models/menu-item.model.ts | 10 +++++++ src/packages/core/manifests.ts | 2 ++ .../menu-item-layout.element.ts | 11 +++++++- .../menu-item/link/link-menu-item.element.ts | 28 +++++++++++++++++++ .../components/menu-item/link/manifests.ts | 14 ++++++++++ .../menu/components/menu-item/manifests.ts | 4 +++ src/packages/core/menu/manifests.ts | 4 +++ src/packages/help/menu/manifests.ts | 8 ++++-- 9 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 src/packages/core/menu/components/menu-item/link/link-menu-item.element.ts create mode 100644 src/packages/core/menu/components/menu-item/link/manifests.ts create mode 100644 src/packages/core/menu/components/menu-item/manifests.ts create mode 100644 src/packages/core/menu/manifests.ts diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts index adc53de04c..278207f19a 100644 --- a/src/packages/core/extension-registry/models/index.ts +++ b/src/packages/core/extension-registry/models/index.ts @@ -30,7 +30,7 @@ import type { ManifestHealthCheck } from './health-check.model.js'; import type { ManifestIcons } from './icons.model.js'; import type { ManifestLocalization } from './localization.model.js'; import type { ManifestMenu } from './menu.model.js'; -import type { ManifestMenuItem, ManifestMenuItemTreeKind } from './menu-item.model.js'; +import type { ManifestMenuItem, ManifestMenuItemLinkKind, ManifestMenuItemTreeKind } from './menu-item.model.js'; import type { ManifestModal } from './modal.model.js'; import type { ManifestPackageView } from './package-view.model.js'; import type { ManifestPreviewAppProvider } from './preview-app.model.js'; @@ -186,6 +186,7 @@ export type ManifestTypes = | ManifestMenu | ManifestMenuItem | ManifestMenuItemTreeKind + | ManifestMenuItemLinkKind | ManifestMfaLoginProvider | ManifestModal | ManifestMonacoMarkdownEditorAction diff --git a/src/packages/core/extension-registry/models/menu-item.model.ts b/src/packages/core/extension-registry/models/menu-item.model.ts index 05eeb81b78..68f7d2f354 100644 --- a/src/packages/core/extension-registry/models/menu-item.model.ts +++ b/src/packages/core/extension-registry/models/menu-item.model.ts @@ -26,3 +26,13 @@ export interface MetaMenuItemTreeKind extends MetaMenuItem { treeAlias: string; hideTreeRoot?: boolean; } + +export interface ManifestMenuItemLinkKind extends ManifestMenuItem { + type: 'menuItem'; + kind: 'link'; + meta: MetaMenuItemLinkKind; +} + +export interface MetaMenuItemLinkKind extends MetaMenuItem { + href: string; +} diff --git a/src/packages/core/manifests.ts b/src/packages/core/manifests.ts index 893b161f1f..5fc8f5c5a8 100644 --- a/src/packages/core/manifests.ts +++ b/src/packages/core/manifests.ts @@ -9,6 +9,7 @@ import { manifests as entityBulkActionManifests } from './entity-bulk-action/man import { manifests as extensionManifests } from './extension-registry/manifests.js'; import { manifests as iconRegistryManifests } from './icon-registry/manifests.js'; import { manifests as localizationManifests } from './localization/manifests.js'; +import { manifests as menuManifests } from './menu/manifests.js'; import { manifests as modalManifests } from './modal/common/manifests.js'; import { manifests as pickerManifests } from './picker/manifests.js'; import { manifests as propertyActionManifests } from './property-action/manifests.js'; @@ -35,6 +36,7 @@ export const manifests: Array = [ ...extensionManifests, ...iconRegistryManifests, ...localizationManifests, + ...menuManifests, ...modalManifests, ...pickerManifests, ...propertyActionManifests, diff --git a/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts b/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts index e9d7291e34..af64f06949 100644 --- a/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts +++ b/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts @@ -47,6 +47,14 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { #debouncedCheckIsActive = debounce(() => this.#checkIsActive(), 100); + #getTarget() { + if (this.href && this.href.startsWith('http')) { + return '_blank'; + } + + return '_self'; + } + #checkIsActive() { if (!this.href) { this._isActive = false; @@ -63,7 +71,8 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { label=${this.label} .caretLabel=${this.localize.term('visuallyHiddenTexts_expandChildItems') + ' ' + this.label} ?active=${this._isActive} - ?has-children=${this.hasChildren}> + ?has-children=${this.hasChildren} + target=${this.#getTarget()}> ${this.entityType ? html` + + `; + } +} + +export { UmbLinkMenuItemElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbLinkMenuItemElement; + } +} diff --git a/src/packages/core/menu/components/menu-item/link/manifests.ts b/src/packages/core/menu/components/menu-item/link/manifests.ts new file mode 100644 index 0000000000..1645bd2edc --- /dev/null +++ b/src/packages/core/menu/components/menu-item/link/manifests.ts @@ -0,0 +1,14 @@ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'kind', + alias: 'Umb.Kind.MenuItem.Link', + matchKind: 'link', + matchType: 'menuItem', + manifest: { + type: 'menuItem', + element: () => import('./link-menu-item.element.js'), + }, + }, +]; diff --git a/src/packages/core/menu/components/menu-item/manifests.ts b/src/packages/core/menu/components/menu-item/manifests.ts new file mode 100644 index 0000000000..08daa5be16 --- /dev/null +++ b/src/packages/core/menu/components/menu-item/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as linkManifests } from './link/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...linkManifests]; diff --git a/src/packages/core/menu/manifests.ts b/src/packages/core/menu/manifests.ts new file mode 100644 index 0000000000..88cfb7bd3d --- /dev/null +++ b/src/packages/core/menu/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as menuItemManifests } from './components/menu-item/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...menuItemManifests]; diff --git a/src/packages/help/menu/manifests.ts b/src/packages/help/menu/manifests.ts index 06cab3d506..4d9985a5b5 100644 --- a/src/packages/help/menu/manifests.ts +++ b/src/packages/help/menu/manifests.ts @@ -9,24 +9,28 @@ export const manifests: Array = [ }, { type: 'menuItem', + kind: 'link', alias: 'Umb.MenuItem.Help.LearningBase', name: 'Learning Base Help Menu Item', weight: 200, meta: { + menus: [UMB_HELP_MENU_ALIAS], label: 'Umbraco Learning Base', icon: 'icon-movie-alt', - menus: [UMB_HELP_MENU_ALIAS], + href: 'https://learn.umbraco.com', }, }, { type: 'menuItem', + kind: 'link', alias: 'Umb.MenuItem.Help.CommunityWebsite', name: 'Community Website Help Menu Item', weight: 100, meta: { + menus: [UMB_HELP_MENU_ALIAS], label: 'Community Website', icon: 'icon-hearts', - menus: [UMB_HELP_MENU_ALIAS], + href: 'https://our.umbraco.com', }, }, ]; From a8c2077e3d2c3dee53ee1b1f475b05bc830e32e6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 10:04:55 +0200 Subject: [PATCH 102/322] add translations for kind --- src/assets/lang/da-dk.ts | 3 +++ src/assets/lang/en-us.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/assets/lang/da-dk.ts b/src/assets/lang/da-dk.ts index d60320fb16..9e700003cf 100644 --- a/src/assets/lang/da-dk.ts +++ b/src/assets/lang/da-dk.ts @@ -357,6 +357,7 @@ export default { member: { createNewMember: 'Opret et nyt medlem', allMembers: 'Alle medlemmer', + kind: 'Slags', memberGroupNoProperties: 'Medlemgrupper har ingen yderligere egenskaber til redigering.', '2fa': 'Totrinsbekræftelse', duplicateMemberLogin: 'A member with this login already exists', @@ -364,6 +365,8 @@ export default { memberHasPassword: 'The member already has a password set', memberLockoutNotEnabled: 'Lockout is not enabled for this member', memberNotInGroup: "The member is not in group '%0%'", + memberKindDefault: 'Bruger', + memberKindApi: 'API Bruger', }, contentType: { copyFailed: 'Kopiering af indholdstypen fejlede', diff --git a/src/assets/lang/en-us.ts b/src/assets/lang/en-us.ts index 5e0d3f266e..ab6f2027bf 100644 --- a/src/assets/lang/en-us.ts +++ b/src/assets/lang/en-us.ts @@ -364,12 +364,15 @@ export default { createNewMember: 'Create a new member', allMembers: 'All Members', duplicateMemberLogin: 'A member with this login already exists', + kind: 'Kind', memberGroupNoProperties: 'Member groups have no additional properties for editing.', memberHasGroup: "The member is already in group '%0%'", memberHasPassword: 'The member already has a password set', memberLockoutNotEnabled: 'Lockout is not enabled for this member', memberNotInGroup: "The member is not in group '%0%'", '2fa': 'Two-Factor Authentication', + memberKindDefault: 'Member', + memberKindApi: 'API Member', }, contentType: { copyFailed: 'Failed to copy content type', From b16d7f519e920889a8e4f1cfcd2fa80663f980d9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 10:05:04 +0200 Subject: [PATCH 103/322] add kind util --- src/packages/members/member/utils/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/packages/members/member/utils/index.ts diff --git a/src/packages/members/member/utils/index.ts b/src/packages/members/member/utils/index.ts new file mode 100644 index 0000000000..9b691b0035 --- /dev/null +++ b/src/packages/members/member/utils/index.ts @@ -0,0 +1,6 @@ +export type UmbMemberKindType = 'Default' | 'Api'; + +export const UmbMemberKind = Object.freeze({ + DEFAULT: 'Default', + API: 'Api', +}); From 41f3bcb1eb01572684d5205f87a6f529bf418c6c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 10:05:18 +0200 Subject: [PATCH 104/322] add kind to types --- src/packages/members/member/collection/types.ts | 2 ++ src/packages/members/member/repository/item/types.ts | 2 ++ src/packages/members/member/types.ts | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/packages/members/member/collection/types.ts b/src/packages/members/member/collection/types.ts index bb3b83cc3b..46b1c95102 100644 --- a/src/packages/members/member/collection/types.ts +++ b/src/packages/members/member/collection/types.ts @@ -1,4 +1,5 @@ import type { UmbMemberEntityType } from '../entity.js'; +import type { UmbMemberKindType } from '../utils/index.js'; export interface UmbMemberCollectionFilterModel { skip?: number; @@ -11,4 +12,5 @@ export interface UmbMemberCollectionModel { unique: string; entityType: UmbMemberEntityType; variants: Array; + kind: UmbMemberKindType; } diff --git a/src/packages/members/member/repository/item/types.ts b/src/packages/members/member/repository/item/types.ts index 9b58f77ef6..660b7d84fc 100644 --- a/src/packages/members/member/repository/item/types.ts +++ b/src/packages/members/member/repository/item/types.ts @@ -1,4 +1,5 @@ import type { UmbMemberEntityType } from '../../entity.js'; +import type { UmbMemberKindType } from '../../utils/index.js'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; export interface UmbMemberItemModel { @@ -11,6 +12,7 @@ export interface UmbMemberItemModel { collection: UmbReferenceByUnique | null; }; variants: Array; + kind: UmbMemberKindType; } export interface UmbMemberVariantItemModel { diff --git a/src/packages/members/member/types.ts b/src/packages/members/member/types.ts index 0e6c4bfb12..d2c1f1dcaf 100644 --- a/src/packages/members/member/types.ts +++ b/src/packages/members/member/types.ts @@ -1,4 +1,5 @@ import type { UmbMemberEntityType } from './entity.js'; +import type { UmbMemberKindType } from './utils/index.js'; import type { UmbVariantModel, UmbVariantOptionModel } from '@umbraco-cms/backoffice/variant'; export interface UmbMemberDetailModel { @@ -9,6 +10,7 @@ export interface UmbMemberDetailModel { isApproved: boolean; isLockedOut: boolean; isTwoFactorEnabled: boolean; + kind: UmbMemberKindType; lastLockoutDate: string | null; lastLoginDate: string | null; lastPasswordChangeDate: string | null; From d58251f809f562b69f582966a47cf309d546f1ba Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 10:05:28 +0200 Subject: [PATCH 105/322] map kind --- .../repository/member-collection.server.data-source.ts | 1 + .../repository/detail/member-detail.server.data-source.ts | 3 +++ .../member/repository/item/member-item.server.data-source.ts | 1 + .../members/member/search/member-search.server.data-source.ts | 1 + 4 files changed, 6 insertions(+) diff --git a/src/packages/members/member/collection/repository/member-collection.server.data-source.ts b/src/packages/members/member/collection/repository/member-collection.server.data-source.ts index 3bfb088260..42376a93c3 100644 --- a/src/packages/members/member/collection/repository/member-collection.server.data-source.ts +++ b/src/packages/members/member/collection/repository/member-collection.server.data-source.ts @@ -50,6 +50,7 @@ export class UmbMemberCollectionServerDataSource implements UmbCollectionDataSou email: item.email, variants: item.variants as UmbVariantModel[], unique: item.id, + kind: item.kind, lastLoginDate: item.lastLoginDate || null, lastLockoutDate: item.lastLockoutDate || null, lastPasswordChangeDate: item.lastPasswordChangeDate || null, diff --git a/src/packages/members/member/repository/detail/member-detail.server.data-source.ts b/src/packages/members/member/repository/detail/member-detail.server.data-source.ts index 37303524ae..169e8e65fd 100644 --- a/src/packages/members/member/repository/detail/member-detail.server.data-source.ts +++ b/src/packages/members/member/repository/detail/member-detail.server.data-source.ts @@ -6,6 +6,7 @@ import type { CreateMemberRequestModel, UpdateMemberRequestModel } from '@umbrac import { MemberService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { UmbMemberKind } from '../../utils/index.js'; /** * A data source for the Member that fetches data from the server @@ -42,6 +43,7 @@ export class UmbMemberServerDataSource implements UmbDetailDataSource { entityType: UMB_MEMBER_ENTITY_TYPE, unique: item.id, name: item.variants[0].name || '', + kind: item.kind, memberType: { unique: item.memberType.id, icon: item.memberType.icon, diff --git a/src/packages/members/member/search/member-search.server.data-source.ts b/src/packages/members/member/search/member-search.server.data-source.ts index 4c8d4acdaf..febcdd024c 100644 --- a/src/packages/members/member/search/member-search.server.data-source.ts +++ b/src/packages/members/member/search/member-search.server.data-source.ts @@ -43,6 +43,7 @@ export class UmbMemberSearchServerDataSource implements UmbSearchDataSource Date: Tue, 10 Sep 2024 10:06:45 +0200 Subject: [PATCH 106/322] show kind in table --- .../table/member-table-collection-view.element.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts b/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts index ea755050bc..bc81f76e4e 100644 --- a/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts +++ b/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts @@ -1,6 +1,7 @@ import type { UmbMemberCollectionModel } from '../../types.js'; import { UMB_MEMBER_COLLECTION_CONTEXT } from '../../member-collection.context-token.js'; import type { UmbMemberCollectionContext } from '../../member-collection.context.js'; +import { UmbMemberKind } from '../../../utils/index.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbTableColumn, UmbTableConfig, UmbTableItem } from '@umbraco-cms/backoffice/components'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; @@ -19,6 +20,10 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { name: this.localize.term('general_name'), alias: 'memberName', }, + { + name: this.localize.term('member_kind'), + alias: 'memberKind', + }, ]; @state() @@ -44,6 +49,10 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { this._tableItems = members.map((member) => { // TODO: get correct variant name const name = member.variants[0].name; + const kind = + member.kind === UmbMemberKind.API + ? this.localize.term('member_memberKindApi') + : this.localize.term('member_memberKindDefault'); return { id: member.unique, @@ -53,6 +62,10 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { columnAlias: 'memberName', value: html`${name}`, }, + { + columnAlias: 'memberKind', + value: kind, + }, ], }; }); From 0613b1775c0a78629b89c8ee18c209019dac43e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 10 Sep 2024 10:51:30 +0200 Subject: [PATCH 107/322] style update --- .../user/user/components/user-avatar/user-avatar.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/packages/user/user/components/user-avatar/user-avatar.element.ts index e36bf586a7..fb144b6a93 100644 --- a/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -118,7 +118,7 @@ export class UmbUserAvatarElement extends UmbLitElement { css` uui-avatar { background-color: transparent; - border: 1.5px solid var(--uui-color-divider-standalone); + border: 1.5px solid var(--uui-color-border); color: inherit; } @@ -127,7 +127,7 @@ export class UmbUserAvatarElement extends UmbLitElement { } uui-avatar.api { - border-radius: var(--uui-border-radius); + border-radius: 9%; } `, ]; From 8a65a8bd2cda8d20bd292a4261752eb100b0deef Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 12:16:48 +0200 Subject: [PATCH 108/322] show username and email in table --- src/packages/members/member/collection/types.ts | 11 +++-------- .../member-table-collection-view.element.ts | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/packages/members/member/collection/types.ts b/src/packages/members/member/collection/types.ts index 46b1c95102..76018d2a04 100644 --- a/src/packages/members/member/collection/types.ts +++ b/src/packages/members/member/collection/types.ts @@ -1,5 +1,4 @@ -import type { UmbMemberEntityType } from '../entity.js'; -import type { UmbMemberKindType } from '../utils/index.js'; +import type { UmbMemberDetailModel } from '../types.js'; export interface UmbMemberCollectionFilterModel { skip?: number; @@ -8,9 +7,5 @@ export interface UmbMemberCollectionFilterModel { filter?: string; } -export interface UmbMemberCollectionModel { - unique: string; - entityType: UmbMemberEntityType; - variants: Array; - kind: UmbMemberKindType; -} +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbMemberCollectionModel extends UmbMemberDetailModel {} diff --git a/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts b/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts index bc81f76e4e..04578cacd3 100644 --- a/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts +++ b/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts @@ -20,6 +20,14 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { name: this.localize.term('general_name'), alias: 'memberName', }, + { + name: this.localize.term('general_username'), + alias: 'memberUsername', + }, + { + name: this.localize.term('general_email'), + alias: 'memberEmail', + }, { name: this.localize.term('member_kind'), alias: 'memberKind', @@ -46,6 +54,7 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { } #createTableItems(members: Array) { + console.log('members', members); this._tableItems = members.map((member) => { // TODO: get correct variant name const name = member.variants[0].name; @@ -62,6 +71,14 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { columnAlias: 'memberName', value: html`${name}`, }, + { + columnAlias: 'memberUsername', + value: member.username, + }, + { + columnAlias: 'memberEmail', + value: member.email, + }, { columnAlias: 'memberKind', value: kind, From 7bbbfa8bc6698175a3b943ddb392ad8b3c270213 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 12:40:27 +0200 Subject: [PATCH 109/322] fix lint errors --- .../views/info/document-workspace-view-info-history.element.ts | 2 +- .../views/info/media-workspace-view-info-history.element.ts | 2 +- .../user-group/workspace/user-group-workspace-editor.element.ts | 1 - .../user/user/components/user-avatar/user-avatar.element.ts | 1 - .../user/user/workspace/user-workspace-editor.element.ts | 1 - 5 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts b/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts index 9388014614..14802bbeca 100644 --- a/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts +++ b/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts @@ -3,7 +3,7 @@ import type { UmbDocumentAuditLogModel } from '../../../audit-log/types.js'; import { UmbDocumentAuditLogRepository } from '../../../audit-log/index.js'; import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../document-workspace.context-token.js'; import { TimeOptions, getDocumentHistoryTagStyleAndText } from './utils.js'; -import { css, html, customElement, state, nothing, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state, nothing, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; diff --git a/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts b/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts index f13d1de9ac..33ac9a609f 100644 --- a/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts +++ b/src/packages/media/media/workspace/views/info/media-workspace-view-info-history.element.ts @@ -2,7 +2,7 @@ import type { UmbMediaAuditLogModel } from '../../../audit-log/types.js'; import { UmbMediaAuditLogRepository } from '../../../audit-log/index.js'; import { UMB_MEDIA_WORKSPACE_CONTEXT } from '../../media-workspace.context-token.js'; import { TimeOptions, getMediaHistoryTagStyleAndText } from './utils.js'; -import { css, html, customElement, state, nothing, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state, nothing, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbPaginationManager } from '@umbraco-cms/backoffice/utils'; diff --git a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts b/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts index 613d012475..9374872d2a 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts +++ b/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts @@ -1,5 +1,4 @@ import type { UmbUserGroupDetailModel } from '../index.js'; -import { UMB_USER_GROUP_ENTITY_TYPE } from '../index.js'; import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from './user-group-workspace.context-token.js'; import type { UUIBooleanInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; diff --git a/src/packages/user/user/components/user-avatar/user-avatar.element.ts b/src/packages/user/user/components/user-avatar/user-avatar.element.ts index fb144b6a93..44661991dc 100644 --- a/src/packages/user/user/components/user-avatar/user-avatar.element.ts +++ b/src/packages/user/user/components/user-avatar/user-avatar.element.ts @@ -1,7 +1,6 @@ import type { UmbUserKindType } from '../../utils/index.js'; import { UmbUserKind } from '../../utils/index.js'; import type { UUIAvatarElement } from '@umbraco-cms/backoffice/external/uui'; -import type { PropertyValues } from '@umbraco-cms/backoffice/external/lit'; import { css, html, diff --git a/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/packages/user/user/workspace/user-workspace-editor.element.ts index 2526f44b14..c4e11d2175 100644 --- a/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -1,5 +1,4 @@ import type { UmbUserDetailModel } from '../index.js'; -import { UMB_USER_ENTITY_TYPE } from '../entity.js'; import type { UmbUserWorkspaceContext } from './user-workspace.context.js'; import { UMB_USER_WORKSPACE_CONTEXT } from './user-workspace.context-token.js'; import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; From de89c91069ded8a25d0e8da894e09f3ae4e7ee93 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 12:55:06 +0200 Subject: [PATCH 110/322] update import path --- src/packages/user/user-group/paths.ts | 2 +- src/packages/user/user/paths.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/user/user-group/paths.ts b/src/packages/user/user-group/paths.ts index 6fc1f8cc7e..bcd681d6dc 100644 --- a/src/packages/user/user-group/paths.ts +++ b/src/packages/user/user-group/paths.ts @@ -1,4 +1,4 @@ -import { UMB_USER_SECTION_PATHNAME } from '../user-section/paths.js'; +import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js'; import { UMB_USER_GROUP_ENTITY_TYPE } from './entity.js'; import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/packages/user/user/paths.ts b/src/packages/user/user/paths.ts index e9040e7270..eb80086f08 100644 --- a/src/packages/user/user/paths.ts +++ b/src/packages/user/user/paths.ts @@ -1,4 +1,4 @@ -import { UMB_USER_SECTION_PATHNAME } from '../user-section/paths.js'; +import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js'; import { UMB_USER_ENTITY_TYPE } from './entity.js'; import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; From 34ba32b4d80f6f8e0af7c125821c62833134af61 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 13:13:52 +0200 Subject: [PATCH 111/322] align sidebar spacing --- ...mber-workspace-view-member-info.element.ts | 54 +++++++-------- .../member-workspace-view-member.element.ts | 68 +++++++++---------- .../user-workspace-info.element.ts | 26 +++---- 3 files changed, 70 insertions(+), 78 deletions(-) diff --git a/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts b/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts index 2a8b77ddb3..fd5ac87c02 100644 --- a/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts +++ b/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts @@ -70,41 +70,37 @@ export class UmbMemberWorkspaceViewMemberInfoElement extends UmbLitElement imple #renderGeneralSection() { return html` -
- Created - ${this._createDate} -
-
- Last edited - ${this._updateDate} -
-
- Member Type - - - -
-
- Id - ${this._unique} -
+ +
+

Created

+ ${this._createDate} +
+
+

Last edited

+ ${this._updateDate} +
+
+

Member Type

+ + + +
+
+

Id

+ ${this._unique} +
+
`; } static override styles = [ UmbTextStyles, css` - .general-item { - display: flex; - flex-direction: column; - gap: var(--uui-size-space-1); - } - - .general-item:not(:last-child) { - margin-bottom: var(--uui-size-space-6); + h4 { + margin: 0; } `, ]; diff --git a/src/packages/members/member/workspace/views/member/member-workspace-view-member.element.ts b/src/packages/members/member/workspace/views/member/member-workspace-view-member.element.ts index bb33e453b8..8573a9b9c4 100644 --- a/src/packages/members/member/workspace/views/member/member-workspace-view-member.element.ts +++ b/src/packages/members/member/workspace/views/member/member-workspace-view-member.element.ts @@ -208,34 +208,36 @@ export class UmbMemberWorkspaceViewMemberElement extends UmbLitElement implement return html`
-
- Failed login attempts - ${this._workspaceContext.failedPasswordAttempts} -
-
- Last lockout date - - ${this._workspaceContext.lastLockOutDate - ? this.localize.date(this._workspaceContext.lastLockOutDate, TimeFormatOptions) - : this.localize.term('general_never')} - -
-
- Last login - - ${this._workspaceContext.lastLoginDate - ? this.localize.date(this._workspaceContext.lastLoginDate, TimeFormatOptions) - : this.localize.term('general_never')} - -
-
- Password changed - - ${this._workspaceContext.lastPasswordChangeDate - ? this.localize.date(this._workspaceContext.lastPasswordChangeDate, TimeFormatOptions) - : this.localize.term('general_never')} - -
+ +
+

Failed login attempts

+ ${this._workspaceContext.failedPasswordAttempts} +
+
+

Last lockout date

+ + ${this._workspaceContext.lastLockOutDate + ? this.localize.date(this._workspaceContext.lastLockOutDate, TimeFormatOptions) + : this.localize.term('general_never')} + +
+
+

Last login

+ + ${this._workspaceContext.lastLoginDate + ? this.localize.date(this._workspaceContext.lastLoginDate, TimeFormatOptions) + : this.localize.term('general_never')} + +
+
+

Password changed

+ + ${this._workspaceContext.lastPasswordChangeDate + ? this.localize.date(this._workspaceContext.lastPasswordChangeDate, TimeFormatOptions) + : this.localize.term('general_never')} + +
+
@@ -291,14 +293,8 @@ export class UmbMemberWorkspaceViewMemberElement extends UmbLitElement implement color: var(--uui-color-danger); } - .general-item { - display: flex; - flex-direction: column; - gap: var(--uui-size-space-1); - } - - .general-item:not(:last-child) { - margin-bottom: var(--uui-size-space-6); + h4 { + margin: 0; } `, ]; diff --git a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts index 3be3786c98..898bea5823 100644 --- a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts @@ -97,18 +97,20 @@ export class UmbUserWorkspaceInfoElement extends UmbLitElement { #renderInfoList() { return html` - ${repeat( - this._userInfo, - (item) => item.labelKey, - (item) => this.#renderInfoItem(item.labelKey, item.value), - )} + + ${repeat( + this._userInfo, + (item) => item.labelKey, + (item) => this.#renderInfoItem(item.labelKey, item.value), + )} + `; } #renderInfoItem(labelKey: string, value?: string | number) { return html` - +
+

+ ${this._memberKind === UmbMemberKind.API + ? this.localize.term('member_memberKindApi') + : this.localize.term('member_memberKindDefault')} +

Id

${this._unique} From 63897eb8965ba2b7662663e570ee2a0d1527ef00 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 13:51:22 +0200 Subject: [PATCH 114/322] show member type + correct member type icon --- .../member-table-collection-view.element.ts | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts b/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts index 04578cacd3..2c66f2df9f 100644 --- a/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts +++ b/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts @@ -6,6 +6,8 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbTableColumn, UmbTableConfig, UmbTableItem } from '@umbraco-cms/backoffice/components'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbMemberItemRepository } from '../../../repository/index.js'; +import { UmbMemberTypeItemRepository } from '@umbraco-cms/backoffice/member-type'; @customElement('umb-member-table-collection-view') export class UmbMemberTableCollectionViewElement extends UmbLitElement { @@ -28,6 +30,10 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { name: this.localize.term('general_email'), alias: 'memberEmail', }, + { + name: this.localize.term('content_membertype'), + alias: 'memberType', + }, { name: this.localize.term('member_kind'), alias: 'memberKind', @@ -38,6 +44,7 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { private _tableItems: Array = []; #collectionContext?: UmbMemberCollectionContext; + #memberTypeItemRepository = new UmbMemberTypeItemRepository(this); constructor() { super(); @@ -53,8 +60,10 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { this.observe(this.#collectionContext.items, (items) => this.#createTableItems(items), 'umbCollectionItemsObserver'); } - #createTableItems(members: Array) { - console.log('members', members); + async #createTableItems(members: Array) { + const memberTypeUniques = members.map((member) => member.memberType.unique); + const { data: memberTypes } = await this.#memberTypeItemRepository.requestItems(memberTypeUniques); + this._tableItems = members.map((member) => { // TODO: get correct variant name const name = member.variants[0].name; @@ -63,9 +72,11 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { ? this.localize.term('member_memberKindApi') : this.localize.term('member_memberKindDefault'); + const memberType = memberTypes?.find((type) => type.unique === member.memberType.unique); + return { id: member.unique, - icon: 'icon-user', + icon: memberType?.icon, data: [ { columnAlias: 'memberName', @@ -79,6 +90,10 @@ export class UmbMemberTableCollectionViewElement extends UmbLitElement { columnAlias: 'memberEmail', value: member.email, }, + { + columnAlias: 'memberType', + value: memberType?.name, + }, { columnAlias: 'memberKind', value: kind, From 32490de2e2a8698f5780e1e8fd1ae9a82932a2b8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 14:20:19 +0200 Subject: [PATCH 115/322] fix lint errors --- .../views/table/member-table-collection-view.element.ts | 1 - .../views/member/member-workspace-view-member-info.element.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts b/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts index 2c66f2df9f..ed4398313a 100644 --- a/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts +++ b/src/packages/members/member/collection/views/table/member-table-collection-view.element.ts @@ -6,7 +6,6 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbTableColumn, UmbTableConfig, UmbTableItem } from '@umbraco-cms/backoffice/components'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbMemberItemRepository } from '../../../repository/index.js'; import { UmbMemberTypeItemRepository } from '@umbraco-cms/backoffice/member-type'; @customElement('umb-member-table-collection-view') diff --git a/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts b/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts index ddd470dba7..10c8d46ee2 100644 --- a/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts +++ b/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts @@ -1,5 +1,6 @@ // import { UMB_COMPOSITION_PICKER_MODAL, type UmbCompositionPickerModalData } from '../../../modals/index.js'; import { UMB_MEMBER_WORKSPACE_CONTEXT } from '../../member-workspace.context-token.js'; +import type { UmbMemberKindType } from '../../../utils/index.js'; import { TimeFormatOptions } from './utils.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; @@ -8,7 +9,6 @@ import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension- import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbMemberTypeItemRepository } from '@umbraco-cms/backoffice/member-type'; -import { UmbMemberKind, UmbMemberKindType } from '../../../utils/index.js'; @customElement('umb-member-workspace-view-member-info') export class UmbMemberWorkspaceViewMemberInfoElement extends UmbLitElement implements UmbWorkspaceViewElement { From 7784bf7912b613bf3749c47bee0321334fe78269 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 14:31:06 +0200 Subject: [PATCH 116/322] Bump version number --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ac79713592..075d0e1d0a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@umbraco-cms/backoffice", "license": "MIT", - "version": "14.3.0", + "version": "15.0.0", "type": "module", "exports": { ".": null, From 9110151bcdf1b42f8945478168c81a033a3fcc3e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 14:31:25 +0200 Subject: [PATCH 117/322] Update member-workspace-view-member-info.element.ts --- .../views/member/member-workspace-view-member-info.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts b/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts index 10c8d46ee2..4c3d0414c1 100644 --- a/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts +++ b/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts @@ -1,6 +1,6 @@ // import { UMB_COMPOSITION_PICKER_MODAL, type UmbCompositionPickerModalData } from '../../../modals/index.js'; import { UMB_MEMBER_WORKSPACE_CONTEXT } from '../../member-workspace.context-token.js'; -import type { UmbMemberKindType } from '../../../utils/index.js'; +import { UmbMemberKind, type UmbMemberKindType } from '../../../utils/index.js'; import { TimeFormatOptions } from './utils.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; From fb493685a0d04c62294e0b189082b407004c7466 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 14:36:00 +0200 Subject: [PATCH 118/322] move target logic to link element --- .../menu-item-layout.element.ts | 19 ++++++++++--------- .../menu-item/link/link-menu-item.element.ts | 11 +++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts b/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts index af64f06949..b6471e064d 100644 --- a/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts +++ b/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts @@ -37,6 +37,15 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { @property({ type: String }) public href?: string; + /** + * Set an anchor tag target, only used when using href. + * @type {string} + * @attr + * @default undefined + */ + @property({ type: String }) + public target?: '_blank' | '_parent' | '_self' | '_top'; + @state() private _isActive = false; @@ -47,14 +56,6 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { #debouncedCheckIsActive = debounce(() => this.#checkIsActive(), 100); - #getTarget() { - if (this.href && this.href.startsWith('http')) { - return '_blank'; - } - - return '_self'; - } - #checkIsActive() { if (!this.href) { this._isActive = false; @@ -72,7 +73,7 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { .caretLabel=${this.localize.term('visuallyHiddenTexts_expandChildItems') + ' ' + this.label} ?active=${this._isActive} ?has-children=${this.hasChildren} - target=${this.#getTarget()}> + target=${ifDefined(this.href && this.target ? this.target : undefined)}> ${this.entityType ? html` From 22553b6bbf117c8d326a184e659be282ee54543b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 14:59:31 +0200 Subject: [PATCH 119/322] add condition to check if the current user is admin --- .../conditions/is-admin/constants.ts | 1 + .../current-user/conditions/is-admin/index.ts | 1 + .../is-admin/is-admin.condition.manifest.ts | 9 +++++++++ .../conditions/is-admin/is-admin.condition.ts | 20 +++++++++++++++++++ .../user/current-user/conditions/manifests.ts | 3 +++ src/packages/user/current-user/manifests.ts | 16 +++++++-------- 6 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 src/packages/user/current-user/conditions/is-admin/constants.ts create mode 100644 src/packages/user/current-user/conditions/is-admin/index.ts create mode 100644 src/packages/user/current-user/conditions/is-admin/is-admin.condition.manifest.ts create mode 100644 src/packages/user/current-user/conditions/is-admin/is-admin.condition.ts create mode 100644 src/packages/user/current-user/conditions/manifests.ts diff --git a/src/packages/user/current-user/conditions/is-admin/constants.ts b/src/packages/user/current-user/conditions/is-admin/constants.ts new file mode 100644 index 0000000000..2d3a8d78da --- /dev/null +++ b/src/packages/user/current-user/conditions/is-admin/constants.ts @@ -0,0 +1 @@ +export const UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS = 'Umb.Condition.CurrentUser.IsAdmin'; diff --git a/src/packages/user/current-user/conditions/is-admin/index.ts b/src/packages/user/current-user/conditions/is-admin/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/user/current-user/conditions/is-admin/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/user/current-user/conditions/is-admin/is-admin.condition.manifest.ts b/src/packages/user/current-user/conditions/is-admin/is-admin.condition.manifest.ts new file mode 100644 index 0000000000..b9c81293e0 --- /dev/null +++ b/src/packages/user/current-user/conditions/is-admin/is-admin.condition.manifest.ts @@ -0,0 +1,9 @@ +import { UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS } from './constants.js'; +import type { ManifestCondition } from '@umbraco-cms/backoffice/extension-api'; + +export const manifest: ManifestCondition = { + type: 'condition', + name: 'Current user is admin Condition', + alias: UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS, + api: () => import('./is-admin.condition.js'), +}; diff --git a/src/packages/user/current-user/conditions/is-admin/is-admin.condition.ts b/src/packages/user/current-user/conditions/is-admin/is-admin.condition.ts new file mode 100644 index 0000000000..438258d6f4 --- /dev/null +++ b/src/packages/user/current-user/conditions/is-admin/is-admin.condition.ts @@ -0,0 +1,20 @@ +import { isCurrentUserAnAdmin } from '../../utils/is-current-user.function.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { + UmbConditionConfigBase, + UmbConditionControllerArguments, + UmbExtensionCondition, +} from '@umbraco-cms/backoffice/extension-api'; +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; + +export class UmbContentHasPropertiesWorkspaceCondition + extends UmbConditionBase + implements UmbExtensionCondition +{ + constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { + super(host, args); + isCurrentUserAnAdmin(host).then((isAdmin) => (this.permitted = isAdmin)); + } +} + +export { UmbContentHasPropertiesWorkspaceCondition as api }; diff --git a/src/packages/user/current-user/conditions/manifests.ts b/src/packages/user/current-user/conditions/manifests.ts new file mode 100644 index 0000000000..63918c839e --- /dev/null +++ b/src/packages/user/current-user/conditions/manifests.ts @@ -0,0 +1,3 @@ +import { manifest as isAdminManifests } from './is-admin/is-admin.condition.manifest.js'; + +export const manifests = [isAdminManifests]; diff --git a/src/packages/user/current-user/manifests.ts b/src/packages/user/current-user/manifests.ts index dce911901e..32ebb91d36 100644 --- a/src/packages/user/current-user/manifests.ts +++ b/src/packages/user/current-user/manifests.ts @@ -1,11 +1,13 @@ import { manifest as actionDefaultKindManifest } from './action/default.kind.js'; -import { manifests as modalManifests } from './modals/manifests.js'; -import { manifests as historyManifests } from './history/manifests.js'; +import { manifests as conditionManifests } from './conditions/manifests.js'; import { manifests as externalLoginProviderManifests } from './external-login/manifests.js'; +import { manifests as historyManifests } from './history/manifests.js'; import { manifests as mfaLoginProviderManifests } from './mfa-login/manifests.js'; +import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as profileManifests } from './profile/manifests.js'; -import { manifests as themeManifests } from './theme/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; +import { manifests as themeManifests } from './theme/manifests.js'; + import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const headerApps: Array = [ @@ -21,19 +23,15 @@ export const headerApps: Array = [ name: 'Current User', element: () => import('./current-user-header-app.element.js'), weight: 0, - meta: { - label: 'TODO: how should we enable this to not be set.', - icon: 'TODO: how should we enable this to not be set.', - pathname: 'user', - }, }, ]; export const manifests = [ actionDefaultKindManifest, + ...conditionManifests, + ...externalLoginProviderManifests, ...headerApps, ...historyManifests, - ...externalLoginProviderManifests, ...mfaLoginProviderManifests, ...modalManifests, ...profileManifests, From 7e8860ad135a700aa6dd2498010bbeaf8a24917c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 15:01:55 +0200 Subject: [PATCH 120/322] export condition alias --- src/packages/user/current-user/conditions/index.ts | 1 + src/packages/user/current-user/index.ts | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 src/packages/user/current-user/conditions/index.ts diff --git a/src/packages/user/current-user/conditions/index.ts b/src/packages/user/current-user/conditions/index.ts new file mode 100644 index 0000000000..8e80a3f329 --- /dev/null +++ b/src/packages/user/current-user/conditions/index.ts @@ -0,0 +1 @@ +export * from './is-admin/index.js'; diff --git a/src/packages/user/current-user/index.ts b/src/packages/user/current-user/index.ts index 343c0ed765..606a128e69 100644 --- a/src/packages/user/current-user/index.ts +++ b/src/packages/user/current-user/index.ts @@ -1,9 +1,10 @@ export * from './action/index.js'; export * from './components/index.js'; -export * from './history/current-user-history.store.js'; -export * from './utils/index.js'; -export * from './repository/index.js'; +export * from './conditions/index.js'; export * from './current-user.context.js'; export * from './current-user.context.token.js'; +export * from './history/current-user-history.store.js'; +export * from './repository/index.js'; +export * from './utils/index.js'; export type * from './types.js'; From f1c50d07c97f9e73e0f200553b00f13bd96249a2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 15:02:09 +0200 Subject: [PATCH 121/322] add conditions to links --- src/packages/help/menu/manifests.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/packages/help/menu/manifests.ts b/src/packages/help/menu/manifests.ts index 4d9985a5b5..aa4b9d68c9 100644 --- a/src/packages/help/menu/manifests.ts +++ b/src/packages/help/menu/manifests.ts @@ -1,4 +1,5 @@ import { UMB_HELP_MENU_ALIAS } from './constants.js'; +import { UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS } from '@umbraco-cms/backoffice/current-user'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ @@ -19,6 +20,11 @@ export const manifests: Array = [ icon: 'icon-movie-alt', href: 'https://learn.umbraco.com', }, + conditions: [ + { + alias: UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS, + }, + ], }, { type: 'menuItem', @@ -32,5 +38,10 @@ export const manifests: Array = [ icon: 'icon-hearts', href: 'https://our.umbraco.com', }, + conditions: [ + { + alias: UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS, + }, + ], }, ]; From 41c0d7016e3914d5f777fc0aa41dc30dfd05e002 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 15:54:25 +0200 Subject: [PATCH 122/322] update links --- src/packages/help/menu/manifests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/help/menu/manifests.ts b/src/packages/help/menu/manifests.ts index aa4b9d68c9..ee466c9a80 100644 --- a/src/packages/help/menu/manifests.ts +++ b/src/packages/help/menu/manifests.ts @@ -18,7 +18,7 @@ export const manifests: Array = [ menus: [UMB_HELP_MENU_ALIAS], label: 'Umbraco Learning Base', icon: 'icon-movie-alt', - href: 'https://learn.umbraco.com', + href: 'https://umbra.co/ulb', }, conditions: [ { @@ -36,7 +36,7 @@ export const manifests: Array = [ menus: [UMB_HELP_MENU_ALIAS], label: 'Community Website', icon: 'icon-hearts', - href: 'https://our.umbraco.com', + href: 'https://our.umbraco.com?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=our', }, conditions: [ { From 81999941ced506b05402882c53a2174eb3bced6d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 18:53:49 +0200 Subject: [PATCH 123/322] pass entity type from manifest --- .../menu/components/menu-item/menu-item-default.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packages/core/menu/components/menu-item/menu-item-default.element.ts b/src/packages/core/menu/components/menu-item/menu-item-default.element.ts index 75fbc48075..916598bc99 100644 --- a/src/packages/core/menu/components/menu-item/menu-item-default.element.ts +++ b/src/packages/core/menu/components/menu-item/menu-item-default.element.ts @@ -45,7 +45,8 @@ export class UmbMenuItemDefaultElement extends UmbLitElement implements UmbMenuI + .label=${this.localize.string(this.manifest.meta.label ?? this.manifest.name)} + .entityType=${this.manifest.meta.entityType}> `; } From dba4c74b036f5d8726ba7d5eb04bee8ee5477ed7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 21:13:01 +0200 Subject: [PATCH 124/322] add path helper to root --- src/packages/user/user/paths.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user/paths.ts b/src/packages/user/user/paths.ts index eb80086f08..210af851fd 100644 --- a/src/packages/user/user/paths.ts +++ b/src/packages/user/user/paths.ts @@ -1,8 +1,13 @@ import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js'; -import { UMB_USER_ENTITY_TYPE } from './entity.js'; +import { UMB_USER_ENTITY_TYPE, UMB_USER_ROOT_ENTITY_TYPE } from './entity.js'; import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; export const UMB_USER_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ sectionName: UMB_USER_SECTION_PATHNAME, entityType: UMB_USER_ENTITY_TYPE, }); + +export const UMB_USER_ROOT_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_USER_SECTION_PATHNAME, + entityType: UMB_USER_ROOT_ENTITY_TYPE, +}); From 6d911aa199ee5f43918b3e1991b608b8dd0fe552 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 21:13:12 +0200 Subject: [PATCH 125/322] back button to root --- .../user/user/workspace/user-workspace-editor.element.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/packages/user/user/workspace/user-workspace-editor.element.ts index c4e11d2175..3a1d79c7ef 100644 --- a/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -13,6 +13,8 @@ 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'; import './components/user-workspace-client-credentials/user-workspace-client-credentials.element.js'; +import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; +import { UMB_USER_ROOT_WORKSPACE_PATH } from '../paths.js'; @customElement('umb-user-workspace-editor') export class UmbUserWorkspaceEditorElement extends UmbLitElement { @@ -50,7 +52,10 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { if (!this._user) return html`User not found`; return html` - + ${this.#renderHeader()}
${this.#renderLeftColumn()}
From 9a1d76c5ac5793dcf8dc8b9e9eb09836c805ca6e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 21:39:06 +0200 Subject: [PATCH 126/322] wip create + invite entity actions --- .../create/create-user-entity-action.ts | 21 ++++ .../user/entity-actions/create/manifests.ts | 22 ++++ .../user/entity-actions/create/modal/index.ts | 8 ++ .../entity-actions/create/modal/manifests.ts | 10 ++ .../user-create-options-modal.element.ts | 108 ++++++++++++++++++ .../invite/invite-user-entity-action.ts | 11 ++ .../user/entity-actions/invite/manifests.ts | 19 +++ .../user/user/entity-actions/manifests.ts | 12 +- 8 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 src/packages/user/user/entity-actions/create/create-user-entity-action.ts create mode 100644 src/packages/user/user/entity-actions/create/manifests.ts create mode 100644 src/packages/user/user/entity-actions/create/modal/index.ts create mode 100644 src/packages/user/user/entity-actions/create/modal/manifests.ts create mode 100644 src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts create mode 100644 src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts create mode 100644 src/packages/user/user/entity-actions/invite/manifests.ts diff --git a/src/packages/user/user/entity-actions/create/create-user-entity-action.ts b/src/packages/user/user/entity-actions/create/create-user-entity-action.ts new file mode 100644 index 0000000000..a6da26da4f --- /dev/null +++ b/src/packages/user/user/entity-actions/create/create-user-entity-action.ts @@ -0,0 +1,21 @@ +import { UMB_USER_CREATE_OPTIONS_MODAL } from './modal/index.js'; +import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; + +export class UmbCreateUserEntityAction extends UmbEntityActionBase { + override async execute() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const modalContext = modalManager.open(this, UMB_USER_CREATE_OPTIONS_MODAL, { + data: { + parent: { + unique: this.args.unique, + entityType: this.args.entityType, + }, + }, + }); + + await modalContext.onSubmit(); + } +} + +export { UmbCreateUserEntityAction as api }; diff --git a/src/packages/user/user/entity-actions/create/manifests.ts b/src/packages/user/user/entity-actions/create/manifests.ts new file mode 100644 index 0000000000..7915152337 --- /dev/null +++ b/src/packages/user/user/entity-actions/create/manifests.ts @@ -0,0 +1,22 @@ +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; + +import { manifests as modalManifests } from './modal/manifests.js'; + +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + kind: 'default', + alias: 'Umb.EntityAction.User.Create', + name: 'Create User Entity Action', + weight: 1200, + api: () => import('./create-user-entity-action.js'), + forEntityTypes: [UMB_USER_ROOT_ENTITY_TYPE], + meta: { + icon: 'icon-add', + label: '#actions_create', + }, + }, + ...modalManifests, +]; diff --git a/src/packages/user/user/entity-actions/create/modal/index.ts b/src/packages/user/user/entity-actions/create/modal/index.ts new file mode 100644 index 0000000000..778a1fe38d --- /dev/null +++ b/src/packages/user/user/entity-actions/create/modal/index.ts @@ -0,0 +1,8 @@ +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export const UMB_USER_CREATE_OPTIONS_MODAL = new UmbModalToken('Umb.Modal.User.CreateOptions', { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/packages/user/user/entity-actions/create/modal/manifests.ts b/src/packages/user/user/entity-actions/create/modal/manifests.ts new file mode 100644 index 0000000000..2c736c75fd --- /dev/null +++ b/src/packages/user/user/entity-actions/create/modal/manifests.ts @@ -0,0 +1,10 @@ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.User.CreateOptions', + name: 'User Create Options Modal', + element: () => import('./user-create-options-modal.element.js'), + }, +]; diff --git a/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts b/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts new file mode 100644 index 0000000000..29932ea273 --- /dev/null +++ b/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts @@ -0,0 +1,108 @@ +import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal.token.js'; +import { UmbUserKind, type UmbUserKindType } from '../../../utils/index.js'; +import { html, customElement, map } from '@umbraco-cms/backoffice/external/lit'; +import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; +import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; + +interface UmbUserCreateOptionModel { + label: string; + description: string; + icon: string; + kind: UmbUserKindType; +} + +const elementName = 'umb-user-create-options-modal'; +@customElement(elementName) +export class UmbUserCreateOptionsModalElement extends UmbModalBaseElement { + #options: Array = [ + { + label: this.localize.term('user_userKindDefault'), + description: 'Donec augue nunc, ullamcorper non turpis ut, maximus facilisis lorem. Nunc id sagittis magna.', + icon: 'icon-user', + kind: UmbUserKind.DEFAULT, + }, + { + label: this.localize.term('user_userKindApi'), + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + icon: 'icon-unplug', + kind: UmbUserKind.API, + }, + ]; + + async #onClick(event: Event, kind: UmbUserKindType) { + event.stopPropagation(); + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); + + const unique = entityContext.getUnique(); + const entityType = entityContext.getEntityType(); + + if (unique === undefined) throw new Error('Missing unique'); + if (!entityType) throw new Error('Missing entityType'); + + const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { + data: { + user: { + kind, + }, + }, + }); + + modalContext + ?.onSubmit() + .then(() => { + this.#requestReloadChildrenOfEntity({ entityType, unique }); + }) + .catch(async () => { + // modal is closed after creation instead of navigating to the new user. + // We therefore need to reload the children of the entity + this.#requestReloadChildrenOfEntity({ entityType, unique }); + }); + } + + async #requestReloadChildrenOfEntity({ entityType, unique }: UmbEntityModel) { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadChildrenOfEntityEvent({ + entityType, + unique, + }); + + eventContext.dispatchEvent(event); + } + + override render() { + return html` + + + + ${map( + this.#options, + (item) => html` + this.#onClick(event, item.kind)}> + `, + )} + + + + + `; + } +} + +export { UmbUserCreateOptionsModalElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserCreateOptionsModalElement; + } +} diff --git a/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts b/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts new file mode 100644 index 0000000000..4ac61a28d5 --- /dev/null +++ b/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts @@ -0,0 +1,11 @@ +import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; + +export class UmbCreateUserEntityAction extends UmbEntityActionBase { + override async execute() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + debugger; + } +} + +export { UmbCreateUserEntityAction as api }; diff --git a/src/packages/user/user/entity-actions/invite/manifests.ts b/src/packages/user/user/entity-actions/invite/manifests.ts new file mode 100644 index 0000000000..0fc1e67e74 --- /dev/null +++ b/src/packages/user/user/entity-actions/invite/manifests.ts @@ -0,0 +1,19 @@ +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; + +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + kind: 'default', + alias: 'Umb.EntityAction.User.Invite', + name: 'Invite User Entity Action', + weight: 1000, + api: () => import('./invite-user-entity-action.js'), + forEntityTypes: [UMB_USER_ROOT_ENTITY_TYPE], + meta: { + icon: 'icon-paper-plane', + label: '#user_invite', + }, + }, +]; diff --git a/src/packages/user/user/entity-actions/manifests.ts b/src/packages/user/user/entity-actions/manifests.ts index b67955449e..493f108ff1 100644 --- a/src/packages/user/user/entity-actions/manifests.ts +++ b/src/packages/user/user/entity-actions/manifests.ts @@ -1,6 +1,10 @@ import { UMB_USER_DETAIL_REPOSITORY_ALIAS, UMB_USER_ITEM_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_USER_ENTITY_TYPE } from '../entity.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +import { manifests as createManifests } from './create/manifests.js'; +import { manifests as inviteManifests } from './invite/manifests.js'; + +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; const entityActions: Array = [ { @@ -93,4 +97,8 @@ const entityActions: Array = [ }, ]; -export const manifests: Array = [...entityActions]; +export const manifests: Array = [ + ...entityActions, + ...createManifests, + ...inviteManifests, +]; From be728f0aec5a807d920752bd2f817e213dca523e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 22:01:12 +0200 Subject: [PATCH 127/322] update back path --- src/packages/user/user-group/paths.ts | 7 ++++++- src/packages/user/user-group/workspace/constants.ts | 1 + .../workspace/user-group-workspace-editor.element.ts | 6 ++++-- 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/packages/user/user-group/workspace/constants.ts diff --git a/src/packages/user/user-group/paths.ts b/src/packages/user/user-group/paths.ts index bcd681d6dc..51aa649211 100644 --- a/src/packages/user/user-group/paths.ts +++ b/src/packages/user/user-group/paths.ts @@ -1,8 +1,13 @@ import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js'; -import { UMB_USER_GROUP_ENTITY_TYPE } from './entity.js'; +import { UMB_USER_GROUP_ENTITY_TYPE, UMB_USER_GROUP_ROOT_ENTITY_TYPE } from './entity.js'; import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; export const UMB_USER_GROUP_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ sectionName: UMB_USER_SECTION_PATHNAME, entityType: UMB_USER_GROUP_ENTITY_TYPE, }); + +export const UMB_USER_GROUP_ROOT_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_USER_SECTION_PATHNAME, + entityType: UMB_USER_GROUP_ROOT_ENTITY_TYPE, +}); diff --git a/src/packages/user/user-group/workspace/constants.ts b/src/packages/user/user-group/workspace/constants.ts new file mode 100644 index 0000000000..6972100cb8 --- /dev/null +++ b/src/packages/user/user-group/workspace/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_GROUP_WORKSPACE_ALIAS = 'Umb.Workspace.UserGroup'; diff --git a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts b/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts index 9374872d2a..a4d129dd04 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts +++ b/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts @@ -1,5 +1,7 @@ import type { UmbUserGroupDetailModel } from '../index.js'; +import { UMB_USER_GROUP_ROOT_WORKSPACE_PATH } from '../paths.js'; import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from './user-group-workspace.context-token.js'; +import { UMB_USER_GROUP_WORKSPACE_ALIAS } from './constants.js'; import type { UUIBooleanInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; @@ -170,9 +172,9 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { return html` + back-path=${UMB_USER_GROUP_ROOT_WORKSPACE_PATH}> ${this.#renderHeader()} ${this.#renderMain()} `; From 6f5474851f307f7c657f1daf7dd246cc4f1834aa Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 10:34:20 +0200 Subject: [PATCH 128/322] add help module --- package-lock.json | 4 ++-- package.json | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 826baef473..434bbdb8ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@umbraco-cms/backoffice", - "version": "14.3.0", + "version": "15.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@umbraco-cms/backoffice", - "version": "14.3.0", + "version": "15.0.0", "license": "MIT", "workspaces": [ "./src/packages/block", diff --git a/package.json b/package.json index 075d0e1d0a..9e7ba1eee0 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "./entity": "./dist-cms/packages/core/entity/index.js", "./event": "./dist-cms/packages/core/event/index.js", "./extension-registry": "./dist-cms/packages/core/extension-registry/index.js", + "./help": "./dist-cms/packages/core/help/index.js", "./icon": "./dist-cms/packages/core/icon-registry/index.js", "./id": "./dist-cms/packages/core/id/index.js", "./imaging": "./dist-cms/packages/media/imaging/index.js", From b949c32f2b04aabb38f6d98c337ae726f2b06336 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 10:34:29 +0200 Subject: [PATCH 129/322] export alias --- src/packages/help/index.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/packages/help/index.ts diff --git a/src/packages/help/index.ts b/src/packages/help/index.ts new file mode 100644 index 0000000000..f15384a062 --- /dev/null +++ b/src/packages/help/index.ts @@ -0,0 +1 @@ +export * from './menu/index.js'; From 0bda6b1e45211829ade7ded911cd43a941f9a02f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 10:34:45 +0200 Subject: [PATCH 130/322] Update tsconfig.json --- tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tsconfig.json b/tsconfig.json index 1d69cbe783..89fcb27d48 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -67,6 +67,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@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"], + "@umbraco-cms/backoffice/help": ["./src/packages/core/help/index.ts"], "@umbraco-cms/backoffice/icon": ["./src/packages/core/icon-registry/index.ts"], "@umbraco-cms/backoffice/id": ["./src/packages/core/id/index.ts"], "@umbraco-cms/backoffice/imaging": ["./src/packages/media/imaging/index.ts"], From a02863c8bcd2cc0f5ed6252bc3700bbf55178c48 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 12:11:12 +0200 Subject: [PATCH 131/322] only render header app if menu has items --- .../header-app/help-header-app.element.ts | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/packages/help/header-app/help-header-app.element.ts b/src/packages/help/header-app/help-header-app.element.ts index 7b0b767d13..0c8ff69b84 100644 --- a/src/packages/help/header-app/help-header-app.element.ts +++ b/src/packages/help/header-app/help-header-app.element.ts @@ -1,8 +1,9 @@ import { UMB_HELP_MENU_ALIAS } from '../menu/index.js'; import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; -import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; -import type { ManifestMenu } from '@umbraco-cms/backoffice/extension-registry'; +import { umbExtensionsRegistry, type ManifestMenu } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; const elementName = 'umb-help-header-app'; @customElement(elementName) @@ -10,6 +11,24 @@ export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { @state() private _popoverOpen = false; + @state() + private _helpMenuHasMenuItems = false; + + constructor() { + super(); + + new UmbExtensionsManifestInitializer( + this, + umbExtensionsRegistry, + 'menuItem', + (manifest) => manifest.meta.menus.includes(UMB_HELP_MENU_ALIAS), + (menuItems) => { + const manifests = menuItems.map((menuItem) => menuItem.manifest); + this._helpMenuHasMenuItems = manifests.length > 0; + }, + ); + } + #onPopoverToggle(event: ToggleEvent) { // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -18,11 +37,21 @@ export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { } override render() { + return html` ${this.#renderButton()} ${this.#renderPopover()} `; + } + + #renderButton() { + if (!this._helpMenuHasMenuItems) return nothing; + return html` + `; + } + #renderPopover() { + return html` From 591b07e2e1d17da7a46b01b0dc967ee14f567c1c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 12:19:56 +0200 Subject: [PATCH 132/322] update package build --- package.json | 2 +- src/packages/help/package.json | 8 ++++++++ src/packages/help/vite.config.ts | 2 +- tsconfig.json | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/packages/help/package.json diff --git a/package.json b/package.json index cefbbb4419..a522d9d100 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "./entity": "./dist-cms/packages/core/entity/index.js", "./event": "./dist-cms/packages/core/event/index.js", "./extension-registry": "./dist-cms/packages/core/extension-registry/index.js", - "./help": "./dist-cms/packages/core/help/index.js", + "./help": "./dist-cms/packages/help/index.js", "./icon": "./dist-cms/packages/core/icon-registry/index.js", "./id": "./dist-cms/packages/core/id/index.js", "./imaging": "./dist-cms/packages/media/imaging/index.js", diff --git a/src/packages/help/package.json b/src/packages/help/package.json new file mode 100644 index 0000000000..3cae8e94ec --- /dev/null +++ b/src/packages/help/package.json @@ -0,0 +1,8 @@ +{ + "name": "@umbraco-backoffice/help", + "private": true, + "type": "module", + "scripts": { + "build": "vite build" + } +} \ No newline at end of file diff --git a/src/packages/help/vite.config.ts b/src/packages/help/vite.config.ts index a320e9a053..965d250b98 100644 --- a/src/packages/help/vite.config.ts +++ b/src/packages/help/vite.config.ts @@ -8,5 +8,5 @@ const dist = '../../../dist-cms/packages/help'; rmSync(dist, { recursive: true, force: true }); export default defineConfig({ - ...getDefaultConfig({ dist, entry: ['manifests.ts', 'umbraco-package.ts'] }), + ...getDefaultConfig({ dist }), }); diff --git a/tsconfig.json b/tsconfig.json index 89fcb27d48..7807084b15 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -67,7 +67,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@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"], - "@umbraco-cms/backoffice/help": ["./src/packages/core/help/index.ts"], + "@umbraco-cms/backoffice/help": ["./src/packages/help/index.ts"], "@umbraco-cms/backoffice/icon": ["./src/packages/core/icon-registry/index.ts"], "@umbraco-cms/backoffice/id": ["./src/packages/core/id/index.ts"], "@umbraco-cms/backoffice/imaging": ["./src/packages/media/imaging/index.ts"], From ca9728d5709f5513c4de445e2a78f08dd5738be6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 12:38:12 +0200 Subject: [PATCH 133/322] Update package-lock.json --- package-lock.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 5005f8e5d4..14b88b3569 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7811,6 +7811,10 @@ "resolved": "src/packages/health-check", "link": true }, + "node_modules/@umbraco-backoffice/help": { + "resolved": "src/packages/help", + "link": true + }, "node_modules/@umbraco-backoffice/language": { "resolved": "src/packages/language", "link": true @@ -23078,6 +23082,7 @@ "src/packages/health-check": { "name": "@umbraco-backoffice/health-check" }, + "src/packages/help": {}, "src/packages/language": { "name": "@umbraco-backoffice/language" }, @@ -23120,7 +23125,9 @@ "src/packages/static-file": { "name": "@umbraco-backoffice/static-file" }, - "src/packages/sysinfo": {}, + "src/packages/sysinfo": { + "name": "@umbraco-backoffice/sysinfo" + }, "src/packages/tags": { "name": "@umbraco-backoffice/tag" }, From f30253b32dedc7ada2c608a9d3b86dbc6a3ce434 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 14:57:08 +0200 Subject: [PATCH 134/322] add pattern validation --- ...ate-user-client-credential-modal.element.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts index dc48873e55..c18ac77d4b 100644 --- a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts +++ b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts @@ -7,6 +7,7 @@ import type { import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, query } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; const elementName = 'umb-create-user-client-credential-modal'; @customElement(elementName) @@ -17,10 +18,27 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement< @query('#CreateUserClientCredentialForm') _form?: HTMLFormElement; + @query('#unique') + _inputUniqueElement?: UUIInputElement; + #userClientCredentialRepository = new UmbUserClientCredentialRepository(this); #uniquePrefix = 'umbraco-back-office-'; + protected override firstUpdated(): void { + // For some reason the pattern attribute is not working with this specific regex. It complains about the regex is invalid. + // TODO: investigate why this is happening. + this._inputUniqueElement?.addValidator( + 'patternMismatch', + () => 'Only alphanumeric characters and hyphens are allowed', + () => { + const value = (this._inputUniqueElement?.value as string) || ''; + // eslint-disable-next-line no-useless-escape + return !new RegExp(/^[a-zA-Z0-9\-]+$/).test(value); + }, + ); + } + async #onSubmit(e: SubmitEvent) { e.preventDefault(); From dc2c07f32414deae1d69c1efb959195b55c9c5ef Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:37:27 +0200 Subject: [PATCH 135/322] add to folder --- .../user/section/sidebar-app/index.ts | 2 +- src/packages/user/user-group/manifests.ts | 4 +- ...orkspace-action-user-group-save.element.ts | 2 +- .../user-allow-action-base.condition.ts | 2 +- src/packages/user/user/workspace/manifests.ts | 44 ++----------------- .../user-workspace-action-save.element.ts | 0 .../user-workspace-access.element.ts | 2 +- .../user-workspace-assign-access.element.ts | 2 +- .../user-workspace-avatar.element.ts | 2 +- ...er-workspace-client-credentials.element.ts | 8 ++-- .../user-workspace-info.element.ts | 8 ++-- ...user-workspace-profile-settings.element.ts | 4 +- .../user/workspace/{ => user}/constants.ts | 0 .../user/user/workspace/user/manifests.ts | 42 ++++++++++++++++++ .../user-workspace-editor.element.ts | 6 +-- .../user-workspace.context-token.ts | 2 +- .../{ => user}/user-workspace.context.ts | 10 ++--- .../{ => user}/user-workspace.test.ts | 0 18 files changed, 72 insertions(+), 68 deletions(-) rename src/packages/user/user/workspace/{ => user}/actions/user-workspace-action-save.element.ts (100%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-access/user-workspace-access.element.ts (97%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-assign-access/user-workspace-assign-access.element.ts (99%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-avatar/user-workspace-avatar.element.ts (97%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts (93%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-info/user-workspace-info.element.ts (95%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts (97%) rename src/packages/user/user/workspace/{ => user}/constants.ts (100%) create mode 100644 src/packages/user/user/workspace/user/manifests.ts rename src/packages/user/user/workspace/{ => user}/user-workspace-editor.element.ts (97%) rename src/packages/user/user/workspace/{ => user}/user-workspace.context-token.ts (89%) rename src/packages/user/user/workspace/{ => user}/user-workspace.context.ts (94%) rename src/packages/user/user/workspace/{ => user}/user-workspace.test.ts (100%) diff --git a/src/packages/user/section/sidebar-app/index.ts b/src/packages/user/section/sidebar-app/index.ts index 4f07201dcf..42f853e5be 100644 --- a/src/packages/user/section/sidebar-app/index.ts +++ b/src/packages/user/section/sidebar-app/index.ts @@ -1 +1 @@ -export * from './constants.js'; +export * from '../constants.js'; diff --git a/src/packages/user/user-group/manifests.ts b/src/packages/user/user-group/manifests.ts index 1ac88d4e75..a68693f9c3 100644 --- a/src/packages/user/user-group/manifests.ts +++ b/src/packages/user/user-group/manifests.ts @@ -7,9 +7,9 @@ import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ +export const manifests: Array = [ ...collectionManifests, ...entityActionManifests, ...entityBulkActionManifests, diff --git a/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts b/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts index 1c86ca5b08..530c72b616 100644 --- a/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts +++ b/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts @@ -1,4 +1,4 @@ -import { UMB_USER_WORKSPACE_CONTEXT } from '../../../user/workspace/user-workspace.context-token.js'; +import { UMB_USER_WORKSPACE_CONTEXT } from '../../../user/workspace/user/user-workspace.context-token.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/packages/user/user/conditions/user-allow-action-base.condition.ts b/src/packages/user/user/conditions/user-allow-action-base.condition.ts index bdae21f4af..7dffc20550 100644 --- a/src/packages/user/user/conditions/user-allow-action-base.condition.ts +++ b/src/packages/user/user/conditions/user-allow-action-base.condition.ts @@ -1,5 +1,5 @@ import type { UmbUserStateEnum } from '../types.js'; -import { UMB_USER_WORKSPACE_CONTEXT } from '../workspace/user-workspace.context-token.js'; +import { UMB_USER_WORKSPACE_CONTEXT } from '../workspace/user/user-workspace.context-token.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { isCurrentUser } from '@umbraco-cms/backoffice/current-user'; import type { diff --git a/src/packages/user/user/workspace/manifests.ts b/src/packages/user/user/workspace/manifests.ts index d2c5c90ec4..a8bafd21d8 100644 --- a/src/packages/user/user/workspace/manifests.ts +++ b/src/packages/user/user/workspace/manifests.ts @@ -1,42 +1,4 @@ -import { UMB_USER_ENTITY_TYPE } from '../entity.js'; -import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; -import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; -import type { - ManifestWorkspaces, - ManifestWorkspaceActions, - ManifestTypes, -} from '@umbraco-cms/backoffice/extension-registry'; +import { manifests as userManifests } from './user/manifests.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -const workspace: ManifestWorkspaces = { - type: 'workspace', - kind: 'routable', - alias: UMB_USER_WORKSPACE_ALIAS, - name: 'User Workspace', - api: () => import('./user-workspace.context.js'), - meta: { - entityType: UMB_USER_ENTITY_TYPE, - }, -}; - -const workspaceActions: Array = [ - { - type: 'workspaceAction', - kind: 'default', - alias: 'Umb.WorkspaceAction.User.Save', - name: 'Save User Workspace Action', - api: UmbSubmitWorkspaceAction, - meta: { - label: '#buttons_save', - look: 'primary', - color: 'positive', - }, - conditions: [ - { - alias: 'Umb.Condition.WorkspaceAlias', - match: workspace.alias, - }, - ], - }, -]; - -export const manifests: Array = [workspace, ...workspaceActions]; +export const manifests: Array = [...userManifests]; diff --git a/src/packages/user/user/workspace/actions/user-workspace-action-save.element.ts b/src/packages/user/user/workspace/user/actions/user-workspace-action-save.element.ts similarity index 100% rename from src/packages/user/user/workspace/actions/user-workspace-action-save.element.ts rename to src/packages/user/user/workspace/user/actions/user-workspace-action-save.element.ts diff --git a/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-access/user-workspace-access.element.ts similarity index 97% rename from src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-access/user-workspace-access.element.ts index 7177e91909..86197319e5 100644 --- a/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-access/user-workspace-access.element.ts @@ -1,5 +1,5 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserStartNodesModel } from '../../../types.js'; +import type { UmbUserStartNodesModel } 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'; diff --git a/src/packages/user/user/workspace/components/user-workspace-assign-access/user-workspace-assign-access.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-assign-access/user-workspace-assign-access.element.ts similarity index 99% rename from src/packages/user/user/workspace/components/user-workspace-assign-access/user-workspace-assign-access.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-assign-access/user-workspace-assign-access.element.ts index 6a7a881039..d32bb6e0fd 100644 --- a/src/packages/user/user/workspace/components/user-workspace-assign-access/user-workspace-assign-access.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-assign-access/user-workspace-assign-access.element.ts @@ -1,5 +1,5 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserDetailModel } from '../../../types.js'; +import type { UmbUserDetailModel } from '../../../../types.js'; import { html, customElement, state, nothing, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; diff --git a/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-avatar/user-workspace-avatar.element.ts similarity index 97% rename from src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-avatar/user-workspace-avatar.element.ts index b3c7317d12..9400230d7a 100644 --- a/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-avatar/user-workspace-avatar.element.ts @@ -1,4 +1,4 @@ -import type { UmbUserDetailModel } from '../../../types.js'; +import type { UmbUserDetailModel } from '../../../../types.js'; import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; import { css, html, customElement, query, nothing, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts similarity index 93% rename from src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index 512d97f2d6..7d77417056 100644 --- a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -2,10 +2,10 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.j import type { UmbDeleteUserClientCredentialRequestArgs, UmbUserClientCredentialModel, -} from '../../../client-credential/index.js'; -import { UmbUserClientCredentialRepository } from '../../../client-credential/index.js'; -import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; -import { UmbUserKind } from '../../../utils/index.js'; +} from '../../../../client-credential/index.js'; +import { UmbUserClientCredentialRepository } from '../../../../client-credential/index.js'; +import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; +import { UmbUserKind } from '../../../../utils/index.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'; diff --git a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-info/user-workspace-info.element.ts similarity index 95% rename from src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-info/user-workspace-info.element.ts index 898bea5823..8f5d2437b0 100644 --- a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-info/user-workspace-info.element.ts @@ -1,8 +1,8 @@ -import type { UmbUserDisplayStatus } from '../../../utils.js'; -import { TimeFormatOptions, getDisplayStateFromUserStatus } from '../../../utils.js'; +import type { UmbUserDisplayStatus } from '../../../../utils.js'; +import { TimeFormatOptions, getDisplayStateFromUserStatus } from '../../../../utils.js'; import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserDetailModel } from '../../../types.js'; -import { UmbUserKind } from '../../../utils/index.js'; +import type { UmbUserDetailModel } from '../../../../types.js'; +import { UmbUserKind } from '../../../../utils/index.js'; import { html, customElement, state, css, repeat, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; diff --git a/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts similarity index 97% rename from src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts index fd4e67c615..0d313eb130 100644 --- a/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts @@ -1,11 +1,11 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserDetailModel } from '../../../types.js'; +import type { UmbUserDetailModel } from '../../../../types.js'; +import { UmbUserKind } from '../../../../utils/index.js'; import { html, customElement, state, ifDefined, 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 { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbUiCultureInputElement } from '@umbraco-cms/backoffice/localization'; -import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-workspace-profile-settings') export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { diff --git a/src/packages/user/user/workspace/constants.ts b/src/packages/user/user/workspace/user/constants.ts similarity index 100% rename from src/packages/user/user/workspace/constants.ts rename to src/packages/user/user/workspace/user/constants.ts diff --git a/src/packages/user/user/workspace/user/manifests.ts b/src/packages/user/user/workspace/user/manifests.ts new file mode 100644 index 0000000000..3f4203dd88 --- /dev/null +++ b/src/packages/user/user/workspace/user/manifests.ts @@ -0,0 +1,42 @@ +import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; +import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; +import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import type { + ManifestWorkspaces, + ManifestWorkspaceActions, + ManifestTypes, +} from '@umbraco-cms/backoffice/extension-registry'; + +const workspace: ManifestWorkspaces = { + type: 'workspace', + kind: 'routable', + alias: UMB_USER_WORKSPACE_ALIAS, + name: 'User Workspace', + api: () => import('./user-workspace.context.js'), + meta: { + entityType: UMB_USER_ENTITY_TYPE, + }, +}; + +const workspaceActions: Array = [ + { + type: 'workspaceAction', + kind: 'default', + alias: 'Umb.WorkspaceAction.User.Save', + name: 'Save User Workspace Action', + api: UmbSubmitWorkspaceAction, + meta: { + label: '#buttons_save', + look: 'primary', + color: 'positive', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: workspace.alias, + }, + ], + }, +]; + +export const manifests: Array = [workspace, ...workspaceActions]; diff --git a/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/packages/user/user/workspace/user/user-workspace-editor.element.ts similarity index 97% rename from src/packages/user/user/workspace/user-workspace-editor.element.ts rename to src/packages/user/user/workspace/user/user-workspace-editor.element.ts index 3a1d79c7ef..b65ebebf63 100644 --- a/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/packages/user/user/workspace/user/user-workspace-editor.element.ts @@ -1,6 +1,8 @@ -import type { UmbUserDetailModel } from '../index.js'; +import type { UmbUserDetailModel } from '../../index.js'; +import { UMB_USER_ROOT_WORKSPACE_PATH } from '../../paths.js'; import type { UmbUserWorkspaceContext } from './user-workspace.context.js'; import { UMB_USER_WORKSPACE_CONTEXT } from './user-workspace.context-token.js'; +import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit'; @@ -13,8 +15,6 @@ 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'; import './components/user-workspace-client-credentials/user-workspace-client-credentials.element.js'; -import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; -import { UMB_USER_ROOT_WORKSPACE_PATH } from '../paths.js'; @customElement('umb-user-workspace-editor') export class UmbUserWorkspaceEditorElement extends UmbLitElement { diff --git a/src/packages/user/user/workspace/user-workspace.context-token.ts b/src/packages/user/user/workspace/user/user-workspace.context-token.ts similarity index 89% rename from src/packages/user/user/workspace/user-workspace.context-token.ts rename to src/packages/user/user/workspace/user/user-workspace.context-token.ts index ac99021cc5..bac31a226c 100644 --- a/src/packages/user/user/workspace/user-workspace.context-token.ts +++ b/src/packages/user/user/workspace/user/user-workspace.context-token.ts @@ -1,4 +1,4 @@ -import { UMB_USER_ENTITY_TYPE } from '../entity.js'; +import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; import type { UmbUserWorkspaceContext } from './user-workspace.context.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/packages/user/user/workspace/user-workspace.context.ts b/src/packages/user/user/workspace/user/user-workspace.context.ts similarity index 94% rename from src/packages/user/user/workspace/user-workspace.context.ts rename to src/packages/user/user/workspace/user/user-workspace.context.ts index 69587e191d..18963318ec 100644 --- a/src/packages/user/user/workspace/user-workspace.context.ts +++ b/src/packages/user/user/workspace/user/user-workspace.context.ts @@ -1,8 +1,8 @@ -import type { UmbUserDetailModel, UmbUserStartNodesModel, UmbUserStateEnum } from '../types.js'; -import { UMB_USER_ENTITY_TYPE } from '../entity.js'; -import { UmbUserDetailRepository } from '../repository/index.js'; -import { UmbUserAvatarRepository } from '../repository/avatar/index.js'; -import { UmbUserConfigRepository } from '../repository/config/index.js'; +import type { UmbUserDetailModel, UmbUserStartNodesModel, UmbUserStateEnum } from '../../types.js'; +import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; +import { UmbUserDetailRepository } from '../../repository/index.js'; +import { UmbUserAvatarRepository } from '../../repository/avatar/index.js'; +import { UmbUserConfigRepository } from '../../repository/config/index.js'; import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; import { UmbUserWorkspaceEditorElement } from './user-workspace-editor.element.js'; import type { UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/packages/user/user/workspace/user-workspace.test.ts b/src/packages/user/user/workspace/user/user-workspace.test.ts similarity index 100% rename from src/packages/user/user/workspace/user-workspace.test.ts rename to src/packages/user/user/workspace/user/user-workspace.test.ts From b2de7e57d6bd66234e45588ca04d84060a14ea8a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:38:05 +0200 Subject: [PATCH 136/322] rename folder --- src/packages/user/user/{section-view => user-root}/manifests.ts | 0 .../{section-view => user-root}/user-root-workspace.element.ts | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/packages/user/user/{section-view => user-root}/manifests.ts (100%) rename src/packages/user/user/{section-view => user-root}/user-root-workspace.element.ts (100%) diff --git a/src/packages/user/user/section-view/manifests.ts b/src/packages/user/user/user-root/manifests.ts similarity index 100% rename from src/packages/user/user/section-view/manifests.ts rename to src/packages/user/user/user-root/manifests.ts diff --git a/src/packages/user/user/section-view/user-root-workspace.element.ts b/src/packages/user/user/user-root/user-root-workspace.element.ts similarity index 100% rename from src/packages/user/user/section-view/user-root-workspace.element.ts rename to src/packages/user/user/user-root/user-root-workspace.element.ts From 8244ab8d7df61e57d9c63b004d8c1a156b9cd4aa Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:38:59 +0200 Subject: [PATCH 137/322] move into workspace folder --- src/packages/user/user/manifests.ts | 2 -- src/packages/user/user/workspace/manifests.ts | 3 ++- src/packages/user/user/{ => workspace}/user-root/manifests.ts | 2 +- .../{ => workspace}/user-root/user-root-workspace.element.ts | 0 4 files changed, 3 insertions(+), 4 deletions(-) rename src/packages/user/user/{ => workspace}/user-root/manifests.ts (86%) rename src/packages/user/user/{ => workspace}/user-root/user-root-workspace.element.ts (100%) diff --git a/src/packages/user/user/manifests.ts b/src/packages/user/user/manifests.ts index 383ff1ad80..b73a4378c2 100644 --- a/src/packages/user/user/manifests.ts +++ b/src/packages/user/user/manifests.ts @@ -7,7 +7,6 @@ import { manifests as inviteManifests } from './invite/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; -import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; import { manifests as menuItemManifests } from './menu-item/manifests.js'; @@ -23,7 +22,6 @@ export const manifests: Array = [ ...modalManifests, ...propertyEditorManifests, ...repositoryManifests, - ...sectionViewManifests, ...workspaceManifests, ...menuItemManifests, ]; diff --git a/src/packages/user/user/workspace/manifests.ts b/src/packages/user/user/workspace/manifests.ts index a8bafd21d8..09e4d463e9 100644 --- a/src/packages/user/user/workspace/manifests.ts +++ b/src/packages/user/user/workspace/manifests.ts @@ -1,4 +1,5 @@ import { manifests as userManifests } from './user/manifests.js'; +import { manifests as userRootManifests } from './user-root/manifests.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...userManifests]; +export const manifests: Array = [...userManifests, ...userRootManifests]; diff --git a/src/packages/user/user/user-root/manifests.ts b/src/packages/user/user/workspace/user-root/manifests.ts similarity index 86% rename from src/packages/user/user/user-root/manifests.ts rename to src/packages/user/user/workspace/user-root/manifests.ts index 96eea28eda..9cb07892d3 100644 --- a/src/packages/user/user/user-root/manifests.ts +++ b/src/packages/user/user/workspace/user-root/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_ROOT_ENTITY_TYPE } from '../entity.js'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ diff --git a/src/packages/user/user/user-root/user-root-workspace.element.ts b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts similarity index 100% rename from src/packages/user/user/user-root/user-root-workspace.element.ts rename to src/packages/user/user/workspace/user-root/user-root-workspace.element.ts From 24a9ae18aeb3b3bb4d910c340adefbf2d29bca8e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:40:31 +0200 Subject: [PATCH 138/322] add missing type --- src/packages/user/user/workspace/manifests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/user/user/workspace/manifests.ts b/src/packages/user/user/workspace/manifests.ts index 09e4d463e9..2208cee94d 100644 --- a/src/packages/user/user/workspace/manifests.ts +++ b/src/packages/user/user/workspace/manifests.ts @@ -1,5 +1,5 @@ import { manifests as userManifests } from './user/manifests.js'; import { manifests as userRootManifests } from './user-root/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...userManifests, ...userRootManifests]; +export const manifests: Array = [...userManifests, ...userRootManifests]; From 5a94f4d6c4cd90e4c9795772c1de2b2831eb71b0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:40:37 +0200 Subject: [PATCH 139/322] fix path --- .../user/workspace/user-root/user-root-workspace.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts index 6e286dada3..65ec9cd88c 100644 --- a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts +++ b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts @@ -1,4 +1,4 @@ -import { UMB_USER_COLLECTION_ALIAS } from '../collection/index.js'; +import { UMB_USER_COLLECTION_ALIAS } from '../../collection/index.js'; import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; From 7913258bedfcafe91fb68d85ecec1d96890b276e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:43:55 +0200 Subject: [PATCH 140/322] delete unused code --- ...orkspace-action-user-group-save.element.ts | 52 ------------------- 1 file changed, 52 deletions(-) delete mode 100644 src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts diff --git a/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts b/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts deleted file mode 100644 index 530c72b616..0000000000 --- a/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { UMB_USER_WORKSPACE_CONTEXT } from '../../../user/workspace/user/user-workspace.context-token.js'; -import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -// TODO: Revisit this component, it can be made via a kind with api instead. [NL] -// TODO: This seems like legacy code [NL] -@customElement('umb-workspace-action-user-group-save') -export class UmbWorkspaceActionUserGroupSaveElement extends UmbLitElement { - @state() - private _saveButtonState?: UUIButtonState; - - private _workspaceContext?: typeof UMB_USER_WORKSPACE_CONTEXT.TYPE; - - constructor() { - super(); - - this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (instance) => { - this._workspaceContext = instance; - }); - } - - private async _handleSave() { - if (!this._workspaceContext) return; - - this._saveButtonState = 'waiting'; - await this._workspaceContext - .requestSubmit() - .then(() => { - this._saveButtonState = 'success'; - }) - .catch(() => { - this._saveButtonState = 'failed'; - }); - } - - override render() { - return html``; - } -} - -export default UmbWorkspaceActionUserGroupSaveElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-workspace-action-user-group-save': UmbWorkspaceActionUserGroupSaveElement; - } -} From 7ab574eadf78991323ca32d46a486ca3d3c32020 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 16:04:02 +0200 Subject: [PATCH 141/322] set up entity context --- .../workspace/user-root/user-root-workspace.element.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts index 65ec9cd88c..2411336b55 100644 --- a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts +++ b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts @@ -1,10 +1,20 @@ import { UMB_USER_COLLECTION_ALIAS } from '../../collection/index.js'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; const elementName = 'umb-user-root-workspace'; @customElement(elementName) export class UmbUserRootWorkspaceElement extends UmbLitElement { + constructor() { + super(); + // TODO: this.should happen automatically + const entityContext = new UmbEntityContext(this); + entityContext.setEntityType(UMB_USER_ROOT_ENTITY_TYPE); + entityContext.setUnique(null); + } + override render() { return html` ; From 820305fea88dfaa0223521ef3c7dcb16b6e17a6d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 16:09:03 +0200 Subject: [PATCH 142/322] add invite entity action + clean up --- .../user/user/entity-actions/manifests.ts | 7 +---- .../invite/invite-user-entity-action.ts | 4 ++- .../entity-action}/invite/manifests.ts | 2 +- .../user/invite/entity-action/manifests.ts | 28 ++++--------------- .../entity-action/resend-invite/manifests.ts | 19 +++++++++++++ src/packages/user/user/invite/manifests.ts | 4 +-- 6 files changed, 31 insertions(+), 33 deletions(-) rename src/packages/user/user/{entity-actions => invite/entity-action}/invite/invite-user-entity-action.ts (70%) rename src/packages/user/user/{entity-actions => invite/entity-action}/invite/manifests.ts (88%) diff --git a/src/packages/user/user/entity-actions/manifests.ts b/src/packages/user/user/entity-actions/manifests.ts index 493f108ff1..f59da30aeb 100644 --- a/src/packages/user/user/entity-actions/manifests.ts +++ b/src/packages/user/user/entity-actions/manifests.ts @@ -2,7 +2,6 @@ import { UMB_USER_DETAIL_REPOSITORY_ALIAS, UMB_USER_ITEM_REPOSITORY_ALIAS } from import { UMB_USER_ENTITY_TYPE } from '../entity.js'; import { manifests as createManifests } from './create/manifests.js'; -import { manifests as inviteManifests } from './invite/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; @@ -97,8 +96,4 @@ const entityActions: Array = [ }, ]; -export const manifests: Array = [ - ...entityActions, - ...createManifests, - ...inviteManifests, -]; +export const manifests: Array = [...entityActions, ...createManifests]; diff --git a/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts b/src/packages/user/user/invite/entity-action/invite/invite-user-entity-action.ts similarity index 70% rename from src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts rename to src/packages/user/user/invite/entity-action/invite/invite-user-entity-action.ts index 4ac61a28d5..7d7f86ec79 100644 --- a/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts +++ b/src/packages/user/user/invite/entity-action/invite/invite-user-entity-action.ts @@ -1,10 +1,12 @@ +import { UMB_INVITE_USER_MODAL } from '../../index.js'; import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; export class UmbCreateUserEntityAction extends UmbEntityActionBase { override async execute() { const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - debugger; + const modalContext = modalManager.open(this, UMB_INVITE_USER_MODAL); + await modalContext?.onSubmit(); } } diff --git a/src/packages/user/user/entity-actions/invite/manifests.ts b/src/packages/user/user/invite/entity-action/invite/manifests.ts similarity index 88% rename from src/packages/user/user/entity-actions/invite/manifests.ts rename to src/packages/user/user/invite/entity-action/invite/manifests.ts index 0fc1e67e74..64ca8e8772 100644 --- a/src/packages/user/user/entity-actions/invite/manifests.ts +++ b/src/packages/user/user/invite/entity-action/invite/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../../entity.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/packages/user/user/invite/entity-action/manifests.ts b/src/packages/user/user/invite/entity-action/manifests.ts index af09b5ff79..0958868a9f 100644 --- a/src/packages/user/user/invite/entity-action/manifests.ts +++ b/src/packages/user/user/invite/entity-action/manifests.ts @@ -1,27 +1,9 @@ -import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; +import { manifests as inviteManifests } from './invite/manifests.js'; import { manifests as resendInviteManifests } from './resend-invite/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -const entityActions: Array = [ - { - type: 'entityAction', - kind: 'default', - alias: 'Umb.EntityAction.User.ResendInvite', - name: 'Resend Invite User Entity Action', - weight: 500, - api: () => import('./resend-invite/resend-invite.action.js'), - forEntityTypes: [UMB_USER_ENTITY_TYPE], - meta: { - icon: 'icon-message', - label: '#actions_resendInvite', - }, - conditions: [ - { - alias: 'Umb.Condition.User.AllowResendInviteAction', - }, - ], - }, +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + ...inviteManifests, ...resendInviteManifests, ]; - -export const manifests: Array = [...entityActions]; diff --git a/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts b/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts index 87dac3af79..1525273137 100644 --- a/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts +++ b/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts @@ -1,6 +1,25 @@ +import { UMB_USER_ENTITY_TYPE } from '../../../entity.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ + { + type: 'entityAction', + kind: 'default', + alias: 'Umb.EntityAction.User.ResendInvite', + name: 'Resend Invite User Entity Action', + weight: 500, + api: () => import('./resend-invite.action.js'), + forEntityTypes: [UMB_USER_ENTITY_TYPE], + meta: { + icon: 'icon-message', + label: '#actions_resendInvite', + }, + conditions: [ + { + alias: 'Umb.Condition.User.AllowResendInviteAction', + }, + ], + }, { type: 'condition', name: 'User Allow Resend Invite Action Condition', diff --git a/src/packages/user/user/invite/manifests.ts b/src/packages/user/user/invite/manifests.ts index 63b76f1ec9..3d56168a11 100644 --- a/src/packages/user/user/invite/manifests.ts +++ b/src/packages/user/user/invite/manifests.ts @@ -2,9 +2,9 @@ import { manifests as collectionActionManifests } from './collection-action/mani import { manifests as modalManifests } from './modal/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as entityActionManifests } from './entity-action/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ +export const manifests: Array = [ ...collectionActionManifests, ...modalManifests, ...repositoryManifests, From 3c3ca6034303e35e104b603af896f05436c4364f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 16:23:51 +0200 Subject: [PATCH 143/322] update user group create path --- src/packages/user/user-group/collection/action/manifests.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user-group/collection/action/manifests.ts b/src/packages/user/user-group/collection/action/manifests.ts index 1168e303e3..3f67cc84e1 100644 --- a/src/packages/user/user-group/collection/action/manifests.ts +++ b/src/packages/user/user-group/collection/action/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_USER_GROUP_WORKSPACE_PATH } from '../../paths.js'; import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; @@ -9,7 +10,7 @@ export const createManifest: ManifestTypes = { weight: 200, meta: { label: '#general_create', - href: 'section/user-management/view/user-groups/user-group/create', + href: `${UMB_USER_GROUP_WORKSPACE_PATH}/create`, }, conditions: [ { From 0ec4405ef47ca13afc4792f0c34b1ed5c8cac9e6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 08:09:54 +0200 Subject: [PATCH 144/322] rename folder --- src/packages/members/{member-section => section}/manifests.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/packages/members/{member-section => section}/manifests.ts (100%) diff --git a/src/packages/members/member-section/manifests.ts b/src/packages/members/section/manifests.ts similarity index 100% rename from src/packages/members/member-section/manifests.ts rename to src/packages/members/section/manifests.ts From dbfee9ccda2000db141897c15f04beb894edf9a3 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 12 Sep 2024 15:28:56 +0200 Subject: [PATCH 145/322] update lockfile --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 32788a9b07..5f5ada3f20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@umbraco-cms/backoffice", - "version": "14.3.0", + "version": "15.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@umbraco-cms/backoffice", - "version": "14.3.0", + "version": "15.0.0", "license": "MIT", "workspaces": [ "./src/packages/*" From d0d3cb356451fc654eb7521b16582bf1e5567ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 19:36:23 +0200 Subject: [PATCH 146/322] JSON Schema corrections --- src/packages/core/extension-registry/umbraco-package.ts | 4 ++-- src/packages/core/json-schema/umbraco-package.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 src/packages/core/json-schema/umbraco-package.ts diff --git a/src/packages/core/extension-registry/umbraco-package.ts b/src/packages/core/extension-registry/umbraco-package.ts index 3a05a2d7f0..19edb76a7f 100644 --- a/src/packages/core/extension-registry/umbraco-package.ts +++ b/src/packages/core/extension-registry/umbraco-package.ts @@ -1,4 +1,4 @@ -import type { ManifestTypes } from './models/index.js'; +import './models/index.js'; /** * Umbraco package manifest JSON @@ -37,7 +37,7 @@ export interface UmbracoPackage { * @title An array of Umbraco package manifest types that will be installed * @required */ - extensions: ManifestTypes[]; + extensions: UmbManifestTypes[]; /** * @title The importmap for the package diff --git a/src/packages/core/json-schema/umbraco-package.ts b/src/packages/core/json-schema/umbraco-package.ts new file mode 100644 index 0000000000..5be7369f5a --- /dev/null +++ b/src/packages/core/json-schema/umbraco-package.ts @@ -0,0 +1 @@ +export * from '@umbraco-cms/backoffice/extension-registry'; From 3c4de3d0d83f0a3835b312106d6e66a95b31bf4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 19:50:00 +0200 Subject: [PATCH 147/322] use UmbManifestTypes in extension registry --- src/packages/core/extension-registry/registry.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/packages/core/extension-registry/registry.ts b/src/packages/core/extension-registry/registry.ts index 09294be440..b29da72ae5 100644 --- a/src/packages/core/extension-registry/registry.ts +++ b/src/packages/core/extension-registry/registry.ts @@ -1,8 +1,7 @@ -import type { ManifestTypes } from './models/index.js'; import type { ManifestKind } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionRegistry } from '@umbraco-cms/backoffice/extension-api'; -export type UmbBackofficeManifestKind = ManifestKind; -export type UmbBackofficeExtensionRegistry = UmbExtensionRegistry; +export type UmbBackofficeManifestKind = ManifestKind; +export type UmbBackofficeExtensionRegistry = UmbExtensionRegistry; -export const umbExtensionsRegistry = new UmbExtensionRegistry() as UmbBackofficeExtensionRegistry; +export const umbExtensionsRegistry = new UmbExtensionRegistry() as UmbBackofficeExtensionRegistry; From 3a7c850dd4d01c2604f2d92f24fd46480891fa82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 19:55:24 +0200 Subject: [PATCH 148/322] JSDocs --- .../registry/extension.registry.ts | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 2680d599e9..a97c4f4d9c 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -6,8 +6,9 @@ import { map, distinctUntilChanged, combineLatest, of, switchMap } from '@umbrac /** * - * @param previousValue - * @param currentValue + * @param previousValue {Array} - previous value + * @param currentValue {Array} - current value + * @returns {boolean} - true if value is assumed to be the same as previous value. */ function extensionArrayMemoization>( previousValue: Array, @@ -26,8 +27,9 @@ function extensionArrayMemoization>( /** * - * @param previousValue - * @param currentValue + * @param previousValue {Array} - previous value + * @param currentValue {Array} - current value + * @returns {boolean} - true if value is assumed to be the same as previous value. */ function extensionAndKindMatchArrayMemoization< T extends Pick & { __isMatchedWithKind?: boolean }, @@ -57,8 +59,9 @@ function extensionAndKindMatchArrayMemoization< /** * - * @param previousValue - * @param currentValue + * @param previousValue {Array} - previous value + * @param currentValue {Array} - current value + * @returns {boolean} - true if value is assumed to be the same as previous value. */ function extensionSingleMemoization>( previousValue: T | undefined, @@ -72,8 +75,9 @@ function extensionSingleMemoization>( /** * - * @param previousValue - * @param currentValue + * @param previousValue {Array} - previous value + * @param currentValue {Array} - current value + * @returns {boolean} - true if value is assumed to be the same as previous value. */ function extensionAndKindMatchSingleMemoization< T extends Pick & { __isMatchedWithKind?: boolean }, From 6f0df55f3cdffb65412db644dc28eb319359a114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 20:38:05 +0200 Subject: [PATCH 149/322] import type --- src/libs/extension-api/registry/extension.registry.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index feb27191c8..7f1d48752a 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -1,4 +1,4 @@ -import { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; +import type { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; import type { ManifestElementWithElementName, ManifestKind, From 40fba5ba032ca91a4f07ec6b0a7c5d233a8d7958 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 21:58:23 +0200 Subject: [PATCH 150/322] revert merge mistake --- src/packages/settings/advanced/manifests.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packages/settings/advanced/manifests.ts b/src/packages/settings/advanced/manifests.ts index 3931a9edb9..5a452d9e3d 100644 --- a/src/packages/settings/advanced/manifests.ts +++ b/src/packages/settings/advanced/manifests.ts @@ -10,11 +10,11 @@ export const manifests = [ { type: 'sectionSidebarApp', kind: 'menu', - alias: 'Umb.SectionSidebarApp.Menu.Users', - name: 'Users Section Sidebar Menu', + alias: 'Umb.SectionSidebarMenu.AdvancedSettings', + name: 'Advanced Settings Sidebar Menu', weight: 100, meta: { - label: 'Users', + label: '#treeHeaders_advancedGroup', menu: UMB_ADVANCED_SETTINGS_MENU_ALIAS, }, conditions: [ From 46ec82674204832db9984eeee5b2c4d66f0b8ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 22:01:34 +0200 Subject: [PATCH 151/322] remove test code --- src/packages/property-editors/entry-point.ts | 47 -------------------- 1 file changed, 47 deletions(-) diff --git a/src/packages/property-editors/entry-point.ts b/src/packages/property-editors/entry-point.ts index f83895ac9b..9745b0d139 100644 --- a/src/packages/property-editors/entry-point.ts +++ b/src/packages/property-editors/entry-point.ts @@ -1,49 +1,2 @@ -import type { - ManifestWithDynamicConditions, - UmbConditionConfigBase, - UmbEntryPointOnInit, -} from '@umbraco-cms/backoffice/extension-api'; -import type { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; - import './checkbox-list/components/index.js'; import './content-picker/components/index.js'; - -export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { - - console.log('HELLO AGAIN'); - - const condition: UmbConditionConfigBase = { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.WARRENYO', - } as WorkspaceAliasConditionConfig; - - console.log( - 'Should not be false and not registered', - _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'), - ); - - _extensionRegistry.addCondition('Umb.Dashboard.UmbracoNewsLATE', condition); - - console.log('I HAZ ADDED CONDITION'); - - const ext: ManifestWithDynamicConditions = { - alias: 'Umb.Dashboard.UmbracoNewsLATE', - type: 'dashboard', - name: 'WARREN Package', - weight: 100, - conditions: [ - { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.LATE-COMER-EXISTING', - } as WorkspaceAliasConditionConfig, - ], - }; - - _extensionRegistry.register(ext); - - const amIRegistered = _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'); - console.log('Should be true and registered', amIRegistered); - - const getTheThing = _extensionRegistry.getByAlias('Umb.Dashboard.UmbracoNewsLATE'); - console.log('Should be the extension', getTheThing); -}; From d8c59cbc466ae48587c7b40e02037039db6ee07f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 22:01:45 +0200 Subject: [PATCH 152/322] refactor for a more direct appending implementation --- .../registry/extension.registry.test.ts | 164 +++++++++++++----- .../registry/extension.registry.ts | 120 ++++++------- 2 files changed, 178 insertions(+), 106 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 7f1d48752a..caed039f60 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -518,7 +518,7 @@ describe('Add Conditions', () => { const conditionToAdd: UmbConditionConfigBase = { alias: 'Umb.Test.Condition.Valid', }; - await extensionRegistry.addCondition('Umb.Test.Section.1', conditionToAdd); + await extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; @@ -529,13 +529,17 @@ describe('Add Conditions', () => { expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); expect(updatedExt.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + // Verify the other extension was not updated: + const otherExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; + expect(otherExt.conditions).to.be.undefined; + // Add a condition with a specific config to Section2 const workspaceCondition: WorkspaceAliasConditionConfig = { alias: 'Umb.Condition.WorkspaceAlias', match: 'Umb.Workspace.Document', }; - await extensionRegistry.addCondition('Umb.Test.Section.2', workspaceCondition); + await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); @@ -556,7 +560,7 @@ describe('Add Conditions', () => { } as WorkspaceAliasConditionConfig, ]; - await extensionRegistry.addConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(extUpdated.conditions?.length).to.equal(3); @@ -565,47 +569,115 @@ describe('Add Conditions', () => { expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); }); - // it('allows conditions to be prepended when an extension is loaded later on', async () => { - // const conditions: Array = [ - // { - // alias: 'Umb.Test.Condition.Invalid', - // }, - // { - // alias: 'Umb.Condition.WorkspaceAlias', - // match: 'Umb.Workspace.Document', - // } as WorkspaceAliasConditionConfig, - // ]; - - // console.log('About to go KABOOM..'); - - // // Prepend the conditions - // // [WB] HELP: Why is this fine when using in in an entrypoint - // // /src/packages/property-editors/entry-point.ts - // // But this TEST implodes if it can't find the extension that is not yet registered - // await extensionRegistry.addConditions('Late.Extension.To.Be.Loaded', conditions); - - // // Make sure the extension is not registered YET - // expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; - - // // Register the extension LATE/after the conditions have been added - // extensionRegistry.register({ - // type: 'section', - // name: 'Late Section Extension with one condition', - // alias: 'Late.Extension.To.Be.Loaded', - // weight: 200, - // conditions: [ - // { - // alias: 'Umb.Test.Condition.Valid', - // }, - // ], - // }); - - // expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; - - // const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; - // expect(extUpdated.conditions?.length).to.equal(3); - // expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - // expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); - // expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); - // }); + it('allows conditions to be prepended when an extension is loaded later on', async () => { + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Invalid', + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; + + // Prepend the conditions, but do not await this. + extensionRegistry.appendConditions('Late.Extension.To.Be.Loaded', conditions); + + // Make sure the extension is not registered YET + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // Register the extension LATE/after the conditions have been added + extensionRegistry.register({ + type: 'section', + name: 'Late Section Extension with one condition', + alias: 'Late.Extension.To.Be.Loaded', + weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], + }); + + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; + + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + }); + + /** + * As of current state, it is by design without further reasons to why, but it is made so additional conditions are only added to a current or next time registered manifest. + * Meaning if it happens to be unregistered and re-registered it does not happen again. + * Unless the exact same appending of conditions happens again. [NL] + * + * This makes sense if extensions gets offloaded and re-registered, but the extension that registered additional conditions didn't get loaded/registered second time. Therefor they need to be re-registered for such to work. [NL] + */ + it('only append conditions to the next time the extension is registered', async () => { + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Invalid', + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; + + // Prepend the conditions, but do not await this. + extensionRegistry.appendConditions('Late.Extension.To.Be.Loaded', conditions); + + // Make sure the extension is not registered YET + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // Register the extension LATE/after the conditions have been added + extensionRegistry.register({ + type: 'section', + name: 'Late Section Extension with one condition', + alias: 'Late.Extension.To.Be.Loaded', + weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], + }); + + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + const extUpdateFirstTime = extensionRegistry.getByAlias( + 'Late.Extension.To.Be.Loaded', + ) as ManifestWithDynamicConditions; + expect(extUpdateFirstTime.conditions?.length).to.equal(3); + + extensionRegistry.unregister('Late.Extension.To.Be.Loaded'); + + // Make sure the extension is not registered YET + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // Register the extension LATE/after the conditions have been added + extensionRegistry.register({ + type: 'section', + name: 'Late Section Extension with one condition', + alias: 'Late.Extension.To.Be.Loaded', + weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], + }); + + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + const extUpdateSecondTime = extensionRegistry.getByAlias( + 'Late.Extension.To.Be.Loaded', + ) as ManifestWithDynamicConditions; + + expect(extUpdateSecondTime.conditions?.length).to.equal(1); + expect(extUpdateSecondTime.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); }); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 26b483b032..e1535825a4 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -7,15 +7,7 @@ import type { import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import { - map, - distinctUntilChanged, - combineLatest, - of, - switchMap, - filter, - firstValueFrom, -} from '@umbraco-cms/backoffice/external/rxjs'; +import { map, distinctUntilChanged, combineLatest, of, switchMap } from '@umbraco-cms/backoffice/external/rxjs'; /** * @@ -113,8 +105,26 @@ export class UmbExtensionRegistry< private _kinds = new UmbBasicState>>([]); public readonly kinds = this._kinds.asObservable(); + #exclusions: Array = []; + #additionalConditions: Map> = new Map(); + #appendAdditionalConditions(manifest: ManifestTypes) { + const newConditions = this.#additionalConditions.get(manifest.alias); + if (newConditions) { + // Append the condition to the extensions conditions array + if ((manifest as ManifestWithDynamicConditions).conditions) { + for (const condition of newConditions) { + (manifest as ManifestWithDynamicConditions).conditions!.push(condition); + } + } else { + (manifest as ManifestWithDynamicConditions).conditions = newConditions; + } + this.#additionalConditions.delete(manifest.alias); + } + return manifest; + } + defineKind(kind: ManifestKind): void { const extensionsValues = this._extensions.getValue(); const extension = extensionsValues.find( @@ -149,12 +159,25 @@ export class UmbExtensionRegistry< }; register(manifest: ManifestTypes | ManifestKind): void { - const isValid = this.#checkExtension(manifest); + const isValid = this.#validateExtension(manifest); if (!isValid) { return; } - this._extensions.setValue([...this._extensions.getValue(), manifest as ManifestTypes]); + if (manifest.type === 'kind') { + this.defineKind(manifest as ManifestKind); + return; + } + + const isApproved = this.#isExtensionApproved(manifest); + if (!isApproved) { + return; + } + + this._extensions.setValue([ + ...this._extensions.getValue(), + this.#appendAdditionalConditions(manifest as ManifestTypes), + ]); } getAllExtensions(): Array { @@ -190,7 +213,7 @@ export class UmbExtensionRegistry< return false; } - #checkExtension(manifest: ManifestTypes | ManifestKind): boolean { + #validateExtension(manifest: ManifestTypes | ManifestKind): boolean { if (!manifest.type) { console.error(`Extension is missing type`, manifest); return false; @@ -201,11 +224,9 @@ export class UmbExtensionRegistry< return false; } - if (manifest.type === 'kind') { - this.defineKind(manifest as ManifestKind); - return false; - } - + return true; + } + #isExtensionApproved(manifest: ManifestTypes | ManifestKind): boolean { if (!this.#acceptExtension(manifest as ManifestTypes)) { return false; } @@ -445,60 +466,39 @@ export class UmbExtensionRegistry< } /** - * Returns a promise that resolves when the extension with the specified alias is found. - * @param alias {string} - The alias of the extension to wait for. - * @returns {Promise} - A promise that resolves with the extension. + * Append a new condition to an existing extension + * Useful to add a condition for example the Save And Publish workspace action shipped by core. + * @param {string} alias - The alias of the extension to append the condition to. + * @param {UmbConditionConfigBase} newCondition - The condition to append to the extension. */ - private async _whenExtensionAliasIsRegistered(alias: string): Promise { - const source = this.extensions.pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))); - const value = await firstValueFrom(source); - const ext = value.find((ext) => ext.alias === alias) as ManifestBase; - return ext; + appendCondition(alias: string, newCondition: UmbConditionConfigBase) { + this.appendConditions(alias, [newCondition]); } /** - * Add a new condition to an existing extension - * Useful to add a condition for example the Save And Publish workspace action shipped by core - * As overwriting the whole extension to simply add an extra condition is not ideal as it causes a lot of duplicated code - * and could easily get out of sync from the CMS core implementation if a 3rd party dev was to try and overwrite it - * @param alias {string} - The alias of the extension to append the condition to - * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. + * Appends an array of conditions to an existing extension + * @param {string} alias - The alias of the extension to append the condition to + * @param {Array} newConditions - An array of conditions to be appended to an extension manifest. */ - async addCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { - try { - // Wait for the extension to be registered (as it could be registered late) - const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - - // Append the condition to the extensions conditions array - if (extensionToWaitFor.conditions) { - extensionToWaitFor.conditions.push(newCondition); - } else { - extensionToWaitFor.conditions = [newCondition]; - } + appendConditions(alias: string, newConditions: Array) { + const existingConditionsToBeAdded = this.#additionalConditions.get(alias); + this.#additionalConditions.set( + alias, + existingConditionsToBeAdded ? [...existingConditionsToBeAdded, ...newConditions] : newConditions, + ); - const allExtensions = this._extensions.getValue(); - const extensionToUpdateIndex = allExtensions.findIndex((ext) => ext.alias === alias); - if (extensionToUpdateIndex !== -1) { + const allExtensions = this._extensions.getValue(); + for (const extension of allExtensions) { + if (extension.alias === alias) { // Replace the existing extension with the updated one - allExtensions[extensionToUpdateIndex] = extensionToWaitFor as ManifestTypes; + allExtensions[allExtensions.indexOf(extension)] = this.#appendAdditionalConditions(extension as ManifestTypes); // Update the main extensions collection/observable this._extensions.setValue(allExtensions); - } - } catch (error) { - // TODO: [WB] Will this ever catch an error? - console.error(`Extension with alias ${alias} was never found and threw ${error}`); - } - } - /** - * Adds a collection of conditions to an exsiting extension - * @param alias {string} - The alias of the extension to append the condition to - * @param newConditions {Array} - A collection of conditions to append to an extension. - */ - async addConditions(alias: string, newConditions: Array): Promise { - for (const condition of newConditions) { - await this.addCondition(alias, condition); + //Stop the search: + break; + } } } } From 68584832e6017353c73feb7fc3713f8940878394 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:48:41 +0200 Subject: [PATCH 153/322] move into folder --- .../user/user-group/workspace/manifests.ts | 44 ++----------------- ...oup-entity-user-permission-list.element.ts | 0 ...-group-granular-permission-list.element.ts | 0 .../workspace/{ => user-group}/constants.ts | 0 .../workspace/user-group/manifests.ts | 42 ++++++++++++++++++ .../user-group-workspace-editor.element.ts | 4 +- .../user-group-workspace.context-token.ts | 2 +- .../user-group-workspace.context.ts | 4 +- 8 files changed, 50 insertions(+), 46 deletions(-) rename src/packages/user/user-group/workspace/{ => user-group}/components/user-group-entity-user-permission-list.element.ts (100%) rename src/packages/user/user-group/workspace/{ => user-group}/components/user-group-granular-permission-list.element.ts (100%) rename src/packages/user/user-group/workspace/{ => user-group}/constants.ts (100%) create mode 100644 src/packages/user/user-group/workspace/user-group/manifests.ts rename src/packages/user/user-group/workspace/{ => user-group}/user-group-workspace-editor.element.ts (98%) rename src/packages/user/user-group/workspace/{ => user-group}/user-group-workspace.context-token.ts (89%) rename src/packages/user/user-group/workspace/{ => user-group}/user-group-workspace.context.ts (97%) diff --git a/src/packages/user/user-group/workspace/manifests.ts b/src/packages/user/user-group/workspace/manifests.ts index 4a593776bc..806ce0f556 100644 --- a/src/packages/user/user-group/workspace/manifests.ts +++ b/src/packages/user/user-group/workspace/manifests.ts @@ -1,42 +1,4 @@ -import type { - ManifestWorkspaces, - ManifestWorkspaceActions, - ManifestWorkspaceView, - ManifestTypes, -} from '@umbraco-cms/backoffice/extension-registry'; -import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import { manifests as userGroupManifests } from './user-group/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -const workspace: ManifestWorkspaces = { - type: 'workspace', - kind: 'routable', - alias: 'Umb.Workspace.UserGroup', - name: 'User Group Workspace', - api: () => import('./user-group-workspace.context.js'), - meta: { - entityType: 'user-group', - }, -}; - -const workspaceViews: Array = []; -const workspaceActions: Array = [ - { - type: 'workspaceAction', - kind: 'default', - alias: 'Umb.WorkspaceAction.UserGroup.Save', - name: 'Save User Group Workspace Action', - api: UmbSubmitWorkspaceAction, - meta: { - label: '#buttons_save', - look: 'primary', - color: 'positive', - }, - conditions: [ - { - alias: 'Umb.Condition.WorkspaceAlias', - match: workspace.alias, - }, - ], - }, -]; - -export const manifests: Array = [workspace, ...workspaceViews, ...workspaceActions]; +export const manifests: Array = [...userGroupManifests]; diff --git a/src/packages/user/user-group/workspace/components/user-group-entity-user-permission-list.element.ts b/src/packages/user/user-group/workspace/user-group/components/user-group-entity-user-permission-list.element.ts similarity index 100% rename from src/packages/user/user-group/workspace/components/user-group-entity-user-permission-list.element.ts rename to src/packages/user/user-group/workspace/user-group/components/user-group-entity-user-permission-list.element.ts diff --git a/src/packages/user/user-group/workspace/components/user-group-granular-permission-list.element.ts b/src/packages/user/user-group/workspace/user-group/components/user-group-granular-permission-list.element.ts similarity index 100% rename from src/packages/user/user-group/workspace/components/user-group-granular-permission-list.element.ts rename to src/packages/user/user-group/workspace/user-group/components/user-group-granular-permission-list.element.ts diff --git a/src/packages/user/user-group/workspace/constants.ts b/src/packages/user/user-group/workspace/user-group/constants.ts similarity index 100% rename from src/packages/user/user-group/workspace/constants.ts rename to src/packages/user/user-group/workspace/user-group/constants.ts diff --git a/src/packages/user/user-group/workspace/user-group/manifests.ts b/src/packages/user/user-group/workspace/user-group/manifests.ts new file mode 100644 index 0000000000..4a593776bc --- /dev/null +++ b/src/packages/user/user-group/workspace/user-group/manifests.ts @@ -0,0 +1,42 @@ +import type { + ManifestWorkspaces, + ManifestWorkspaceActions, + ManifestWorkspaceView, + ManifestTypes, +} from '@umbraco-cms/backoffice/extension-registry'; +import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; + +const workspace: ManifestWorkspaces = { + type: 'workspace', + kind: 'routable', + alias: 'Umb.Workspace.UserGroup', + name: 'User Group Workspace', + api: () => import('./user-group-workspace.context.js'), + meta: { + entityType: 'user-group', + }, +}; + +const workspaceViews: Array = []; +const workspaceActions: Array = [ + { + type: 'workspaceAction', + kind: 'default', + alias: 'Umb.WorkspaceAction.UserGroup.Save', + name: 'Save User Group Workspace Action', + api: UmbSubmitWorkspaceAction, + meta: { + label: '#buttons_save', + look: 'primary', + color: 'positive', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: workspace.alias, + }, + ], + }, +]; + +export const manifests: Array = [workspace, ...workspaceViews, ...workspaceActions]; diff --git a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts b/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts similarity index 98% rename from src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts rename to src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts index a4d129dd04..01835e7c2a 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts +++ b/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts @@ -1,5 +1,5 @@ -import type { UmbUserGroupDetailModel } from '../index.js'; -import { UMB_USER_GROUP_ROOT_WORKSPACE_PATH } from '../paths.js'; +import type { UmbUserGroupDetailModel } from '../../index.js'; +import { UMB_USER_GROUP_ROOT_WORKSPACE_PATH } from '../../paths.js'; import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from './user-group-workspace.context-token.js'; import { UMB_USER_GROUP_WORKSPACE_ALIAS } from './constants.js'; import type { UUIBooleanInputEvent } from '@umbraco-cms/backoffice/external/uui'; diff --git a/src/packages/user/user-group/workspace/user-group-workspace.context-token.ts b/src/packages/user/user-group/workspace/user-group/user-group-workspace.context-token.ts similarity index 89% rename from src/packages/user/user-group/workspace/user-group-workspace.context-token.ts rename to src/packages/user/user-group/workspace/user-group/user-group-workspace.context-token.ts index a09ae6a716..3a11176569 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace.context-token.ts +++ b/src/packages/user/user-group/workspace/user-group/user-group-workspace.context-token.ts @@ -1,4 +1,4 @@ -import { UMB_USER_GROUP_ENTITY_TYPE } from '../index.js'; +import { UMB_USER_GROUP_ENTITY_TYPE } from '../../index.js'; import type { UmbUserGroupWorkspaceContext } from './user-group-workspace.context.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/packages/user/user-group/workspace/user-group-workspace.context.ts b/src/packages/user/user-group/workspace/user-group/user-group-workspace.context.ts similarity index 97% rename from src/packages/user/user-group/workspace/user-group-workspace.context.ts rename to src/packages/user/user-group/workspace/user-group/user-group-workspace.context.ts index c360e2057f..6f81961747 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace.context.ts +++ b/src/packages/user/user-group/workspace/user-group/user-group-workspace.context.ts @@ -1,5 +1,5 @@ -import { UmbUserGroupDetailRepository } from '../repository/detail/index.js'; -import type { UmbUserGroupDetailModel } from '../types.js'; +import { UmbUserGroupDetailRepository } from '../../repository/detail/index.js'; +import type { UmbUserGroupDetailModel } from '../../types.js'; import { UmbUserGroupWorkspaceEditorElement } from './user-group-workspace-editor.element.js'; import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; import type { UmbRoutableWorkspaceContext, UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; From 0460d328965b9cce250e1aef4b01016b8b6b3b42 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:49:09 +0200 Subject: [PATCH 154/322] rename folder --- .../user-group/{section-view => user-group-root}/manifests.ts | 0 .../user-group-root-workspace.element.ts | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/packages/user/user-group/{section-view => user-group-root}/manifests.ts (100%) rename src/packages/user/user-group/{section-view => user-group-root}/user-group-root-workspace.element.ts (100%) diff --git a/src/packages/user/user-group/section-view/manifests.ts b/src/packages/user/user-group/user-group-root/manifests.ts similarity index 100% rename from src/packages/user/user-group/section-view/manifests.ts rename to src/packages/user/user-group/user-group-root/manifests.ts diff --git a/src/packages/user/user-group/section-view/user-group-root-workspace.element.ts b/src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts similarity index 100% rename from src/packages/user/user-group/section-view/user-group-root-workspace.element.ts rename to src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts From a9e19254290ec0e2eaaf37e72b5e316d046a456d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:49:35 +0200 Subject: [PATCH 155/322] move folder into workspace --- src/packages/user/user-group/manifests.ts | 2 +- .../user-group/{ => workspace}/user-group-root/manifests.ts | 2 +- .../user-group-root/user-group-root-workspace.element.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/packages/user/user-group/{ => workspace}/user-group-root/manifests.ts (86%) rename src/packages/user/user-group/{ => workspace}/user-group-root/user-group-root-workspace.element.ts (89%) diff --git a/src/packages/user/user-group/manifests.ts b/src/packages/user/user-group/manifests.ts index a68693f9c3..7db75cbebf 100644 --- a/src/packages/user/user-group/manifests.ts +++ b/src/packages/user/user-group/manifests.ts @@ -4,7 +4,7 @@ import { manifests as entityBulkActionManifests } from './entity-bulk-actions/ma import { manifests as menuItemManifests } from './menu-item/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; -import { manifests as sectionViewManifests } from './section-view/manifests.js'; +import { manifests as sectionViewManifests } from './workspace/user-group-root/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/packages/user/user-group/user-group-root/manifests.ts b/src/packages/user/user-group/workspace/user-group-root/manifests.ts similarity index 86% rename from src/packages/user/user-group/user-group-root/manifests.ts rename to src/packages/user/user-group/workspace/user-group-root/manifests.ts index ade0536011..ac7b088e93 100644 --- a/src/packages/user/user-group/user-group-root/manifests.ts +++ b/src/packages/user/user-group/workspace/user-group-root/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../entity.js'; +import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../../entity.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ diff --git a/src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts b/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts similarity index 89% rename from src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts rename to src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts index f02687d62d..0a77413d07 100644 --- a/src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts +++ b/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts @@ -1,4 +1,4 @@ -import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../collection/index.js'; +import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../../collection/index.js'; import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; From 2a15cddd0613ea1efdc16962c3050e5d6cf60f0d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:50:58 +0200 Subject: [PATCH 156/322] localize headline --- .../user-group-root/user-group-root-workspace.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts b/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts index 0a77413d07..0900cee472 100644 --- a/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts +++ b/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts @@ -6,7 +6,7 @@ const elementName = 'umb-user-group-root-workspace'; @customElement(elementName) export class UmbUserGroupRootWorkspaceElement extends UmbLitElement { override render() { - return html` + return html` ; `; } From 496b25f828527455674a7c00e6fae10f176fd862 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:56:11 +0200 Subject: [PATCH 157/322] localize header --- .../user/workspace/user-root/user-root-workspace.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts index 2411336b55..335f7b9590 100644 --- a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts +++ b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts @@ -16,7 +16,7 @@ export class UmbUserRootWorkspaceElement extends UmbLitElement { } override render() { - return html` + return html` ; `; } From 4925949f0f0035808a8831c420704473550aa0c7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 23:12:53 +0200 Subject: [PATCH 158/322] remove lorem ipsum --- .../create/modal/user-create-options-modal.element.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts b/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts index 29932ea273..74e8646990 100644 --- a/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts +++ b/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts @@ -9,7 +9,7 @@ import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/e interface UmbUserCreateOptionModel { label: string; - description: string; + description?: string; icon: string; kind: UmbUserKindType; } @@ -20,13 +20,11 @@ export class UmbUserCreateOptionsModalElement extends UmbModalBaseElement { #options: Array = [ { label: this.localize.term('user_userKindDefault'), - description: 'Donec augue nunc, ullamcorper non turpis ut, maximus facilisis lorem. Nunc id sagittis magna.', icon: 'icon-user', kind: UmbUserKind.DEFAULT, }, { label: this.localize.term('user_userKindApi'), - description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', icon: 'icon-unplug', kind: UmbUserKind.API, }, From c7b07f89b5d069fc545666a7c632a54b2121bddd Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 13 Sep 2024 07:24:56 +0200 Subject: [PATCH 159/322] register member management menu --- src/packages/members/manifests.ts | 5 ++-- src/packages/members/section/constants.ts | 1 + src/packages/members/section/index.ts | 1 + src/packages/members/section/manifests.ts | 19 +++++++++++---- .../members/section/menu/constants.ts | 1 + src/packages/members/section/menu/index.ts | 1 + .../members/section/menu/manifests.ts | 9 ++++++++ src/packages/members/section/paths.ts | 7 ++++++ .../members/section/sidebar-app/index.ts | 1 + .../members/section/sidebar-app/manifests.ts | 23 +++++++++++++++++++ 10 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 src/packages/members/section/constants.ts create mode 100644 src/packages/members/section/index.ts create mode 100644 src/packages/members/section/menu/constants.ts create mode 100644 src/packages/members/section/menu/index.ts create mode 100644 src/packages/members/section/menu/manifests.ts create mode 100644 src/packages/members/section/paths.ts create mode 100644 src/packages/members/section/sidebar-app/index.ts create mode 100644 src/packages/members/section/sidebar-app/manifests.ts diff --git a/src/packages/members/manifests.ts b/src/packages/members/manifests.ts index c5d00784c1..53aac2298d 100644 --- a/src/packages/members/manifests.ts +++ b/src/packages/members/manifests.ts @@ -1,7 +1,8 @@ import { manifests as memberGroupManifests } from './member-group/manifests.js'; import { manifests as memberManifests } from './member/manifests.js'; -import { manifests as memberSectionManifests } from './member-section/manifests.js'; import { manifests as memberTypeManifests } from './member-type/manifests.js'; +import { manifests as sectionManifests } from './section/manifests.js'; + import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; import './member/components/index.js'; @@ -10,6 +11,6 @@ import './member-group/components/index.js'; export const manifests: Array = [ ...memberGroupManifests, ...memberManifests, - ...memberSectionManifests, ...memberTypeManifests, + ...sectionManifests, ]; diff --git a/src/packages/members/section/constants.ts b/src/packages/members/section/constants.ts new file mode 100644 index 0000000000..afe1a32f6d --- /dev/null +++ b/src/packages/members/section/constants.ts @@ -0,0 +1 @@ +export const UMB_MEMBER_MANAGEMENT_SECTION_ALIAS = 'Umb.Section.Members'; diff --git a/src/packages/members/section/index.ts b/src/packages/members/section/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/members/section/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/members/section/manifests.ts b/src/packages/members/section/manifests.ts index b1563a290b..8b1493ab85 100644 --- a/src/packages/members/section/manifests.ts +++ b/src/packages/members/section/manifests.ts @@ -1,8 +1,15 @@ -import type { ManifestSection, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_MEMBER_MANAGEMENT_SECTION_ALIAS } from './constants.js'; +import { manifests as sectionSidebarAppManifests } from './sidebar-app/manifests.js'; +import { manifests as menuManifests } from './menu/manifests.js'; +import type { + ManifestSection, + ManifestTypes, + UmbBackofficeManifestKind, +} from '@umbraco-cms/backoffice/extension-registry'; const section: ManifestSection = { type: 'section', - alias: 'Umb.Section.Members', + alias: UMB_MEMBER_MANAGEMENT_SECTION_ALIAS, name: 'Members Section', weight: 500, meta: { @@ -12,9 +19,13 @@ const section: ManifestSection = { conditions: [ { alias: 'Umb.Condition.SectionUserPermission', - match: 'Umb.Section.Members', + match: UMB_MEMBER_MANAGEMENT_SECTION_ALIAS, }, ], }; -export const manifests: Array = [section]; +export const manifests: Array = [ + section, + ...sectionSidebarAppManifests, + ...menuManifests, +]; diff --git a/src/packages/members/section/menu/constants.ts b/src/packages/members/section/menu/constants.ts new file mode 100644 index 0000000000..c90a996f52 --- /dev/null +++ b/src/packages/members/section/menu/constants.ts @@ -0,0 +1 @@ +export const UMB_MEMBER_MANAGEMENT_MENU_ALIAS = 'Umb.Menu.MemberManagement'; diff --git a/src/packages/members/section/menu/index.ts b/src/packages/members/section/menu/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/members/section/menu/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/members/section/menu/manifests.ts b/src/packages/members/section/menu/manifests.ts new file mode 100644 index 0000000000..36cbd68c00 --- /dev/null +++ b/src/packages/members/section/menu/manifests.ts @@ -0,0 +1,9 @@ +import { UMB_MEMBER_MANAGEMENT_MENU_ALIAS } from './constants.js'; + +export const manifests = [ + { + type: 'menu', + alias: UMB_MEMBER_MANAGEMENT_MENU_ALIAS, + name: 'Member Management Menu', + }, +]; diff --git a/src/packages/members/section/paths.ts b/src/packages/members/section/paths.ts new file mode 100644 index 0000000000..27a89f53ce --- /dev/null +++ b/src/packages/members/section/paths.ts @@ -0,0 +1,7 @@ +import { UMB_SECTION_PATH_PATTERN } from '@umbraco-cms/backoffice/section'; + +export const UMB_MEMBER_MANAGEMENT_SECTION_PATHNAME = 'member-management'; + +export const UMB_MEMBER_MANAGEMENT_SECTION_PATH = UMB_SECTION_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_MEMBER_MANAGEMENT_SECTION_PATHNAME, +}); diff --git a/src/packages/members/section/sidebar-app/index.ts b/src/packages/members/section/sidebar-app/index.ts new file mode 100644 index 0000000000..42f853e5be --- /dev/null +++ b/src/packages/members/section/sidebar-app/index.ts @@ -0,0 +1 @@ +export * from '../constants.js'; diff --git a/src/packages/members/section/sidebar-app/manifests.ts b/src/packages/members/section/sidebar-app/manifests.ts new file mode 100644 index 0000000000..b96519e9ac --- /dev/null +++ b/src/packages/members/section/sidebar-app/manifests.ts @@ -0,0 +1,23 @@ +import { UMB_MEMBER_MANAGEMENT_SECTION_ALIAS } from '../constants.js'; +import { UMB_MEMBER_MANAGEMENT_MENU_ALIAS } from '../menu/index.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'sectionSidebarApp', + kind: 'menu', + alias: 'Umb.SectionSidebarApp.Menu.MemberManagement', + name: 'Member Management Menu Sidebar App', + weight: 100, + meta: { + label: '#treeHeaders_member', + menu: UMB_MEMBER_MANAGEMENT_MENU_ALIAS, + }, + conditions: [ + { + alias: 'Umb.Condition.SectionAlias', + match: UMB_MEMBER_MANAGEMENT_SECTION_ALIAS, + }, + ], + }, +]; From f59f33afebe9b3f11b2e876bfb875feae25a66a7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 13 Sep 2024 07:27:28 +0200 Subject: [PATCH 160/322] Register member menu item --- src/packages/members/member/manifests.ts | 2 ++ .../members/member/menu-item/manifests.ts | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/packages/members/member/menu-item/manifests.ts diff --git a/src/packages/members/member/manifests.ts b/src/packages/members/member/manifests.ts index 1a80cef0a9..8d5355e021 100644 --- a/src/packages/members/member/manifests.ts +++ b/src/packages/members/member/manifests.ts @@ -1,6 +1,7 @@ import { manifests as collectionManifests } from './collection/manifests.js'; import { manifests as entityActionManifests } from './entity-actions/manifests.js'; import { manifests as memberPickerModalManifests } from './components/member-picker-modal/manifests.js'; +import { manifests as menuItemManifests } from './menu-item/manifests.js'; import { manifests as pickerManifests } from './picker/manifests.js'; import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; @@ -14,6 +15,7 @@ export const manifests: Array = [ ...collectionManifests, ...entityActionManifests, ...memberPickerModalManifests, + ...menuItemManifests, ...pickerManifests, ...propertyEditorManifests, ...repositoryManifests, diff --git a/src/packages/members/member/menu-item/manifests.ts b/src/packages/members/member/menu-item/manifests.ts new file mode 100644 index 0000000000..0304866916 --- /dev/null +++ b/src/packages/members/member/menu-item/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_MEMBER_MANAGEMENT_MENU_ALIAS } from '../../section/menu/constants.js'; +import { UMB_MEMBER_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'menuItem', + alias: 'Umb.MenuItem.Members', + name: 'Members Menu Item', + weight: 200, + meta: { + label: '#treeHeaders_member', + icon: 'icon-user', + entityType: UMB_MEMBER_ROOT_ENTITY_TYPE, + menus: [UMB_MEMBER_MANAGEMENT_MENU_ALIAS], + }, + }, +]; From 8cb7ea62896481795d67630b691df0eaeebb628d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 13 Sep 2024 07:29:41 +0200 Subject: [PATCH 161/322] move member workspace into folder --- src/packages/members/member/manifests.ts | 2 +- src/packages/members/member/workspace/{ => member}/index.ts | 0 .../members/member/workspace/{ => member}/manifests.ts | 2 +- .../{ => member}/member-workspace-editor.element.ts | 2 +- .../{ => member}/member-workspace-split-view.element.ts | 0 .../{ => member}/member-workspace.context-token.ts | 0 .../workspace/{ => member}/member-workspace.context.ts | 6 +++--- .../member/member-workspace-view-member-info.element.ts | 2 +- .../views/member/member-workspace-view-member.element.ts | 2 +- .../member/workspace/{ => member}/views/member/utils.ts | 0 10 files changed, 8 insertions(+), 8 deletions(-) rename src/packages/members/member/workspace/{ => member}/index.ts (100%) rename src/packages/members/member/workspace/{ => member}/manifests.ts (97%) rename src/packages/members/member/workspace/{ => member}/member-workspace-editor.element.ts (98%) rename src/packages/members/member/workspace/{ => member}/member-workspace-split-view.element.ts (100%) rename src/packages/members/member/workspace/{ => member}/member-workspace.context-token.ts (100%) rename src/packages/members/member/workspace/{ => member}/member-workspace.context.ts (98%) rename src/packages/members/member/workspace/{ => member}/views/member/member-workspace-view-member-info.element.ts (99%) rename src/packages/members/member/workspace/{ => member}/views/member/member-workspace-view-member.element.ts (99%) rename src/packages/members/member/workspace/{ => member}/views/member/utils.ts (100%) diff --git a/src/packages/members/member/manifests.ts b/src/packages/members/member/manifests.ts index 8d5355e021..35ec8d5c58 100644 --- a/src/packages/members/member/manifests.ts +++ b/src/packages/members/member/manifests.ts @@ -7,7 +7,7 @@ import { manifests as propertyEditorManifests } from './property-editor/manifest import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as searchManifests } from './search/manifests.js'; import { manifests as sectionViewManifests } from './section-view/manifests.js'; -import { manifests as workspaceManifests } from './workspace/manifests.js'; +import { manifests as workspaceManifests } from './workspace/member/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/packages/members/member/workspace/index.ts b/src/packages/members/member/workspace/member/index.ts similarity index 100% rename from src/packages/members/member/workspace/index.ts rename to src/packages/members/member/workspace/member/index.ts diff --git a/src/packages/members/member/workspace/manifests.ts b/src/packages/members/member/workspace/member/manifests.ts similarity index 97% rename from src/packages/members/member/workspace/manifests.ts rename to src/packages/members/member/workspace/member/manifests.ts index c47595c8fc..fe71c5921d 100644 --- a/src/packages/members/member/workspace/manifests.ts +++ b/src/packages/members/member/workspace/member/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_MEMBER_ENTITY_TYPE } from '../entity.js'; +import { UMB_MEMBER_ENTITY_TYPE } from '../../entity.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; import type { ManifestWorkspaces, diff --git a/src/packages/members/member/workspace/member-workspace-editor.element.ts b/src/packages/members/member/workspace/member/member-workspace-editor.element.ts similarity index 98% rename from src/packages/members/member/workspace/member-workspace-editor.element.ts rename to src/packages/members/member/workspace/member/member-workspace-editor.element.ts index 5bbe5e974e..70aa290688 100644 --- a/src/packages/members/member/workspace/member-workspace-editor.element.ts +++ b/src/packages/members/member/workspace/member/member-workspace-editor.element.ts @@ -1,4 +1,4 @@ -import type { UmbMemberVariantOptionModel } from '../types.js'; +import type { UmbMemberVariantOptionModel } from '../../types.js'; import { UMB_MEMBER_WORKSPACE_CONTEXT } from './member-workspace.context-token.js'; import { UmbMemberWorkspaceSplitViewElement } from './member-workspace-split-view.element.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; diff --git a/src/packages/members/member/workspace/member-workspace-split-view.element.ts b/src/packages/members/member/workspace/member/member-workspace-split-view.element.ts similarity index 100% rename from src/packages/members/member/workspace/member-workspace-split-view.element.ts rename to src/packages/members/member/workspace/member/member-workspace-split-view.element.ts diff --git a/src/packages/members/member/workspace/member-workspace.context-token.ts b/src/packages/members/member/workspace/member/member-workspace.context-token.ts similarity index 100% rename from src/packages/members/member/workspace/member-workspace.context-token.ts rename to src/packages/members/member/workspace/member/member-workspace.context-token.ts diff --git a/src/packages/members/member/workspace/member-workspace.context.ts b/src/packages/members/member/workspace/member/member-workspace.context.ts similarity index 98% rename from src/packages/members/member/workspace/member-workspace.context.ts rename to src/packages/members/member/workspace/member/member-workspace.context.ts index f71c0c7b3c..fce275292b 100644 --- a/src/packages/members/member/workspace/member-workspace.context.ts +++ b/src/packages/members/member/workspace/member/member-workspace.context.ts @@ -1,6 +1,6 @@ -import { UmbMemberDetailRepository } from '../repository/index.js'; -import type { UmbMemberDetailModel, UmbMemberVariantModel, UmbMemberVariantOptionModel } from '../types.js'; -import { UmbMemberPropertyDatasetContext } from '../property-dataset-context/member-property-dataset-context.js'; +import { UmbMemberDetailRepository } from '../../repository/index.js'; +import type { UmbMemberDetailModel, UmbMemberVariantModel, UmbMemberVariantOptionModel } from '../../types.js'; +import { UmbMemberPropertyDatasetContext } from '../../property-dataset-context/member-property-dataset-context.js'; import { UMB_MEMBER_WORKSPACE_ALIAS } from './manifests.js'; import { UmbMemberWorkspaceEditorElement } from './member-workspace-editor.element.js'; import { type UmbMemberTypeDetailModel, UmbMemberTypeDetailRepository } from '@umbraco-cms/backoffice/member-type'; diff --git a/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts b/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts similarity index 99% rename from src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts rename to src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts index 4c3d0414c1..eb9c32af01 100644 --- a/src/packages/members/member/workspace/views/member/member-workspace-view-member-info.element.ts +++ b/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts @@ -1,6 +1,6 @@ // import { UMB_COMPOSITION_PICKER_MODAL, type UmbCompositionPickerModalData } from '../../../modals/index.js'; import { UMB_MEMBER_WORKSPACE_CONTEXT } from '../../member-workspace.context-token.js'; -import { UmbMemberKind, type UmbMemberKindType } from '../../../utils/index.js'; +import { UmbMemberKind, type UmbMemberKindType } from '../../../../utils/index.js'; import { TimeFormatOptions } from './utils.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; diff --git a/src/packages/members/member/workspace/views/member/member-workspace-view-member.element.ts b/src/packages/members/member/workspace/member/views/member/member-workspace-view-member.element.ts similarity index 99% rename from src/packages/members/member/workspace/views/member/member-workspace-view-member.element.ts rename to src/packages/members/member/workspace/member/views/member/member-workspace-view-member.element.ts index 8573a9b9c4..e313f80f6d 100644 --- a/src/packages/members/member/workspace/views/member/member-workspace-view-member.element.ts +++ b/src/packages/members/member/workspace/member/views/member/member-workspace-view-member.element.ts @@ -1,5 +1,5 @@ import { UMB_MEMBER_WORKSPACE_CONTEXT } from '../../member-workspace.context-token.js'; -import type { UmbMemberDetailModel } from '../../../types.js'; +import type { UmbMemberDetailModel } from '../../../../types.js'; import { TimeFormatOptions } from './utils.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state, when } from '@umbraco-cms/backoffice/external/lit'; diff --git a/src/packages/members/member/workspace/views/member/utils.ts b/src/packages/members/member/workspace/member/views/member/utils.ts similarity index 100% rename from src/packages/members/member/workspace/views/member/utils.ts rename to src/packages/members/member/workspace/member/views/member/utils.ts From a25b11ae41ec035e9e73b82b8a1049476b0dd1ec Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 13 Sep 2024 07:31:17 +0200 Subject: [PATCH 162/322] add manifest files --- src/packages/members/member/manifests.ts | 2 +- src/packages/members/member/workspace/manifests.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 src/packages/members/member/workspace/manifests.ts diff --git a/src/packages/members/member/manifests.ts b/src/packages/members/member/manifests.ts index 35ec8d5c58..8d5355e021 100644 --- a/src/packages/members/member/manifests.ts +++ b/src/packages/members/member/manifests.ts @@ -7,7 +7,7 @@ import { manifests as propertyEditorManifests } from './property-editor/manifest import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as searchManifests } from './search/manifests.js'; import { manifests as sectionViewManifests } from './section-view/manifests.js'; -import { manifests as workspaceManifests } from './workspace/member/manifests.js'; +import { manifests as workspaceManifests } from './workspace/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/packages/members/member/workspace/manifests.ts b/src/packages/members/member/workspace/manifests.ts new file mode 100644 index 0000000000..50b3efff3e --- /dev/null +++ b/src/packages/members/member/workspace/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as memberManifests } from './member/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...memberManifests]; From cccb5d3f46e79e83af19446a3b94115448636693 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 13 Sep 2024 07:37:34 +0200 Subject: [PATCH 163/322] change section view to workspace --- src/packages/members/member/manifests.ts | 2 - .../members/member/section-view/manifests.ts | 24 -------- .../member-section-view.element.ts | 61 ------------------- .../members/member/workspace/manifests.ts | 3 +- .../member/workspace/member-root/manifests.ts | 14 +++++ .../member-root-workspace.element.ts | 31 ++++++++++ 6 files changed, 47 insertions(+), 88 deletions(-) delete mode 100644 src/packages/members/member/section-view/manifests.ts delete mode 100644 src/packages/members/member/section-view/member-section-view.element.ts create mode 100644 src/packages/members/member/workspace/member-root/manifests.ts create mode 100644 src/packages/members/member/workspace/member-root/member-root-workspace.element.ts diff --git a/src/packages/members/member/manifests.ts b/src/packages/members/member/manifests.ts index 8d5355e021..a56f825196 100644 --- a/src/packages/members/member/manifests.ts +++ b/src/packages/members/member/manifests.ts @@ -6,7 +6,6 @@ import { manifests as pickerManifests } from './picker/manifests.js'; import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as searchManifests } from './search/manifests.js'; -import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; @@ -20,6 +19,5 @@ export const manifests: Array = [ ...propertyEditorManifests, ...repositoryManifests, ...searchManifests, - ...sectionViewManifests, ...workspaceManifests, ]; diff --git a/src/packages/members/member/section-view/manifests.ts b/src/packages/members/member/section-view/manifests.ts deleted file mode 100644 index da16766f81..0000000000 --- a/src/packages/members/member/section-view/manifests.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; - -const sectionsViews: Array = [ - { - type: 'sectionView', - alias: 'Umb.SectionView.Member', - name: 'Member Section View', - js: () => import('./member-section-view.element.js'), - weight: 200, - meta: { - label: '#treeHeaders_member', - pathname: 'members', - icon: 'icon-user', - }, - conditions: [ - { - alias: 'Umb.Condition.SectionAlias', - match: 'Umb.Section.Members', - }, - ], - }, -]; - -export const manifests: Array = [...sectionsViews]; diff --git a/src/packages/members/member/section-view/member-section-view.element.ts b/src/packages/members/member/section-view/member-section-view.element.ts deleted file mode 100644 index c5ed738500..0000000000 --- a/src/packages/members/member/section-view/member-section-view.element.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { UMB_MEMBER_COLLECTION_ALIAS } from '../collection/manifests.js'; -import { UMB_MEMBER_ENTITY_TYPE } from '../entity.js'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbRoute } from '@umbraco-cms/backoffice/router'; - -@customElement('umb-member-section-view') -export class UmbMemberSectionViewElement extends UmbLitElement { - #routes: UmbRoute[] = [ - { - path: 'collection', - component: () => { - const element = document.createElement('umb-collection'); - element.setAttribute('alias', UMB_MEMBER_COLLECTION_ALIAS); - return element; - }, - }, - { - path: 'member', - component: () => { - const element = document.createElement('umb-workspace'); - element.setAttribute('entityType', UMB_MEMBER_ENTITY_TYPE); - return element; - }, - }, - { - path: '', - redirectTo: 'collection', - }, - { - path: `**`, - component: async () => (await import('@umbraco-cms/backoffice/router')).UmbRouteNotFoundElement, - }, - ]; - - override render() { - return html``; - } - - static override styles = [ - UmbTextStyles, - css` - :host { - height: 100%; - } - - #router-slot { - height: calc(100% - var(--umb-header-layout-height)); - } - `, - ]; -} - -export default UmbMemberSectionViewElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-member-section-view': UmbMemberSectionViewElement; - } -} diff --git a/src/packages/members/member/workspace/manifests.ts b/src/packages/members/member/workspace/manifests.ts index 50b3efff3e..f89d6870b8 100644 --- a/src/packages/members/member/workspace/manifests.ts +++ b/src/packages/members/member/workspace/manifests.ts @@ -1,4 +1,5 @@ import { manifests as memberManifests } from './member/manifests.js'; +import { manifests as memberRootManifests } from './member-root/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...memberManifests]; +export const manifests: Array = [...memberManifests, ...memberRootManifests]; diff --git a/src/packages/members/member/workspace/member-root/manifests.ts b/src/packages/members/member/workspace/member-root/manifests.ts new file mode 100644 index 0000000000..62b3d161d0 --- /dev/null +++ b/src/packages/members/member/workspace/member-root/manifests.ts @@ -0,0 +1,14 @@ +import { UMB_MEMBER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'workspace', + alias: 'Umb.Workspace.MemberRoot', + name: 'Member Root Workspace View', + element: () => import('./member-root-workspace.element.js'), + meta: { + entityType: UMB_MEMBER_ROOT_ENTITY_TYPE, + }, + }, +]; diff --git a/src/packages/members/member/workspace/member-root/member-root-workspace.element.ts b/src/packages/members/member/workspace/member-root/member-root-workspace.element.ts new file mode 100644 index 0000000000..7095f17e2d --- /dev/null +++ b/src/packages/members/member/workspace/member-root/member-root-workspace.element.ts @@ -0,0 +1,31 @@ +import { UMB_MEMBER_COLLECTION_ALIAS } from '../../collection/index.js'; +import { UMB_MEMBER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; +import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +const elementName = 'umb-member-root-workspace'; +@customElement(elementName) +export class UmbMemberRootWorkspaceElement extends UmbLitElement { + constructor() { + super(); + // TODO: this.should happen automatically + const entityContext = new UmbEntityContext(this); + entityContext.setEntityType(UMB_MEMBER_ROOT_ENTITY_TYPE); + entityContext.setUnique(null); + } + + override render() { + return html` + ; + `; + } +} + +export { UmbMemberRootWorkspaceElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbMemberRootWorkspaceElement; + } +} From 8cc14525a9c86d321f9dd386b6340770ae734603 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 22 Aug 2024 16:50:16 +0000 Subject: [PATCH 164/322] Adds new method to extensionRegistry for appendCondition --- .../registry/extension.registry.test.ts | 83 ++++++++++++++++++- .../registry/extension.registry.ts | 29 ++++++- 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 83ee09d37b..0ad82590b7 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -1,4 +1,5 @@ -import type { ManifestElementWithElementName, ManifestKind, ManifestBase } from '../types/index.js'; +import { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; +import type { ManifestElementWithElementName, ManifestKind, ManifestBase, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; import { UmbExtensionRegistry } from './extension.registry.js'; import { expect } from '@open-wc/testing'; @@ -453,3 +454,83 @@ describe('UmbExtensionRegistry with exclusions', () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.Late')).to.be.false; }); }); + +describe('Append Conditions', () => { + let extensionRegistry: UmbExtensionRegistry; + let manifests: Array< + ManifestWithDynamicConditions + >; + + beforeEach(() => { + extensionRegistry = new UmbExtensionRegistry(); + manifests = [ + { + type: 'section', + name: 'test-section-1', + alias: 'Umb.Test.Section.1', + weight: 1, + conditions: [ + { + alias: "Umb.Test.Condition.Valid" + } + ] + }, + { + type: 'section', + name: 'test-section-2', + alias: 'Umb.Test.Section.2', + weight: 200 + }, + ]; + + manifests.forEach((manifest) => extensionRegistry.register(manifest)); + + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid' + }); + }); + + + it('allows an extension condition to be updated', () => { + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; + + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + // Register new condition as if I was in my own entrypoint + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-valid', + alias: 'Umb.Test.Condition.Valid' + }); + + // Add the new condition to the extension + const conditionToAdd:UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid' + }; + extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); + + // Check new condition is registered + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + + // Verify the extension now has two conditions + const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(updatedExt.conditions?.length).to.equal(2); + + // Add a condition with a specific config to Section2 + const workspaceCondition:WorkspaceAliasConditionConfig = { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document' + + }; + extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); + + const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; + expect(updatedWorkspaceExt.conditions?.length).to.equal(1); + }); +}); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index a97c4f4d9c..cb47923bc2 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -1,4 +1,4 @@ -import type { ManifestBase, ManifestKind } from '../types/index.js'; +import type { ManifestBase, ManifestKind, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; @@ -434,4 +434,31 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } + + /** + * Appends a new condition to an existing extension + * Useful to add a condition for example the Save And Publish workspace action shipped by core + * As overwriting the whole extension to simply add an extra condition is not ideal as it causes a lot of duplicated code + * and could easily get out of sync from the CMS core implementation if a 3rd party dev was to try and overwrite it + * @param alias {string} - The alias of the extension to get. + * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. + */ + appendCondition(alias: string, newCondition: UmbConditionConfigBase) { + const allExtensions = this._extensions.getValue(); + const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + + if(extensionToUpdate === undefined) { + console.error(`Extension with alias ${alias} not found`); + } + + // Append the condition to the extensions conditions array + if (extensionToUpdate.conditions){ + extensionToUpdate.conditions.push(newCondition); + } else { + extensionToUpdate.conditions = [newCondition]; + } + + // Update the extensions observable + this._extensions.setValue(allExtensions); + } } From 64e80ce3f520c0c99dc24a0451ac44c6ce2ca75f Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 23 Aug 2024 09:57:11 +0000 Subject: [PATCH 165/322] Adds appendConditions to allow adding multiple in one go --- .../registry/extension.registry.test.ts | 20 +++++++++++++++++++ .../registry/extension.registry.ts | 11 +++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 0ad82590b7..f6add8c5c2 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -533,4 +533,24 @@ describe('Append Conditions', () => { const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); }); + + it('allows an extension to update with multiple conditions', () => { + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + const conditions:Array = [ + { + alias: 'Umb.Test.Condition.Valid' + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document' + } as WorkspaceAliasConditionConfig + ] + + extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); + + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(3); + }); }); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index cb47923bc2..e776d131f2 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -440,7 +440,7 @@ export class UmbExtensionRegistry< * Useful to add a condition for example the Save And Publish workspace action shipped by core * As overwriting the whole extension to simply add an extra condition is not ideal as it causes a lot of duplicated code * and could easily get out of sync from the CMS core implementation if a 3rd party dev was to try and overwrite it - * @param alias {string} - The alias of the extension to get. + * @param alias {string} - The alias of the extension to append the condition to * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. */ appendCondition(alias: string, newCondition: UmbConditionConfigBase) { @@ -461,4 +461,13 @@ export class UmbExtensionRegistry< // Update the extensions observable this._extensions.setValue(allExtensions); } + + /** + * Appends a collection of conditions to an exsiting extension + * @param alias {string} - The alias of the extension to append the condition to + * @param newConditions {Array} - A collection of conditions to append to an extension. + */ + appendConditions(alias: string, newConditions: Array){ + newConditions.forEach((condition) => this.appendCondition(alias, condition)); + } } From b6db37359359ec7d3a8adedddb46762b0e9d9fab Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 29 Aug 2024 11:10:48 +0000 Subject: [PATCH 166/322] Adds prependCondition and prependConditions so you can make sure your condition loads first, as order of conditions are important --- .../registry/extension.registry.test.ts | 89 +++++++++++++++++++ .../registry/extension.registry.ts | 48 ++++++++-- 2 files changed, 132 insertions(+), 5 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index f6add8c5c2..9add871f65 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -554,3 +554,92 @@ describe('Append Conditions', () => { expect(ext.conditions?.length).to.equal(3); }); }); + +describe('Prepend Conditions', () => { + let extensionRegistry: UmbExtensionRegistry; + let manifests: Array; + + beforeEach(() => { + extensionRegistry = new UmbExtensionRegistry(); + manifests = [ + { + type: 'section', + name: 'test-section-1', + alias: 'Umb.Test.Section.1', + weight: 1, + conditions: [ + { + alias: "Umb.Test.Condition.Valid" + } + ] + }, + { + type: 'section', + name: 'test-section-2', + alias: 'Umb.Test.Section.2', + weight: 200 + }, + ]; + + manifests.forEach((manifest) => extensionRegistry.register(manifest)); + + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid' + }); + }); + + it('allows an extension condition to be prepended', () => { + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; + + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + // Register new condition as if I was in my own entrypoint + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-valid', + alias: 'Umb.Test.Condition.Valid' + }); + + // Prepend the new condition to the extension + const conditionToPrepend: UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid' + }; + extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); + + // Check new condition is registered + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + + // Verify the extension now has two conditions and the new condition is prepended + const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(updatedExt.conditions?.length).to.equal(2); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); + + it('allows an extension to update with multiple prepended conditions', () => { + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Valid' + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document' + } as WorkspaceAliasConditionConfig + ]; + + extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); +}); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index e776d131f2..ed142671ac 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -1,4 +1,9 @@ -import type { ManifestBase, ManifestKind, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; +import type { + ManifestBase, + ManifestKind, + ManifestWithDynamicConditions, + UmbConditionConfigBase, +} from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; @@ -434,7 +439,7 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } - + /** * Appends a new condition to an existing extension * Useful to add a condition for example the Save And Publish workspace action shipped by core @@ -447,12 +452,12 @@ export class UmbExtensionRegistry< const allExtensions = this._extensions.getValue(); const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; - if(extensionToUpdate === undefined) { + if (extensionToUpdate === undefined) { console.error(`Extension with alias ${alias} not found`); } // Append the condition to the extensions conditions array - if (extensionToUpdate.conditions){ + if (extensionToUpdate.conditions) { extensionToUpdate.conditions.push(newCondition); } else { extensionToUpdate.conditions = [newCondition]; @@ -467,7 +472,40 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to append the condition to * @param newConditions {Array} - A collection of conditions to append to an extension. */ - appendConditions(alias: string, newConditions: Array){ + appendConditions(alias: string, newConditions: Array) { newConditions.forEach((condition) => this.appendCondition(alias, condition)); } + + /** + * Prepends a new condition to an existing extension + * @param alias {string} - The alias of the extension to prepend the condition to + * @param newCondition {UmbConditionConfigBase} - The condition to prepend to the extension. + */ + prependCondition(alias: string, newCondition: UmbConditionConfigBase) { + const allExtensions = this._extensions.getValue(); + const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + + if (extensionToUpdate === undefined) { + console.error(`Extension with alias ${alias} not found`); + } + + // Prepend the condition to the extensions conditions array + if (extensionToUpdate.conditions) { + extensionToUpdate.conditions.unshift(newCondition); + } else { + extensionToUpdate.conditions = [newCondition]; + } + + // Update the extensions observable + this._extensions.setValue(allExtensions); + } + + /** + * Prepends a collection of conditions to an existing extension + * @param alias {string} - The alias of the extension to prepend the conditions to + * @param newConditions {Array} - A collection of conditions to prepend to an extension. + */ + prependConditions(alias: string, newConditions: Array) { + newConditions.forEach((condition) => this.prependCondition(alias, condition)); + } } From 2c0896335fae77fe97ddcede41d6e7bcc4da77b2 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 29 Aug 2024 16:14:06 +0000 Subject: [PATCH 167/322] Adds _whenExtensionAliasIsRegistered as a promise so that we basically wait until the manifest is registered so late extensions will work as well Seems to work with my hack in an entrypoint and the console logs the extension with the updated condition but its the tests I am struggling to get to work. As this code is heavily worked from me trying to Google, read RXJS docs and talking with Copilot I am not fully in confident in this approach --- .../registry/extension.registry.test.ts | 19 +-- .../registry/extension.registry.ts | 114 +++++++++++++----- src/packages/property-editors/entry-point.ts | 31 +++++ 3 files changed, 123 insertions(+), 41 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 9add871f65..94c5fccbf5 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -493,7 +493,7 @@ describe('Append Conditions', () => { }); - it('allows an extension condition to be updated', () => { + it('allows an extension condition to be updated', async () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; @@ -513,7 +513,7 @@ describe('Append Conditions', () => { const conditionToAdd:UmbConditionConfigBase = { alias: 'Umb.Test.Condition.Valid' }; - extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); + await extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; @@ -528,13 +528,13 @@ describe('Append Conditions', () => { match: 'Umb.Workspace.Document' }; - extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); + await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); }); - it('allows an extension to update with multiple conditions', () => { + it('allows an extension to update with multiple conditions', async () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); @@ -548,7 +548,7 @@ describe('Append Conditions', () => { } as WorkspaceAliasConditionConfig ] - extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(3); @@ -590,7 +590,7 @@ describe('Prepend Conditions', () => { }); }); - it('allows an extension condition to be prepended', () => { + it('allows an extension condition to be prepended', async () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; @@ -610,7 +610,8 @@ describe('Prepend Conditions', () => { const conditionToPrepend: UmbConditionConfigBase = { alias: 'Umb.Test.Condition.Valid' }; - extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); + + await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; @@ -621,7 +622,7 @@ describe('Prepend Conditions', () => { expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); }); - it('allows an extension to update with multiple prepended conditions', () => { + it('allows an extension to update with multiple prepended conditions', async () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); @@ -635,7 +636,7 @@ describe('Prepend Conditions', () => { } as WorkspaceAliasConditionConfig ]; - extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(extUpdated.conditions?.length).to.equal(3); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index ed142671ac..19c9701a0a 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -6,8 +6,8 @@ import type { } from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; -import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import { map, distinctUntilChanged, combineLatest, of, switchMap } from '@umbraco-cms/backoffice/external/rxjs'; +import type { Observable, Subscription } from '@umbraco-cms/backoffice/external/rxjs'; +import { map, distinctUntilChanged, combineLatest, of, switchMap, filter } from '@umbraco-cms/backoffice/external/rxjs'; /** * @@ -440,6 +440,37 @@ export class UmbExtensionRegistry< ) as Observable>; } + + /** + * Returns a promise that resolves when the extension with the specified alias is found. + * @param alias {string} - The alias of the extension to wait for. + * @returns {Promise} - A promise that resolves with the extension. + */ + private _whenExtensionAliasIsRegistered(alias: string): Promise { + return new Promise((resolve, reject) => { + const subscription: Subscription = this.extensions + .pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))) + .subscribe({ + next: (allExtensions) => { + console.log('I AM IN NEXT', allExtensions); + const extension = allExtensions.find((ext) => ext.alias === alias); + if (extension) { + subscription.unsubscribe(); + resolve(extension as ManifestBase); + } + }, + error: (error) => { + console.error('I AM IN ERROR', error); + reject(error); + }, + complete: () => { + console.log('I AM IN COMPLETE'); + reject(new Error(`Extension with alias ${alias} not found`)); + }, + }); + }); + } + /** * Appends a new condition to an existing extension * Useful to add a condition for example the Save And Publish workspace action shipped by core @@ -448,23 +479,39 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to append the condition to * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. */ - appendCondition(alias: string, newCondition: UmbConditionConfigBase) { - const allExtensions = this._extensions.getValue(); - const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + async appendCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { + try { - if (extensionToUpdate === undefined) { - console.error(`Extension with alias ${alias} not found`); - } + // Wait for the extension to be registered (as it could be registered late) + const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - // Append the condition to the extensions conditions array - if (extensionToUpdate.conditions) { - extensionToUpdate.conditions.push(newCondition); - } else { - extensionToUpdate.conditions = [newCondition]; - } + // Got it... now carry on & mutate it + console.log('got the extension to update/mutate', extensionToWaitFor); + + // Append the condition to the extensions conditions array + if (extensionToWaitFor.conditions) { + extensionToWaitFor.conditions.push(newCondition); + } else { + extensionToWaitFor.conditions = [newCondition]; + } - // Update the extensions observable - this._extensions.setValue(allExtensions); + const allExtensions = this._extensions.getValue(); + const extensionToUpdateIndex = allExtensions.findIndex((ext) => ext.alias === alias); + if (extensionToUpdateIndex !== -1) { + // Replace the existing extension with the updated one + allExtensions[extensionToUpdateIndex] = extensionToWaitFor as ManifestTypes; + + // Update the main extensions collection/observable + this._extensions.setValue(allExtensions); + + // Log the updated extensions for debugging + console.log('UPDATED extensions:', this._extensions.getValue()); + console.table(this._extensions.getValue()); + } + } catch (error) { + // TODO: [WB] Will this ever catch an error? + console.error(`Extension with alias ${alias} was never found and threw ${error}`); + } } /** @@ -472,7 +519,7 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to append the condition to * @param newConditions {Array} - A collection of conditions to append to an extension. */ - appendConditions(alias: string, newConditions: Array) { + async appendConditions(alias: string, newConditions: Array): Promise { newConditions.forEach((condition) => this.appendCondition(alias, condition)); } @@ -481,23 +528,26 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to prepend the condition to * @param newCondition {UmbConditionConfigBase} - The condition to prepend to the extension. */ - prependCondition(alias: string, newCondition: UmbConditionConfigBase) { - const allExtensions = this._extensions.getValue(); - const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + async prependCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { + try { - if (extensionToUpdate === undefined) { - console.error(`Extension with alias ${alias} not found`); - } + // Wait for the extension to be registered (as it could be registered late) + const extensionToUpdate = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - // Prepend the condition to the extensions conditions array - if (extensionToUpdate.conditions) { - extensionToUpdate.conditions.unshift(newCondition); - } else { - extensionToUpdate.conditions = [newCondition]; - } + // Got it... now carry on & mutate it + console.log('got the extension to update/mutate', extensionToUpdate); + + // Append the condition to the extensions conditions array + if (extensionToUpdate.conditions) { + extensionToUpdate.conditions.unshift(newCondition); + } else { + extensionToUpdate.conditions = [newCondition]; + } - // Update the extensions observable - this._extensions.setValue(allExtensions); + } catch (error) { + // TODO: [WB] Will this ever catch an error? + console.error(`Extension with alias ${alias} was never found and threw ${error}`); + } } /** @@ -505,7 +555,7 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to prepend the conditions to * @param newConditions {Array} - A collection of conditions to prepend to an extension. */ - prependConditions(alias: string, newConditions: Array) { + async prependConditions(alias: string, newConditions: Array): Promise { newConditions.forEach((condition) => this.prependCondition(alias, condition)); } } diff --git a/src/packages/property-editors/entry-point.ts b/src/packages/property-editors/entry-point.ts index 9745b0d139..baafe2af43 100644 --- a/src/packages/property-editors/entry-point.ts +++ b/src/packages/property-editors/entry-point.ts @@ -1,2 +1,33 @@ +import type { ManifestWithDynamicConditions, UmbConditionConfigBase, UmbEntryPointOnInit } from '@umbraco-cms/backoffice/extension-api'; +import type { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; + import './checkbox-list/components/index.js'; import './content-picker/components/index.js'; + +export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { + + console.log('HELLO AGAIN'); + + const condition: UmbConditionConfigBase = { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.WARRENYO', + } as WorkspaceAliasConditionConfig; + + _extensionRegistry.appendCondition('Umb.Dashboard.UmbracoNewsLATE', condition); + + const ext:ManifestWithDynamicConditions = { + alias: 'Umb.Dashboard.UmbracoNewsLATE', + type: 'dashboard', + name: 'WARREN Package', + weight: 100, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.LATE-COMER-EXISTING', + } as WorkspaceAliasConditionConfig, + ], + }; + + _extensionRegistry.register(ext); + +}; From e2153992a7f2fdc1fa375ff046ef2142a8fad622 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 10:19:27 +0200 Subject: [PATCH 168/322] simplify _whenExtensionAliasIsRegistered --- .../registry/extension.registry.ts | 43 ++++++------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 19c9701a0a..7e482d9d71 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -6,8 +6,16 @@ import type { } from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; -import type { Observable, Subscription } from '@umbraco-cms/backoffice/external/rxjs'; -import { map, distinctUntilChanged, combineLatest, of, switchMap, filter } from '@umbraco-cms/backoffice/external/rxjs'; +import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; +import { + map, + distinctUntilChanged, + combineLatest, + of, + switchMap, + filter, + firstValueFrom, +} from '@umbraco-cms/backoffice/external/rxjs'; /** * @@ -440,35 +448,15 @@ export class UmbExtensionRegistry< ) as Observable>; } - /** * Returns a promise that resolves when the extension with the specified alias is found. * @param alias {string} - The alias of the extension to wait for. * @returns {Promise} - A promise that resolves with the extension. */ - private _whenExtensionAliasIsRegistered(alias: string): Promise { - return new Promise((resolve, reject) => { - const subscription: Subscription = this.extensions - .pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))) - .subscribe({ - next: (allExtensions) => { - console.log('I AM IN NEXT', allExtensions); - const extension = allExtensions.find((ext) => ext.alias === alias); - if (extension) { - subscription.unsubscribe(); - resolve(extension as ManifestBase); - } - }, - error: (error) => { - console.error('I AM IN ERROR', error); - reject(error); - }, - complete: () => { - console.log('I AM IN COMPLETE'); - reject(new Error(`Extension with alias ${alias} not found`)); - }, - }); - }); + private async _whenExtensionAliasIsRegistered(alias: string): Promise { + const source = this.extensions.pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))); + const value = await firstValueFrom(source); + return value[0]; } /** @@ -481,7 +469,6 @@ export class UmbExtensionRegistry< */ async appendCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { try { - // Wait for the extension to be registered (as it could be registered late) const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; @@ -530,7 +517,6 @@ export class UmbExtensionRegistry< */ async prependCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { try { - // Wait for the extension to be registered (as it could be registered late) const extensionToUpdate = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; @@ -543,7 +529,6 @@ export class UmbExtensionRegistry< } else { extensionToUpdate.conditions = [newCondition]; } - } catch (error) { // TODO: [WB] Will this ever catch an error? console.error(`Extension with alias ${alias} was never found and threw ${error}`); From 8c40133392f5f5666288e9c39c2dd1315c5d02b8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 10:22:24 +0200 Subject: [PATCH 169/322] split some tests --- .../registry/extension.registry.test.ts | 188 +++++++++--------- 1 file changed, 97 insertions(+), 91 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 94c5fccbf5..dd1e8612f9 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -1,5 +1,11 @@ import { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; -import type { ManifestElementWithElementName, ManifestKind, ManifestBase, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; +import type { + ManifestElementWithElementName, + ManifestKind, + ManifestBase, + ManifestWithDynamicConditions, + UmbConditionConfigBase, +} from '../types/index.js'; import { UmbExtensionRegistry } from './extension.registry.js'; import { expect } from '@open-wc/testing'; @@ -457,9 +463,7 @@ describe('UmbExtensionRegistry with exclusions', () => { describe('Append Conditions', () => { let extensionRegistry: UmbExtensionRegistry; - let manifests: Array< - ManifestWithDynamicConditions - >; + let manifests: Array; beforeEach(() => { extensionRegistry = new UmbExtensionRegistry(); @@ -471,15 +475,15 @@ describe('Append Conditions', () => { weight: 1, conditions: [ { - alias: "Umb.Test.Condition.Valid" - } - ] + alias: 'Umb.Test.Condition.Valid', + }, + ], }, { type: 'section', name: 'test-section-2', alias: 'Umb.Test.Section.2', - weight: 200 + weight: 200, }, ]; @@ -488,17 +492,18 @@ describe('Append Conditions', () => { extensionRegistry.register({ type: 'condition', name: 'test-condition-invalid', - alias: 'Umb.Test.Condition.Invalid' + alias: 'Umb.Test.Condition.Invalid', }); }); - - it('allows an extension condition to be updated', async () => { + it('should have the extensions registered', () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; + }); + it('allows an extension condition to be updated', async () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); @@ -506,12 +511,12 @@ describe('Append Conditions', () => { extensionRegistry.register({ type: 'condition', name: 'test-condition-valid', - alias: 'Umb.Test.Condition.Valid' + alias: 'Umb.Test.Condition.Valid', }); // Add the new condition to the extension - const conditionToAdd:UmbConditionConfigBase = { - alias: 'Umb.Test.Condition.Valid' + const conditionToAdd: UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid', }; await extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); @@ -523,10 +528,9 @@ describe('Append Conditions', () => { expect(updatedExt.conditions?.length).to.equal(2); // Add a condition with a specific config to Section2 - const workspaceCondition:WorkspaceAliasConditionConfig = { + const workspaceCondition: WorkspaceAliasConditionConfig = { alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document' - + match: 'Umb.Workspace.Document', }; await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); @@ -538,15 +542,15 @@ describe('Append Conditions', () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); - const conditions:Array = [ + const conditions: Array = [ { - alias: 'Umb.Test.Condition.Valid' + alias: 'Umb.Test.Condition.Valid', }, { alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document' - } as WorkspaceAliasConditionConfig - ] + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); @@ -560,87 +564,89 @@ describe('Prepend Conditions', () => { let manifests: Array; beforeEach(() => { - extensionRegistry = new UmbExtensionRegistry(); - manifests = [ - { - type: 'section', - name: 'test-section-1', - alias: 'Umb.Test.Section.1', - weight: 1, - conditions: [ - { - alias: "Umb.Test.Condition.Valid" - } - ] - }, + extensionRegistry = new UmbExtensionRegistry(); + manifests = [ + { + type: 'section', + name: 'test-section-1', + alias: 'Umb.Test.Section.1', + weight: 1, + conditions: [ { - type: 'section', - name: 'test-section-2', - alias: 'Umb.Test.Section.2', - weight: 200 + alias: 'Umb.Test.Condition.Valid', }, - ]; + ], + }, + { + type: 'section', + name: 'test-section-2', + alias: 'Umb.Test.Section.2', + weight: 200, + }, + ]; - manifests.forEach((manifest) => extensionRegistry.register(manifest)); + manifests.forEach((manifest) => extensionRegistry.register(manifest)); - extensionRegistry.register({ - type: 'condition', - name: 'test-condition-invalid', - alias: 'Umb.Test.Condition.Invalid' - }); + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid', + }); + }); + + it('should have the extensions registered', () => { + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; }); it('allows an extension condition to be prepended', async () => { - expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; - - const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(1); - - // Register new condition as if I was in my own entrypoint - extensionRegistry.register({ - type: 'condition', - name: 'test-condition-valid', - alias: 'Umb.Test.Condition.Valid' - }); - - // Prepend the new condition to the extension - const conditionToPrepend: UmbConditionConfigBase = { - alias: 'Umb.Test.Condition.Valid' - }; - - await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); - - // Check new condition is registered - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; - - // Verify the extension now has two conditions and the new condition is prepended - const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(updatedExt.conditions?.length).to.equal(2); - expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + // Register new condition as if I was in my own entrypoint + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-valid', + alias: 'Umb.Test.Condition.Valid', + }); + + // Prepend the new condition to the extension + const conditionToPrepend: UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid', + }; + + await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); + + // Check new condition is registered + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + + // Verify the extension now has two conditions and the new condition is prepended + const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(updatedExt.conditions?.length).to.equal(2); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); }); it('allows an extension to update with multiple prepended conditions', async () => { - const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(1); + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); - const conditions: Array = [ - { - alias: 'Umb.Test.Condition.Valid' - }, - { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document' - } as WorkspaceAliasConditionConfig - ]; + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Valid', + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; - await extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); - const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(extUpdated.conditions?.length).to.equal(3); - expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); }); }); From 3ee3cab0a380aacb9f2972a2c8a2ddb05f789e77 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 30 Aug 2024 11:43:31 +0100 Subject: [PATCH 170/322] Rework of tests to pass and minor fix to _whenExtensionAliasIsRegistered to get the ext alias that matches --- .../registry/extension.registry.test.ts | 56 +++++++++++-------- .../registry/extension.registry.ts | 21 +++---- 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index dd1e8612f9..e089f1bd17 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -475,7 +475,7 @@ describe('Append Conditions', () => { weight: 1, conditions: [ { - alias: 'Umb.Test.Condition.Valid', + alias: 'Umb.Test.Condition.Invalid', }, ], }, @@ -483,7 +483,7 @@ describe('Append Conditions', () => { type: 'section', name: 'test-section-2', alias: 'Umb.Test.Section.2', - weight: 200, + weight: 200 }, ]; @@ -523,19 +523,23 @@ describe('Append Conditions', () => { // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; - // Verify the extension now has two conditions + // Verify the extension now has two conditions and in correct order with aliases const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(updatedExt.conditions?.length).to.equal(2); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(updatedExt.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); // Add a condition with a specific config to Section2 const workspaceCondition: WorkspaceAliasConditionConfig = { alias: 'Umb.Condition.WorkspaceAlias', match: 'Umb.Workspace.Document', }; + await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); + expect(updatedWorkspaceExt.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); }); it('allows an extension to update with multiple conditions', async () => { @@ -555,7 +559,10 @@ describe('Append Conditions', () => { await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); }); }); @@ -582,59 +589,60 @@ describe('Prepend Conditions', () => { name: 'test-section-2', alias: 'Umb.Test.Section.2', weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], }, ]; manifests.forEach((manifest) => extensionRegistry.register(manifest)); - - extensionRegistry.register({ - type: 'condition', - name: 'test-condition-invalid', - alias: 'Umb.Test.Condition.Invalid', - }); }); it('should have the extensions registered', () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.false; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; }); it('allows an extension condition to be prepended', async () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); + expect(ext.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); - // Register new condition as if I was in my own entrypoint extensionRegistry.register({ type: 'condition', - name: 'test-condition-valid', - alias: 'Umb.Test.Condition.Valid', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid', }); // Prepend the new condition to the extension const conditionToPrepend: UmbConditionConfigBase = { - alias: 'Umb.Test.Condition.Valid', + alias: 'Umb.Test.Condition.Invalid', }; await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); // Check new condition is registered - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; // Verify the extension now has two conditions and the new condition is prepended const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(updatedExt.conditions?.length).to.equal(2); - expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); // Our new one prepended + expect(updatedExt.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); }); it('allows an extension to update with multiple prepended conditions', async () => { - const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + const ext = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); + expect(ext.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); const conditions: Array = [ { - alias: 'Umb.Test.Condition.Valid', + alias: 'Umb.Test.Condition.Invalid', }, { alias: 'Umb.Condition.WorkspaceAlias', @@ -642,11 +650,15 @@ describe('Prepend Conditions', () => { } as WorkspaceAliasConditionConfig, ]; - await extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.prependConditions('Umb.Test.Section.2', conditions); - const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(extUpdated.conditions?.length).to.equal(3); + + // The thing to note here our two new conditions is that are prepended in reverse order they are passed in + // as each one is prepended to the front of the array expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); }); }); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 7e482d9d71..91c06e1543 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -456,7 +456,8 @@ export class UmbExtensionRegistry< private async _whenExtensionAliasIsRegistered(alias: string): Promise { const source = this.extensions.pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))); const value = await firstValueFrom(source); - return value[0]; + const ext = value.find((ext) => ext.alias === alias) as ManifestBase; + return ext; } /** @@ -472,9 +473,6 @@ export class UmbExtensionRegistry< // Wait for the extension to be registered (as it could be registered late) const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - // Got it... now carry on & mutate it - console.log('got the extension to update/mutate', extensionToWaitFor); - // Append the condition to the extensions conditions array if (extensionToWaitFor.conditions) { extensionToWaitFor.conditions.push(newCondition); @@ -490,10 +488,6 @@ export class UmbExtensionRegistry< // Update the main extensions collection/observable this._extensions.setValue(allExtensions); - - // Log the updated extensions for debugging - console.log('UPDATED extensions:', this._extensions.getValue()); - console.table(this._extensions.getValue()); } } catch (error) { // TODO: [WB] Will this ever catch an error? @@ -507,7 +501,9 @@ export class UmbExtensionRegistry< * @param newConditions {Array} - A collection of conditions to append to an extension. */ async appendConditions(alias: string, newConditions: Array): Promise { - newConditions.forEach((condition) => this.appendCondition(alias, condition)); + for (const condition of newConditions) { + await this.appendCondition(alias, condition); + } } /** @@ -520,9 +516,6 @@ export class UmbExtensionRegistry< // Wait for the extension to be registered (as it could be registered late) const extensionToUpdate = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - // Got it... now carry on & mutate it - console.log('got the extension to update/mutate', extensionToUpdate); - // Append the condition to the extensions conditions array if (extensionToUpdate.conditions) { extensionToUpdate.conditions.unshift(newCondition); @@ -541,6 +534,8 @@ export class UmbExtensionRegistry< * @param newConditions {Array} - A collection of conditions to prepend to an extension. */ async prependConditions(alias: string, newConditions: Array): Promise { - newConditions.forEach((condition) => this.prependCondition(alias, condition)); + for (const condition of newConditions) { + await this.prependCondition(alias, condition); + } } } From ac415ca296c0654f0ef8ffbad934fd2f4922e940 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 30 Aug 2024 13:27:48 +0100 Subject: [PATCH 171/322] Trying to add a test to show that a late registered extension works - but test says otherwise compared to using it in entrypoint --- .../registry/extension.registry.test.ts | 46 ++++++++++++++++++- src/packages/property-editors/entry-point.ts | 20 +++++++- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index e089f1bd17..b38fdac8b2 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -483,7 +483,7 @@ describe('Append Conditions', () => { type: 'section', name: 'test-section-2', alias: 'Umb.Test.Section.2', - weight: 200 + weight: 200, }, ]; @@ -661,4 +661,48 @@ describe('Prepend Conditions', () => { expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); }); + + it('allows conditions to be prepended when an extension is loaded later on', async () => { + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Invalid', + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; + + console.log('About to go KABOOM..'); + + // Prepend the conditions + // [WB] HELP: Why is this fine when using in in an entrypoint + // /src/packages/property-editors/entry-point.ts + // But this TEST implodes if it can't find the extension that is not yet registered + await extensionRegistry.prependConditions('Late.Extension.To.Be.Loaded', conditions); + + // Make sure the extension is not registered YET + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // Register the extension LATE/after the conditions have been added + extensionRegistry.register({ + type: 'section', + name: 'Late Section Extension with one condition', + alias: 'Late.Extension.To.Be.Loaded', + weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], + }); + + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); }); diff --git a/src/packages/property-editors/entry-point.ts b/src/packages/property-editors/entry-point.ts index baafe2af43..64d64bc9c4 100644 --- a/src/packages/property-editors/entry-point.ts +++ b/src/packages/property-editors/entry-point.ts @@ -1,4 +1,8 @@ -import type { ManifestWithDynamicConditions, UmbConditionConfigBase, UmbEntryPointOnInit } from '@umbraco-cms/backoffice/extension-api'; +import type { + ManifestWithDynamicConditions, + UmbConditionConfigBase, + UmbEntryPointOnInit, +} from '@umbraco-cms/backoffice/extension-api'; import type { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; import './checkbox-list/components/index.js'; @@ -13,9 +17,16 @@ export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { match: 'Umb.Workspace.WARRENYO', } as WorkspaceAliasConditionConfig; + console.log( + 'Should not be false and not registered', + _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'), + ); + _extensionRegistry.appendCondition('Umb.Dashboard.UmbracoNewsLATE', condition); - const ext:ManifestWithDynamicConditions = { + console.log('I HAZ APPENED CONDITIONS'); + + const ext: ManifestWithDynamicConditions = { alias: 'Umb.Dashboard.UmbracoNewsLATE', type: 'dashboard', name: 'WARREN Package', @@ -30,4 +41,9 @@ export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { _extensionRegistry.register(ext); + const amIRegistered = _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'); + console.log('Should be true and registered', amIRegistered); + + const getTheThing = _extensionRegistry.getByAlias('Umb.Dashboard.UmbracoNewsLATE'); + console.log('Should be the extension', getTheThing); }; From d3f7e28bc00aeedf63c605c2947a0dae38f266b7 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 2 Sep 2024 17:18:21 +0100 Subject: [PATCH 172/322] Remove the prepend conditions and rename append to addCondition and addCondtions As the order of conditions is not important, as all conditions set on an extensions must be true/valid --- .../registry/extension.registry.ts | 43 +++---------------- 1 file changed, 5 insertions(+), 38 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 91c06e1543..d4f984b4a8 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -461,14 +461,14 @@ export class UmbExtensionRegistry< } /** - * Appends a new condition to an existing extension + * Add a new condition to an existing extension * Useful to add a condition for example the Save And Publish workspace action shipped by core * As overwriting the whole extension to simply add an extra condition is not ideal as it causes a lot of duplicated code * and could easily get out of sync from the CMS core implementation if a 3rd party dev was to try and overwrite it * @param alias {string} - The alias of the extension to append the condition to * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. */ - async appendCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { + async addCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { try { // Wait for the extension to be registered (as it could be registered late) const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; @@ -496,46 +496,13 @@ export class UmbExtensionRegistry< } /** - * Appends a collection of conditions to an exsiting extension + * Adds a collection of conditions to an exsiting extension * @param alias {string} - The alias of the extension to append the condition to * @param newConditions {Array} - A collection of conditions to append to an extension. */ - async appendConditions(alias: string, newConditions: Array): Promise { + async addConditions(alias: string, newConditions: Array): Promise { for (const condition of newConditions) { - await this.appendCondition(alias, condition); - } - } - - /** - * Prepends a new condition to an existing extension - * @param alias {string} - The alias of the extension to prepend the condition to - * @param newCondition {UmbConditionConfigBase} - The condition to prepend to the extension. - */ - async prependCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { - try { - // Wait for the extension to be registered (as it could be registered late) - const extensionToUpdate = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - - // Append the condition to the extensions conditions array - if (extensionToUpdate.conditions) { - extensionToUpdate.conditions.unshift(newCondition); - } else { - extensionToUpdate.conditions = [newCondition]; - } - } catch (error) { - // TODO: [WB] Will this ever catch an error? - console.error(`Extension with alias ${alias} was never found and threw ${error}`); - } - } - - /** - * Prepends a collection of conditions to an existing extension - * @param alias {string} - The alias of the extension to prepend the conditions to - * @param newConditions {Array} - A collection of conditions to prepend to an extension. - */ - async prependConditions(alias: string, newConditions: Array): Promise { - for (const condition of newConditions) { - await this.prependCondition(alias, condition); + await this.addCondition(alias, condition); } } } From 18ce99a2061b9c25282b43d83ba8b3ba7e68d99e Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 2 Sep 2024 20:03:34 +0100 Subject: [PATCH 173/322] Update tests Still need to uncomment & reinvestigate the late loading test --- .../registry/extension.registry.test.ts | 191 +++++------------- 1 file changed, 47 insertions(+), 144 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index b38fdac8b2..feb27191c8 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -461,7 +461,7 @@ describe('UmbExtensionRegistry with exclusions', () => { }); }); -describe('Append Conditions', () => { +describe('Add Conditions', () => { let extensionRegistry: UmbExtensionRegistry; let manifests: Array; @@ -518,7 +518,7 @@ describe('Append Conditions', () => { const conditionToAdd: UmbConditionConfigBase = { alias: 'Umb.Test.Condition.Valid', }; - await extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); + await extensionRegistry.addCondition('Umb.Test.Section.1', conditionToAdd); // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; @@ -535,7 +535,7 @@ describe('Append Conditions', () => { match: 'Umb.Workspace.Document', }; - await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); + await extensionRegistry.addCondition('Umb.Test.Section.2', workspaceCondition); const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); @@ -556,7 +556,7 @@ describe('Append Conditions', () => { } as WorkspaceAliasConditionConfig, ]; - await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.addConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(extUpdated.conditions?.length).to.equal(3); @@ -564,145 +564,48 @@ describe('Append Conditions', () => { expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); }); -}); - -describe('Prepend Conditions', () => { - let extensionRegistry: UmbExtensionRegistry; - let manifests: Array; - - beforeEach(() => { - extensionRegistry = new UmbExtensionRegistry(); - manifests = [ - { - type: 'section', - name: 'test-section-1', - alias: 'Umb.Test.Section.1', - weight: 1, - conditions: [ - { - alias: 'Umb.Test.Condition.Valid', - }, - ], - }, - { - type: 'section', - name: 'test-section-2', - alias: 'Umb.Test.Section.2', - weight: 200, - conditions: [ - { - alias: 'Umb.Test.Condition.Valid', - }, - ], - }, - ]; - - manifests.forEach((manifest) => extensionRegistry.register(manifest)); - }); - - it('should have the extensions registered', () => { - expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.false; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; - }); - - it('allows an extension condition to be prepended', async () => { - const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(1); - expect(ext.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); - - extensionRegistry.register({ - type: 'condition', - name: 'test-condition-invalid', - alias: 'Umb.Test.Condition.Invalid', - }); - - // Prepend the new condition to the extension - const conditionToPrepend: UmbConditionConfigBase = { - alias: 'Umb.Test.Condition.Invalid', - }; - - await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); - - // Check new condition is registered - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; - - // Verify the extension now has two conditions and the new condition is prepended - const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(updatedExt.conditions?.length).to.equal(2); - expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); // Our new one prepended - expect(updatedExt.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); - }); - - it('allows an extension to update with multiple prepended conditions', async () => { - const ext = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(1); - expect(ext.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); - - const conditions: Array = [ - { - alias: 'Umb.Test.Condition.Invalid', - }, - { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document', - } as WorkspaceAliasConditionConfig, - ]; - - await extensionRegistry.prependConditions('Umb.Test.Section.2', conditions); - - const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; - expect(extUpdated.conditions?.length).to.equal(3); - - // The thing to note here our two new conditions is that are prepended in reverse order they are passed in - // as each one is prepended to the front of the array - expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); - expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); - }); - - it('allows conditions to be prepended when an extension is loaded later on', async () => { - const conditions: Array = [ - { - alias: 'Umb.Test.Condition.Invalid', - }, - { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document', - } as WorkspaceAliasConditionConfig, - ]; - console.log('About to go KABOOM..'); - - // Prepend the conditions - // [WB] HELP: Why is this fine when using in in an entrypoint - // /src/packages/property-editors/entry-point.ts - // But this TEST implodes if it can't find the extension that is not yet registered - await extensionRegistry.prependConditions('Late.Extension.To.Be.Loaded', conditions); - - // Make sure the extension is not registered YET - expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; - - // Register the extension LATE/after the conditions have been added - extensionRegistry.register({ - type: 'section', - name: 'Late Section Extension with one condition', - alias: 'Late.Extension.To.Be.Loaded', - weight: 200, - conditions: [ - { - alias: 'Umb.Test.Condition.Valid', - }, - ], - }); - - expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; - - const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; - expect(extUpdated.conditions?.length).to.equal(3); - expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); - expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); - }); + // it('allows conditions to be prepended when an extension is loaded later on', async () => { + // const conditions: Array = [ + // { + // alias: 'Umb.Test.Condition.Invalid', + // }, + // { + // alias: 'Umb.Condition.WorkspaceAlias', + // match: 'Umb.Workspace.Document', + // } as WorkspaceAliasConditionConfig, + // ]; + + // console.log('About to go KABOOM..'); + + // // Prepend the conditions + // // [WB] HELP: Why is this fine when using in in an entrypoint + // // /src/packages/property-editors/entry-point.ts + // // But this TEST implodes if it can't find the extension that is not yet registered + // await extensionRegistry.addConditions('Late.Extension.To.Be.Loaded', conditions); + + // // Make sure the extension is not registered YET + // expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // // Register the extension LATE/after the conditions have been added + // extensionRegistry.register({ + // type: 'section', + // name: 'Late Section Extension with one condition', + // alias: 'Late.Extension.To.Be.Loaded', + // weight: 200, + // conditions: [ + // { + // alias: 'Umb.Test.Condition.Valid', + // }, + // ], + // }); + + // expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + // const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; + // expect(extUpdated.conditions?.length).to.equal(3); + // expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + // expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); + // expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); + // }); }); From a6faa5971115191c74055c2622a161e8eb91ef37 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 3 Sep 2024 19:38:45 +0100 Subject: [PATCH 174/322] Fix up code so test passes & my rough entrypoint demo of usage works --- src/packages/property-editors/entry-point.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/property-editors/entry-point.ts b/src/packages/property-editors/entry-point.ts index 64d64bc9c4..f83895ac9b 100644 --- a/src/packages/property-editors/entry-point.ts +++ b/src/packages/property-editors/entry-point.ts @@ -22,9 +22,9 @@ export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'), ); - _extensionRegistry.appendCondition('Umb.Dashboard.UmbracoNewsLATE', condition); + _extensionRegistry.addCondition('Umb.Dashboard.UmbracoNewsLATE', condition); - console.log('I HAZ APPENED CONDITIONS'); + console.log('I HAZ ADDED CONDITION'); const ext: ManifestWithDynamicConditions = { alias: 'Umb.Dashboard.UmbracoNewsLATE', From eb197722317904423eeebe81e27d3a3f5550135f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 20:38:05 +0200 Subject: [PATCH 175/322] import type --- src/libs/extension-api/registry/extension.registry.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index feb27191c8..7f1d48752a 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -1,4 +1,4 @@ -import { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; +import type { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; import type { ManifestElementWithElementName, ManifestKind, From 8fd2cd03d375d682f3f137889b909d589fad3e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 22:01:34 +0200 Subject: [PATCH 176/322] remove test code --- src/packages/property-editors/entry-point.ts | 47 -------------------- 1 file changed, 47 deletions(-) diff --git a/src/packages/property-editors/entry-point.ts b/src/packages/property-editors/entry-point.ts index f83895ac9b..9745b0d139 100644 --- a/src/packages/property-editors/entry-point.ts +++ b/src/packages/property-editors/entry-point.ts @@ -1,49 +1,2 @@ -import type { - ManifestWithDynamicConditions, - UmbConditionConfigBase, - UmbEntryPointOnInit, -} from '@umbraco-cms/backoffice/extension-api'; -import type { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; - import './checkbox-list/components/index.js'; import './content-picker/components/index.js'; - -export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { - - console.log('HELLO AGAIN'); - - const condition: UmbConditionConfigBase = { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.WARRENYO', - } as WorkspaceAliasConditionConfig; - - console.log( - 'Should not be false and not registered', - _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'), - ); - - _extensionRegistry.addCondition('Umb.Dashboard.UmbracoNewsLATE', condition); - - console.log('I HAZ ADDED CONDITION'); - - const ext: ManifestWithDynamicConditions = { - alias: 'Umb.Dashboard.UmbracoNewsLATE', - type: 'dashboard', - name: 'WARREN Package', - weight: 100, - conditions: [ - { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.LATE-COMER-EXISTING', - } as WorkspaceAliasConditionConfig, - ], - }; - - _extensionRegistry.register(ext); - - const amIRegistered = _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'); - console.log('Should be true and registered', amIRegistered); - - const getTheThing = _extensionRegistry.getByAlias('Umb.Dashboard.UmbracoNewsLATE'); - console.log('Should be the extension', getTheThing); -}; From 95031c913f0d2ee55a541774ee5eb31b82c8ac0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 22:01:45 +0200 Subject: [PATCH 177/322] refactor for a more direct appending implementation --- .../registry/extension.registry.test.ts | 164 +++++++++++++----- .../registry/extension.registry.ts | 120 ++++++------- 2 files changed, 178 insertions(+), 106 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 7f1d48752a..caed039f60 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -518,7 +518,7 @@ describe('Add Conditions', () => { const conditionToAdd: UmbConditionConfigBase = { alias: 'Umb.Test.Condition.Valid', }; - await extensionRegistry.addCondition('Umb.Test.Section.1', conditionToAdd); + await extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; @@ -529,13 +529,17 @@ describe('Add Conditions', () => { expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); expect(updatedExt.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + // Verify the other extension was not updated: + const otherExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; + expect(otherExt.conditions).to.be.undefined; + // Add a condition with a specific config to Section2 const workspaceCondition: WorkspaceAliasConditionConfig = { alias: 'Umb.Condition.WorkspaceAlias', match: 'Umb.Workspace.Document', }; - await extensionRegistry.addCondition('Umb.Test.Section.2', workspaceCondition); + await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); @@ -556,7 +560,7 @@ describe('Add Conditions', () => { } as WorkspaceAliasConditionConfig, ]; - await extensionRegistry.addConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(extUpdated.conditions?.length).to.equal(3); @@ -565,47 +569,115 @@ describe('Add Conditions', () => { expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); }); - // it('allows conditions to be prepended when an extension is loaded later on', async () => { - // const conditions: Array = [ - // { - // alias: 'Umb.Test.Condition.Invalid', - // }, - // { - // alias: 'Umb.Condition.WorkspaceAlias', - // match: 'Umb.Workspace.Document', - // } as WorkspaceAliasConditionConfig, - // ]; - - // console.log('About to go KABOOM..'); - - // // Prepend the conditions - // // [WB] HELP: Why is this fine when using in in an entrypoint - // // /src/packages/property-editors/entry-point.ts - // // But this TEST implodes if it can't find the extension that is not yet registered - // await extensionRegistry.addConditions('Late.Extension.To.Be.Loaded', conditions); - - // // Make sure the extension is not registered YET - // expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; - - // // Register the extension LATE/after the conditions have been added - // extensionRegistry.register({ - // type: 'section', - // name: 'Late Section Extension with one condition', - // alias: 'Late.Extension.To.Be.Loaded', - // weight: 200, - // conditions: [ - // { - // alias: 'Umb.Test.Condition.Valid', - // }, - // ], - // }); - - // expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; - - // const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; - // expect(extUpdated.conditions?.length).to.equal(3); - // expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - // expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); - // expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); - // }); + it('allows conditions to be prepended when an extension is loaded later on', async () => { + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Invalid', + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; + + // Prepend the conditions, but do not await this. + extensionRegistry.appendConditions('Late.Extension.To.Be.Loaded', conditions); + + // Make sure the extension is not registered YET + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // Register the extension LATE/after the conditions have been added + extensionRegistry.register({ + type: 'section', + name: 'Late Section Extension with one condition', + alias: 'Late.Extension.To.Be.Loaded', + weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], + }); + + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; + + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + }); + + /** + * As of current state, it is by design without further reasons to why, but it is made so additional conditions are only added to a current or next time registered manifest. + * Meaning if it happens to be unregistered and re-registered it does not happen again. + * Unless the exact same appending of conditions happens again. [NL] + * + * This makes sense if extensions gets offloaded and re-registered, but the extension that registered additional conditions didn't get loaded/registered second time. Therefor they need to be re-registered for such to work. [NL] + */ + it('only append conditions to the next time the extension is registered', async () => { + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Invalid', + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; + + // Prepend the conditions, but do not await this. + extensionRegistry.appendConditions('Late.Extension.To.Be.Loaded', conditions); + + // Make sure the extension is not registered YET + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // Register the extension LATE/after the conditions have been added + extensionRegistry.register({ + type: 'section', + name: 'Late Section Extension with one condition', + alias: 'Late.Extension.To.Be.Loaded', + weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], + }); + + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + const extUpdateFirstTime = extensionRegistry.getByAlias( + 'Late.Extension.To.Be.Loaded', + ) as ManifestWithDynamicConditions; + expect(extUpdateFirstTime.conditions?.length).to.equal(3); + + extensionRegistry.unregister('Late.Extension.To.Be.Loaded'); + + // Make sure the extension is not registered YET + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // Register the extension LATE/after the conditions have been added + extensionRegistry.register({ + type: 'section', + name: 'Late Section Extension with one condition', + alias: 'Late.Extension.To.Be.Loaded', + weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], + }); + + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + const extUpdateSecondTime = extensionRegistry.getByAlias( + 'Late.Extension.To.Be.Loaded', + ) as ManifestWithDynamicConditions; + + expect(extUpdateSecondTime.conditions?.length).to.equal(1); + expect(extUpdateSecondTime.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); }); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index d4f984b4a8..6ff5762ca7 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -7,15 +7,7 @@ import type { import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import { - map, - distinctUntilChanged, - combineLatest, - of, - switchMap, - filter, - firstValueFrom, -} from '@umbraco-cms/backoffice/external/rxjs'; +import { map, distinctUntilChanged, combineLatest, of, switchMap } from '@umbraco-cms/backoffice/external/rxjs'; /** * @@ -117,8 +109,26 @@ export class UmbExtensionRegistry< private _kinds = new UmbBasicState>>([]); public readonly kinds = this._kinds.asObservable(); + #exclusions: Array = []; + #additionalConditions: Map> = new Map(); + #appendAdditionalConditions(manifest: ManifestTypes) { + const newConditions = this.#additionalConditions.get(manifest.alias); + if (newConditions) { + // Append the condition to the extensions conditions array + if ((manifest as ManifestWithDynamicConditions).conditions) { + for (const condition of newConditions) { + (manifest as ManifestWithDynamicConditions).conditions!.push(condition); + } + } else { + (manifest as ManifestWithDynamicConditions).conditions = newConditions; + } + this.#additionalConditions.delete(manifest.alias); + } + return manifest; + } + defineKind(kind: ManifestKind): void { const extensionsValues = this._extensions.getValue(); const extension = extensionsValues.find( @@ -153,12 +163,25 @@ export class UmbExtensionRegistry< }; register(manifest: ManifestTypes | ManifestKind): void { - const isValid = this.#checkExtension(manifest); + const isValid = this.#validateExtension(manifest); if (!isValid) { return; } - this._extensions.setValue([...this._extensions.getValue(), manifest as ManifestTypes]); + if (manifest.type === 'kind') { + this.defineKind(manifest as ManifestKind); + return; + } + + const isApproved = this.#isExtensionApproved(manifest); + if (!isApproved) { + return; + } + + this._extensions.setValue([ + ...this._extensions.getValue(), + this.#appendAdditionalConditions(manifest as ManifestTypes), + ]); } getAllExtensions(): Array { @@ -194,7 +217,7 @@ export class UmbExtensionRegistry< return false; } - #checkExtension(manifest: ManifestTypes | ManifestKind): boolean { + #validateExtension(manifest: ManifestTypes | ManifestKind): boolean { if (!manifest.type) { console.error(`Extension is missing type`, manifest); return false; @@ -205,11 +228,9 @@ export class UmbExtensionRegistry< return false; } - if (manifest.type === 'kind') { - this.defineKind(manifest as ManifestKind); - return false; - } - + return true; + } + #isExtensionApproved(manifest: ManifestTypes | ManifestKind): boolean { if (!this.#acceptExtension(manifest as ManifestTypes)) { return false; } @@ -449,60 +470,39 @@ export class UmbExtensionRegistry< } /** - * Returns a promise that resolves when the extension with the specified alias is found. - * @param alias {string} - The alias of the extension to wait for. - * @returns {Promise} - A promise that resolves with the extension. + * Append a new condition to an existing extension + * Useful to add a condition for example the Save And Publish workspace action shipped by core. + * @param {string} alias - The alias of the extension to append the condition to. + * @param {UmbConditionConfigBase} newCondition - The condition to append to the extension. */ - private async _whenExtensionAliasIsRegistered(alias: string): Promise { - const source = this.extensions.pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))); - const value = await firstValueFrom(source); - const ext = value.find((ext) => ext.alias === alias) as ManifestBase; - return ext; + appendCondition(alias: string, newCondition: UmbConditionConfigBase) { + this.appendConditions(alias, [newCondition]); } /** - * Add a new condition to an existing extension - * Useful to add a condition for example the Save And Publish workspace action shipped by core - * As overwriting the whole extension to simply add an extra condition is not ideal as it causes a lot of duplicated code - * and could easily get out of sync from the CMS core implementation if a 3rd party dev was to try and overwrite it - * @param alias {string} - The alias of the extension to append the condition to - * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. + * Appends an array of conditions to an existing extension + * @param {string} alias - The alias of the extension to append the condition to + * @param {Array} newConditions - An array of conditions to be appended to an extension manifest. */ - async addCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { - try { - // Wait for the extension to be registered (as it could be registered late) - const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - - // Append the condition to the extensions conditions array - if (extensionToWaitFor.conditions) { - extensionToWaitFor.conditions.push(newCondition); - } else { - extensionToWaitFor.conditions = [newCondition]; - } + appendConditions(alias: string, newConditions: Array) { + const existingConditionsToBeAdded = this.#additionalConditions.get(alias); + this.#additionalConditions.set( + alias, + existingConditionsToBeAdded ? [...existingConditionsToBeAdded, ...newConditions] : newConditions, + ); - const allExtensions = this._extensions.getValue(); - const extensionToUpdateIndex = allExtensions.findIndex((ext) => ext.alias === alias); - if (extensionToUpdateIndex !== -1) { + const allExtensions = this._extensions.getValue(); + for (const extension of allExtensions) { + if (extension.alias === alias) { // Replace the existing extension with the updated one - allExtensions[extensionToUpdateIndex] = extensionToWaitFor as ManifestTypes; + allExtensions[allExtensions.indexOf(extension)] = this.#appendAdditionalConditions(extension as ManifestTypes); // Update the main extensions collection/observable this._extensions.setValue(allExtensions); - } - } catch (error) { - // TODO: [WB] Will this ever catch an error? - console.error(`Extension with alias ${alias} was never found and threw ${error}`); - } - } - /** - * Adds a collection of conditions to an exsiting extension - * @param alias {string} - The alias of the extension to append the condition to - * @param newConditions {Array} - A collection of conditions to append to an extension. - */ - async addConditions(alias: string, newConditions: Array): Promise { - for (const condition of newConditions) { - await this.addCondition(alias, condition); + //Stop the search: + break; + } } } } From 8946912450f155acc3acf4757636c7b42fa9cfea Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 21:43:54 +0200 Subject: [PATCH 178/322] register user sidebar menu --- src/packages/settings/advanced/manifests.ts | 6 ++-- src/packages/user/manifests.ts | 2 +- .../{user-section => section}/constants.ts | 0 .../user/{user-section => section}/index.ts | 0 src/packages/user/section/manifests.ts | 31 +++++++++++++++++++ src/packages/user/section/menu/constants.ts | 1 + src/packages/user/section/menu/index.ts | 1 + src/packages/user/section/menu/manifests.ts | 9 ++++++ .../user/{user-section => section}/paths.ts | 0 .../user/section/sidebar-app/index.ts | 1 + .../user/section/sidebar-app/manifests.ts | 23 ++++++++++++++ .../user/user-group/section-view/manifests.ts | 2 +- src/packages/user/user-section/manifests.ts | 21 ------------- .../user/user/section-view/manifests.ts | 2 +- 14 files changed, 72 insertions(+), 27 deletions(-) rename src/packages/user/{user-section => section}/constants.ts (100%) rename src/packages/user/{user-section => section}/index.ts (100%) create mode 100644 src/packages/user/section/manifests.ts create mode 100644 src/packages/user/section/menu/constants.ts create mode 100644 src/packages/user/section/menu/index.ts create mode 100644 src/packages/user/section/menu/manifests.ts rename src/packages/user/{user-section => section}/paths.ts (100%) create mode 100644 src/packages/user/section/sidebar-app/index.ts create mode 100644 src/packages/user/section/sidebar-app/manifests.ts delete mode 100644 src/packages/user/user-section/manifests.ts diff --git a/src/packages/settings/advanced/manifests.ts b/src/packages/settings/advanced/manifests.ts index 5a452d9e3d..3931a9edb9 100644 --- a/src/packages/settings/advanced/manifests.ts +++ b/src/packages/settings/advanced/manifests.ts @@ -10,11 +10,11 @@ export const manifests = [ { type: 'sectionSidebarApp', kind: 'menu', - alias: 'Umb.SectionSidebarMenu.AdvancedSettings', - name: 'Advanced Settings Sidebar Menu', + alias: 'Umb.SectionSidebarApp.Menu.Users', + name: 'Users Section Sidebar Menu', weight: 100, meta: { - label: '#treeHeaders_advancedGroup', + label: 'Users', menu: UMB_ADVANCED_SETTINGS_MENU_ALIAS, }, conditions: [ diff --git a/src/packages/user/manifests.ts b/src/packages/user/manifests.ts index 96353d28f7..d649d8f06f 100644 --- a/src/packages/user/manifests.ts +++ b/src/packages/user/manifests.ts @@ -1,6 +1,6 @@ import { manifests as userGroupManifests } from './user-group/manifests.js'; import { manifests as userManifests } from './user/manifests.js'; -import { manifests as userSectionManifests } from './user-section/manifests.js'; +import { manifests as userSectionManifests } from './section/manifests.js'; import { manifests as currentUserManifests } from './current-user/manifests.js'; import { manifests as userPermissionManifests } from './user-permission/manifests.js'; import { manifests as changePasswordManifests } from './change-password/manifests.js'; diff --git a/src/packages/user/user-section/constants.ts b/src/packages/user/section/constants.ts similarity index 100% rename from src/packages/user/user-section/constants.ts rename to src/packages/user/section/constants.ts diff --git a/src/packages/user/user-section/index.ts b/src/packages/user/section/index.ts similarity index 100% rename from src/packages/user/user-section/index.ts rename to src/packages/user/section/index.ts diff --git a/src/packages/user/section/manifests.ts b/src/packages/user/section/manifests.ts new file mode 100644 index 0000000000..bb49da5322 --- /dev/null +++ b/src/packages/user/section/manifests.ts @@ -0,0 +1,31 @@ +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from './constants.js'; +import { manifests as sectionSidebarAppManifests } from './sidebar-app/manifests.js'; +import { manifests as menuManifests } from './menu/manifests.js'; +import type { + ManifestSection, + ManifestTypes, + UmbBackofficeManifestKind, +} from '@umbraco-cms/backoffice/extension-registry'; + +const section: ManifestSection = { + type: 'section', + alias: UMB_USER_MANAGEMENT_SECTION_ALIAS, + name: 'User Management Section', + weight: 600, + meta: { + label: '#sections_users', + pathname: 'user-management', + }, + conditions: [ + { + alias: 'Umb.Condition.SectionUserPermission', + match: UMB_USER_MANAGEMENT_SECTION_ALIAS, + }, + ], +}; + +export const manifests: Array = [ + section, + ...sectionSidebarAppManifests, + ...menuManifests, +]; diff --git a/src/packages/user/section/menu/constants.ts b/src/packages/user/section/menu/constants.ts new file mode 100644 index 0000000000..7bf050d53c --- /dev/null +++ b/src/packages/user/section/menu/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_MANAGEMENT_MENU_ALIAS = 'Umb.Menu.UserManagement'; diff --git a/src/packages/user/section/menu/index.ts b/src/packages/user/section/menu/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/user/section/menu/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/user/section/menu/manifests.ts b/src/packages/user/section/menu/manifests.ts new file mode 100644 index 0000000000..f5852aa534 --- /dev/null +++ b/src/packages/user/section/menu/manifests.ts @@ -0,0 +1,9 @@ +import { UMB_USER_MANAGEMENT_MENU_ALIAS } from './constants.js'; + +export const manifests = [ + { + type: 'menu', + alias: UMB_USER_MANAGEMENT_MENU_ALIAS, + name: 'User Management Menu', + }, +]; diff --git a/src/packages/user/user-section/paths.ts b/src/packages/user/section/paths.ts similarity index 100% rename from src/packages/user/user-section/paths.ts rename to src/packages/user/section/paths.ts diff --git a/src/packages/user/section/sidebar-app/index.ts b/src/packages/user/section/sidebar-app/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/user/section/sidebar-app/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/user/section/sidebar-app/manifests.ts b/src/packages/user/section/sidebar-app/manifests.ts new file mode 100644 index 0000000000..f21d698bc2 --- /dev/null +++ b/src/packages/user/section/sidebar-app/manifests.ts @@ -0,0 +1,23 @@ +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../constants.js'; +import { UMB_USER_MANAGEMENT_MENU_ALIAS } from '../menu/index.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'sectionSidebarApp', + kind: 'menu', + alias: 'Umb.SectionSidebarApp.Menu.UserManagement', + name: 'User Management Menu Sidebar App', + weight: 100, + meta: { + label: '#treeHeaders_users', + menu: UMB_USER_MANAGEMENT_MENU_ALIAS, + }, + conditions: [ + { + alias: 'Umb.Condition.SectionAlias', + match: UMB_USER_MANAGEMENT_SECTION_ALIAS, + }, + ], + }, +]; diff --git a/src/packages/user/user-group/section-view/manifests.ts b/src/packages/user/user-group/section-view/manifests.ts index 3780224244..f4549d458f 100644 --- a/src/packages/user/user-group/section-view/manifests.ts +++ b/src/packages/user/user-group/section-view/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../user-section/index.js'; +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/index.js'; import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; const sectionsViews: Array = [ diff --git a/src/packages/user/user-section/manifests.ts b/src/packages/user/user-section/manifests.ts deleted file mode 100644 index 74bb597e28..0000000000 --- a/src/packages/user/user-section/manifests.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from './constants.js'; -import type { ManifestSection, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; - -const section: ManifestSection = { - type: 'section', - alias: UMB_USER_MANAGEMENT_SECTION_ALIAS, - name: 'User Management Section', - weight: 600, - meta: { - label: '#sections_users', - pathname: 'user-management', - }, - conditions: [ - { - alias: 'Umb.Condition.SectionUserPermission', - match: UMB_USER_MANAGEMENT_SECTION_ALIAS, - }, - ], -}; - -export const manifests: Array = [section]; diff --git a/src/packages/user/user/section-view/manifests.ts b/src/packages/user/user/section-view/manifests.ts index a9dbcd430b..8af99c6b24 100644 --- a/src/packages/user/user/section-view/manifests.ts +++ b/src/packages/user/user/section-view/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../user-section/index.js'; +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/index.js'; import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; const sectionsViews: Array = [ From 26666fdb56fcddc908b3778566c69ccf76759ca7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 21:56:10 +0200 Subject: [PATCH 179/322] register root workspace --- src/packages/user/user/manifests.ts | 6 +- src/packages/user/user/menu-item/manifests.ts | 18 +++++ .../user/user/section-view/manifests.ts | 27 +++----- .../user-root-workspace-view.element.ts | 21 ++++++ .../users-section-view.element.ts | 67 ------------------- 5 files changed, 51 insertions(+), 88 deletions(-) create mode 100644 src/packages/user/user/menu-item/manifests.ts create mode 100644 src/packages/user/user/section-view/user-root-workspace-view.element.ts delete mode 100644 src/packages/user/user/section-view/users-section-view.element.ts diff --git a/src/packages/user/user/manifests.ts b/src/packages/user/user/manifests.ts index 3eae6c756b..d842d25b03 100644 --- a/src/packages/user/user/manifests.ts +++ b/src/packages/user/user/manifests.ts @@ -9,9 +9,10 @@ import { manifests as propertyEditorManifests } from './property-editor/manifest import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; +import { manifests as menuItemManifests } from './menu-item/manifests.js'; +import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ +export const manifests: Array = [ ...clientCredentialManifests, ...collectionManifests, ...conditionsManifests, @@ -23,4 +24,5 @@ export const manifests: Array = [ ...repositoryManifests, ...sectionViewManifests, ...workspaceManifests, + ...menuItemManifests, ]; diff --git a/src/packages/user/user/menu-item/manifests.ts b/src/packages/user/user/menu-item/manifests.ts new file mode 100644 index 0000000000..2239c2fe0f --- /dev/null +++ b/src/packages/user/user/menu-item/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_USER_MANAGEMENT_MENU_ALIAS } from '../../section/menu/constants.js'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'menuItem', + alias: 'Umb.MenuItem.Users', + name: 'Users Menu Item', + weight: 100, + meta: { + label: '#treeHeaders_users', + icon: 'icon-user', + entityType: UMB_USER_ROOT_ENTITY_TYPE, + menus: [UMB_USER_MANAGEMENT_MENU_ALIAS], + }, + }, +]; diff --git a/src/packages/user/user/section-view/manifests.ts b/src/packages/user/user/section-view/manifests.ts index 8af99c6b24..aef4c6370e 100644 --- a/src/packages/user/user/section-view/manifests.ts +++ b/src/packages/user/user/section-view/manifests.ts @@ -1,25 +1,14 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/index.js'; -import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -const sectionsViews: Array = [ +export const manifests: Array = [ { - type: 'sectionView', - alias: 'Umb.SectionView.Users', - name: 'Users Section View', - js: () => import('./users-section-view.element.js'), - weight: 200, + type: 'workspace', + alias: 'Umb.Workspace.UserRoot', + name: 'User Root Workspace View', + element: () => import('./user-root-workspace-view.element.js'), meta: { - label: '#general_users', - pathname: 'users', - icon: 'icon-user', + entityType: UMB_USER_ROOT_ENTITY_TYPE, }, - conditions: [ - { - alias: 'Umb.Condition.SectionAlias', - match: UMB_USER_MANAGEMENT_SECTION_ALIAS, - }, - ], }, ]; - -export const manifests: Array = [...sectionsViews]; diff --git a/src/packages/user/user/section-view/user-root-workspace-view.element.ts b/src/packages/user/user/section-view/user-root-workspace-view.element.ts new file mode 100644 index 0000000000..6e286dada3 --- /dev/null +++ b/src/packages/user/user/section-view/user-root-workspace-view.element.ts @@ -0,0 +1,21 @@ +import { UMB_USER_COLLECTION_ALIAS } from '../collection/index.js'; +import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +const elementName = 'umb-user-root-workspace'; +@customElement(elementName) +export class UmbUserRootWorkspaceElement extends UmbLitElement { + override render() { + return html` + ; + `; + } +} + +export { UmbUserRootWorkspaceElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserRootWorkspaceElement; + } +} diff --git a/src/packages/user/user/section-view/users-section-view.element.ts b/src/packages/user/user/section-view/users-section-view.element.ts deleted file mode 100644 index 22f9d5069d..0000000000 --- a/src/packages/user/user/section-view/users-section-view.element.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { UMB_USER_COLLECTION_ALIAS } from '../collection/index.js'; -import { UMB_USER_ENTITY_TYPE, UMB_USER_ROOT_ENTITY_TYPE } from '../entity.js'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbRoute } from '@umbraco-cms/backoffice/router'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbCollectionElement } from '@umbraco-cms/backoffice/collection'; -import { UmbWorkspaceElement } from '@umbraco-cms/backoffice/workspace'; -import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; - -@customElement('umb-section-view-users') -export class UmbSectionViewUsersElement extends UmbLitElement { - #routes: UmbRoute[] = [ - { - path: 'collection', - component: () => { - const element = new UmbCollectionElement(); - const entityContext = new UmbEntityContext(element); - entityContext.setEntityType(UMB_USER_ROOT_ENTITY_TYPE); - entityContext.setUnique(null); - element.setAttribute('alias', UMB_USER_COLLECTION_ALIAS); - return element; - }, - }, - { - path: 'user', - component: () => { - const element = new UmbWorkspaceElement(); - element.setAttribute('entity-type', UMB_USER_ENTITY_TYPE); - return element; - }, - }, - { - path: '', - redirectTo: 'collection', - }, - { - path: `**`, - component: async () => (await import('@umbraco-cms/backoffice/router')).UmbRouteNotFoundElement, - }, - ]; - - override render() { - return html` `; - } - - static override styles = [ - UmbTextStyles, - css` - :host { - height: 100%; - } - - #router-slot { - height: calc(100% - var(--umb-header-layout-height)); - } - `, - ]; -} - -export default UmbSectionViewUsersElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-section-view-users': UmbSectionViewUsersElement; - } -} From 52385eef3ea615536a9a989c5e92a70f02140da0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 08:53:01 +0200 Subject: [PATCH 180/322] register user group menu item --- src/packages/user/user-group/entity.ts | 2 + src/packages/user/user-group/manifests.ts | 19 +++--- .../user/user-group/menu-item/manifests.ts | 18 ++++++ .../user/user-group/section-view/manifests.ts | 27 +++----- .../user-group-root-workspace.element.ts | 21 +++++++ .../user-group-section-view.element.ts | 63 ------------------- src/packages/user/user/menu-item/manifests.ts | 2 +- .../user/user/section-view/manifests.ts | 2 +- ...ment.ts => user-root-workspace.element.ts} | 0 9 files changed, 62 insertions(+), 92 deletions(-) create mode 100644 src/packages/user/user-group/menu-item/manifests.ts create mode 100644 src/packages/user/user-group/section-view/user-group-root-workspace.element.ts delete mode 100644 src/packages/user/user-group/section-view/user-group-section-view.element.ts rename src/packages/user/user/section-view/{user-root-workspace-view.element.ts => user-root-workspace.element.ts} (100%) diff --git a/src/packages/user/user-group/entity.ts b/src/packages/user/user-group/entity.ts index 40fc592fed..3978bfa6a5 100644 --- a/src/packages/user/user-group/entity.ts +++ b/src/packages/user/user-group/entity.ts @@ -1,3 +1,5 @@ export const UMB_USER_GROUP_ENTITY_TYPE = 'user-group'; +export const UMB_USER_GROUP_ROOT_ENTITY_TYPE = 'user-group-root'; export type UmbUserGroupEntityType = typeof UMB_USER_GROUP_ENTITY_TYPE; +export type UmbUserGroupRootEntityType = typeof UMB_USER_GROUP_ROOT_ENTITY_TYPE; diff --git a/src/packages/user/user-group/manifests.ts b/src/packages/user/user-group/manifests.ts index 4a03fbb339..1ac88d4e75 100644 --- a/src/packages/user/user-group/manifests.ts +++ b/src/packages/user/user-group/manifests.ts @@ -1,18 +1,21 @@ import { manifests as collectionManifests } from './collection/manifests.js'; -import { manifests as repositoryManifests } from './repository/manifests.js'; -import { manifests as workspaceManifests } from './workspace/manifests.js'; -import { manifests as modalManifests } from './modals/manifests.js'; -import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as entityActionManifests } from './entity-actions/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-actions/manifests.js'; +import { manifests as menuItemManifests } from './menu-item/manifests.js'; +import { manifests as modalManifests } from './modals/manifests.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import { manifests as sectionViewManifests } from './section-view/manifests.js'; +import { manifests as workspaceManifests } from './workspace/manifests.js'; + import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ ...collectionManifests, - ...repositoryManifests, - ...workspaceManifests, - ...modalManifests, - ...sectionViewManifests, ...entityActionManifests, ...entityBulkActionManifests, + ...menuItemManifests, + ...modalManifests, + ...repositoryManifests, + ...sectionViewManifests, + ...workspaceManifests, ]; diff --git a/src/packages/user/user-group/menu-item/manifests.ts b/src/packages/user/user-group/menu-item/manifests.ts new file mode 100644 index 0000000000..1c770acdae --- /dev/null +++ b/src/packages/user/user-group/menu-item/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_USER_MANAGEMENT_MENU_ALIAS } from '../../section/menu/constants.js'; +import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'menuItem', + alias: 'Umb.MenuItem.UserGroups', + name: 'User Groups Menu Item', + weight: 100, + meta: { + label: '#user_usergroups', + icon: 'icon-users', + entityType: UMB_USER_GROUP_ROOT_ENTITY_TYPE, + menus: [UMB_USER_MANAGEMENT_MENU_ALIAS], + }, + }, +]; diff --git a/src/packages/user/user-group/section-view/manifests.ts b/src/packages/user/user-group/section-view/manifests.ts index f4549d458f..ade0536011 100644 --- a/src/packages/user/user-group/section-view/manifests.ts +++ b/src/packages/user/user-group/section-view/manifests.ts @@ -1,25 +1,14 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/index.js'; -import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -const sectionsViews: Array = [ +export const manifests: Array = [ { - type: 'sectionView', - alias: 'Umb.SectionView.UserGroup', - name: 'User Group Section View', - js: () => import('./user-group-section-view.element.js'), - weight: 100, + type: 'workspace', + alias: 'Umb.Workspace.UserGroupRoot', + name: 'User Group Root Workspace View', + element: () => import('./user-group-root-workspace.element.js'), meta: { - label: '#user_usergroups', - pathname: 'user-groups', - icon: 'icon-users', + entityType: UMB_USER_GROUP_ROOT_ENTITY_TYPE, }, - conditions: [ - { - alias: 'Umb.Condition.SectionAlias', - match: UMB_USER_MANAGEMENT_SECTION_ALIAS, - }, - ], }, ]; - -export const manifests: Array = [...sectionsViews]; diff --git a/src/packages/user/user-group/section-view/user-group-root-workspace.element.ts b/src/packages/user/user-group/section-view/user-group-root-workspace.element.ts new file mode 100644 index 0000000000..f02687d62d --- /dev/null +++ b/src/packages/user/user-group/section-view/user-group-root-workspace.element.ts @@ -0,0 +1,21 @@ +import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../collection/index.js'; +import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +const elementName = 'umb-user-group-root-workspace'; +@customElement(elementName) +export class UmbUserGroupRootWorkspaceElement extends UmbLitElement { + override render() { + return html` + ; + `; + } +} + +export { UmbUserGroupRootWorkspaceElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserGroupRootWorkspaceElement; + } +} diff --git a/src/packages/user/user-group/section-view/user-group-section-view.element.ts b/src/packages/user/user-group/section-view/user-group-section-view.element.ts deleted file mode 100644 index 4611f0962d..0000000000 --- a/src/packages/user/user-group/section-view/user-group-section-view.element.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../collection/index.js'; -import { UMB_USER_GROUP_ENTITY_TYPE } from '../entity.js'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbRoute } from '@umbraco-cms/backoffice/router'; -import { UmbCollectionElement } from '@umbraco-cms/backoffice/collection'; -import { UmbWorkspaceElement } from '@umbraco-cms/backoffice/workspace'; - -@customElement('umb-user-group-section-view') -export class UmbUserGroupSectionViewElement extends UmbLitElement { - #routes: UmbRoute[] = [ - { - path: 'collection', - component: () => { - const element = new UmbCollectionElement(); - element.setAttribute('alias', UMB_USER_GROUP_COLLECTION_ALIAS); - return element; - }, - }, - { - path: 'user-group', - component: () => { - const element = new UmbWorkspaceElement(); - element.setAttribute('entity-type', UMB_USER_GROUP_ENTITY_TYPE); - return element; - }, - }, - { - path: '', - redirectTo: 'collection', - }, - { - path: `**`, - component: async () => (await import('@umbraco-cms/backoffice/router')).UmbRouteNotFoundElement, - }, - ]; - - override render() { - return html``; - } - - static override styles = [ - UmbTextStyles, - css` - :host { - height: 100%; - } - - #router-slot { - height: calc(100% - var(--umb-header-layout-height)); - } - `, - ]; -} - -export default UmbUserGroupSectionViewElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-user-group-section-view': UmbUserGroupSectionViewElement; - } -} diff --git a/src/packages/user/user/menu-item/manifests.ts b/src/packages/user/user/menu-item/manifests.ts index 2239c2fe0f..c1980c58ef 100644 --- a/src/packages/user/user/menu-item/manifests.ts +++ b/src/packages/user/user/menu-item/manifests.ts @@ -7,7 +7,7 @@ export const manifests: Array = [ type: 'menuItem', alias: 'Umb.MenuItem.Users', name: 'Users Menu Item', - weight: 100, + weight: 200, meta: { label: '#treeHeaders_users', icon: 'icon-user', diff --git a/src/packages/user/user/section-view/manifests.ts b/src/packages/user/user/section-view/manifests.ts index aef4c6370e..96eea28eda 100644 --- a/src/packages/user/user/section-view/manifests.ts +++ b/src/packages/user/user/section-view/manifests.ts @@ -6,7 +6,7 @@ export const manifests: Array = [ type: 'workspace', alias: 'Umb.Workspace.UserRoot', name: 'User Root Workspace View', - element: () => import('./user-root-workspace-view.element.js'), + element: () => import('./user-root-workspace.element.js'), meta: { entityType: UMB_USER_ROOT_ENTITY_TYPE, }, diff --git a/src/packages/user/user/section-view/user-root-workspace-view.element.ts b/src/packages/user/user/section-view/user-root-workspace.element.ts similarity index 100% rename from src/packages/user/user/section-view/user-root-workspace-view.element.ts rename to src/packages/user/user/section-view/user-root-workspace.element.ts From d86e4e76231ecbf88a66ce43085867b2d2ab1a9b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 12:55:06 +0200 Subject: [PATCH 181/322] update import path --- src/packages/user/user-group/paths.ts | 2 +- src/packages/user/user/paths.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/user/user-group/paths.ts b/src/packages/user/user-group/paths.ts index 6fc1f8cc7e..bcd681d6dc 100644 --- a/src/packages/user/user-group/paths.ts +++ b/src/packages/user/user-group/paths.ts @@ -1,4 +1,4 @@ -import { UMB_USER_SECTION_PATHNAME } from '../user-section/paths.js'; +import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js'; import { UMB_USER_GROUP_ENTITY_TYPE } from './entity.js'; import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/packages/user/user/paths.ts b/src/packages/user/user/paths.ts index e9040e7270..eb80086f08 100644 --- a/src/packages/user/user/paths.ts +++ b/src/packages/user/user/paths.ts @@ -1,4 +1,4 @@ -import { UMB_USER_SECTION_PATHNAME } from '../user-section/paths.js'; +import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js'; import { UMB_USER_ENTITY_TYPE } from './entity.js'; import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; From dc0cd54ece0508bc6039001c397d93ca7a34fc24 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 18:53:49 +0200 Subject: [PATCH 182/322] pass entity type from manifest --- .../menu/components/menu-item/menu-item-default.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packages/core/menu/components/menu-item/menu-item-default.element.ts b/src/packages/core/menu/components/menu-item/menu-item-default.element.ts index 75fbc48075..916598bc99 100644 --- a/src/packages/core/menu/components/menu-item/menu-item-default.element.ts +++ b/src/packages/core/menu/components/menu-item/menu-item-default.element.ts @@ -45,7 +45,8 @@ export class UmbMenuItemDefaultElement extends UmbLitElement implements UmbMenuI + .label=${this.localize.string(this.manifest.meta.label ?? this.manifest.name)} + .entityType=${this.manifest.meta.entityType}> `; } From 4a09c9f0e430312b7a8e351c75bb0d592beba836 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 21:13:01 +0200 Subject: [PATCH 183/322] add path helper to root --- src/packages/user/user/paths.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user/paths.ts b/src/packages/user/user/paths.ts index eb80086f08..210af851fd 100644 --- a/src/packages/user/user/paths.ts +++ b/src/packages/user/user/paths.ts @@ -1,8 +1,13 @@ import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js'; -import { UMB_USER_ENTITY_TYPE } from './entity.js'; +import { UMB_USER_ENTITY_TYPE, UMB_USER_ROOT_ENTITY_TYPE } from './entity.js'; import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; export const UMB_USER_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ sectionName: UMB_USER_SECTION_PATHNAME, entityType: UMB_USER_ENTITY_TYPE, }); + +export const UMB_USER_ROOT_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_USER_SECTION_PATHNAME, + entityType: UMB_USER_ROOT_ENTITY_TYPE, +}); From a8da784dc6faddc47c92881c7b9a4d144e6ec76f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 21:13:12 +0200 Subject: [PATCH 184/322] back button to root --- .../user/user/workspace/user-workspace-editor.element.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/packages/user/user/workspace/user-workspace-editor.element.ts index c4e11d2175..3a1d79c7ef 100644 --- a/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -13,6 +13,8 @@ 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'; import './components/user-workspace-client-credentials/user-workspace-client-credentials.element.js'; +import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; +import { UMB_USER_ROOT_WORKSPACE_PATH } from '../paths.js'; @customElement('umb-user-workspace-editor') export class UmbUserWorkspaceEditorElement extends UmbLitElement { @@ -50,7 +52,10 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { if (!this._user) return html`User not found`; return html` - + ${this.#renderHeader()}
${this.#renderLeftColumn()}
From 1aab5dfb7bca2a2e06367d518500a9b4d29a502d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 21:39:06 +0200 Subject: [PATCH 185/322] wip create + invite entity actions --- .../create/create-user-entity-action.ts | 21 ++++ .../user/entity-actions/create/manifests.ts | 22 ++++ .../user/entity-actions/create/modal/index.ts | 8 ++ .../entity-actions/create/modal/manifests.ts | 10 ++ .../user-create-options-modal.element.ts | 108 ++++++++++++++++++ .../invite/invite-user-entity-action.ts | 11 ++ .../user/entity-actions/invite/manifests.ts | 19 +++ .../user/user/entity-actions/manifests.ts | 12 +- 8 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 src/packages/user/user/entity-actions/create/create-user-entity-action.ts create mode 100644 src/packages/user/user/entity-actions/create/manifests.ts create mode 100644 src/packages/user/user/entity-actions/create/modal/index.ts create mode 100644 src/packages/user/user/entity-actions/create/modal/manifests.ts create mode 100644 src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts create mode 100644 src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts create mode 100644 src/packages/user/user/entity-actions/invite/manifests.ts diff --git a/src/packages/user/user/entity-actions/create/create-user-entity-action.ts b/src/packages/user/user/entity-actions/create/create-user-entity-action.ts new file mode 100644 index 0000000000..a6da26da4f --- /dev/null +++ b/src/packages/user/user/entity-actions/create/create-user-entity-action.ts @@ -0,0 +1,21 @@ +import { UMB_USER_CREATE_OPTIONS_MODAL } from './modal/index.js'; +import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; + +export class UmbCreateUserEntityAction extends UmbEntityActionBase { + override async execute() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const modalContext = modalManager.open(this, UMB_USER_CREATE_OPTIONS_MODAL, { + data: { + parent: { + unique: this.args.unique, + entityType: this.args.entityType, + }, + }, + }); + + await modalContext.onSubmit(); + } +} + +export { UmbCreateUserEntityAction as api }; diff --git a/src/packages/user/user/entity-actions/create/manifests.ts b/src/packages/user/user/entity-actions/create/manifests.ts new file mode 100644 index 0000000000..7915152337 --- /dev/null +++ b/src/packages/user/user/entity-actions/create/manifests.ts @@ -0,0 +1,22 @@ +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; + +import { manifests as modalManifests } from './modal/manifests.js'; + +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + kind: 'default', + alias: 'Umb.EntityAction.User.Create', + name: 'Create User Entity Action', + weight: 1200, + api: () => import('./create-user-entity-action.js'), + forEntityTypes: [UMB_USER_ROOT_ENTITY_TYPE], + meta: { + icon: 'icon-add', + label: '#actions_create', + }, + }, + ...modalManifests, +]; diff --git a/src/packages/user/user/entity-actions/create/modal/index.ts b/src/packages/user/user/entity-actions/create/modal/index.ts new file mode 100644 index 0000000000..778a1fe38d --- /dev/null +++ b/src/packages/user/user/entity-actions/create/modal/index.ts @@ -0,0 +1,8 @@ +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export const UMB_USER_CREATE_OPTIONS_MODAL = new UmbModalToken('Umb.Modal.User.CreateOptions', { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/packages/user/user/entity-actions/create/modal/manifests.ts b/src/packages/user/user/entity-actions/create/modal/manifests.ts new file mode 100644 index 0000000000..2c736c75fd --- /dev/null +++ b/src/packages/user/user/entity-actions/create/modal/manifests.ts @@ -0,0 +1,10 @@ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.User.CreateOptions', + name: 'User Create Options Modal', + element: () => import('./user-create-options-modal.element.js'), + }, +]; diff --git a/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts b/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts new file mode 100644 index 0000000000..29932ea273 --- /dev/null +++ b/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts @@ -0,0 +1,108 @@ +import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal.token.js'; +import { UmbUserKind, type UmbUserKindType } from '../../../utils/index.js'; +import { html, customElement, map } from '@umbraco-cms/backoffice/external/lit'; +import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; +import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; + +interface UmbUserCreateOptionModel { + label: string; + description: string; + icon: string; + kind: UmbUserKindType; +} + +const elementName = 'umb-user-create-options-modal'; +@customElement(elementName) +export class UmbUserCreateOptionsModalElement extends UmbModalBaseElement { + #options: Array = [ + { + label: this.localize.term('user_userKindDefault'), + description: 'Donec augue nunc, ullamcorper non turpis ut, maximus facilisis lorem. Nunc id sagittis magna.', + icon: 'icon-user', + kind: UmbUserKind.DEFAULT, + }, + { + label: this.localize.term('user_userKindApi'), + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + icon: 'icon-unplug', + kind: UmbUserKind.API, + }, + ]; + + async #onClick(event: Event, kind: UmbUserKindType) { + event.stopPropagation(); + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); + + const unique = entityContext.getUnique(); + const entityType = entityContext.getEntityType(); + + if (unique === undefined) throw new Error('Missing unique'); + if (!entityType) throw new Error('Missing entityType'); + + const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { + data: { + user: { + kind, + }, + }, + }); + + modalContext + ?.onSubmit() + .then(() => { + this.#requestReloadChildrenOfEntity({ entityType, unique }); + }) + .catch(async () => { + // modal is closed after creation instead of navigating to the new user. + // We therefore need to reload the children of the entity + this.#requestReloadChildrenOfEntity({ entityType, unique }); + }); + } + + async #requestReloadChildrenOfEntity({ entityType, unique }: UmbEntityModel) { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadChildrenOfEntityEvent({ + entityType, + unique, + }); + + eventContext.dispatchEvent(event); + } + + override render() { + return html` + + + + ${map( + this.#options, + (item) => html` + this.#onClick(event, item.kind)}> + `, + )} + + + + + `; + } +} + +export { UmbUserCreateOptionsModalElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserCreateOptionsModalElement; + } +} diff --git a/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts b/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts new file mode 100644 index 0000000000..4ac61a28d5 --- /dev/null +++ b/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts @@ -0,0 +1,11 @@ +import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; + +export class UmbCreateUserEntityAction extends UmbEntityActionBase { + override async execute() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + debugger; + } +} + +export { UmbCreateUserEntityAction as api }; diff --git a/src/packages/user/user/entity-actions/invite/manifests.ts b/src/packages/user/user/entity-actions/invite/manifests.ts new file mode 100644 index 0000000000..0fc1e67e74 --- /dev/null +++ b/src/packages/user/user/entity-actions/invite/manifests.ts @@ -0,0 +1,19 @@ +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; + +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + kind: 'default', + alias: 'Umb.EntityAction.User.Invite', + name: 'Invite User Entity Action', + weight: 1000, + api: () => import('./invite-user-entity-action.js'), + forEntityTypes: [UMB_USER_ROOT_ENTITY_TYPE], + meta: { + icon: 'icon-paper-plane', + label: '#user_invite', + }, + }, +]; diff --git a/src/packages/user/user/entity-actions/manifests.ts b/src/packages/user/user/entity-actions/manifests.ts index b67955449e..493f108ff1 100644 --- a/src/packages/user/user/entity-actions/manifests.ts +++ b/src/packages/user/user/entity-actions/manifests.ts @@ -1,6 +1,10 @@ import { UMB_USER_DETAIL_REPOSITORY_ALIAS, UMB_USER_ITEM_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_USER_ENTITY_TYPE } from '../entity.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +import { manifests as createManifests } from './create/manifests.js'; +import { manifests as inviteManifests } from './invite/manifests.js'; + +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; const entityActions: Array = [ { @@ -93,4 +97,8 @@ const entityActions: Array = [ }, ]; -export const manifests: Array = [...entityActions]; +export const manifests: Array = [ + ...entityActions, + ...createManifests, + ...inviteManifests, +]; From fdb51a33db56570a36e35cc21ec964b6108c933d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 22:01:12 +0200 Subject: [PATCH 186/322] update back path --- src/packages/user/user-group/paths.ts | 7 ++++++- src/packages/user/user-group/workspace/constants.ts | 1 + .../workspace/user-group-workspace-editor.element.ts | 6 ++++-- 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/packages/user/user-group/workspace/constants.ts diff --git a/src/packages/user/user-group/paths.ts b/src/packages/user/user-group/paths.ts index bcd681d6dc..51aa649211 100644 --- a/src/packages/user/user-group/paths.ts +++ b/src/packages/user/user-group/paths.ts @@ -1,8 +1,13 @@ import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js'; -import { UMB_USER_GROUP_ENTITY_TYPE } from './entity.js'; +import { UMB_USER_GROUP_ENTITY_TYPE, UMB_USER_GROUP_ROOT_ENTITY_TYPE } from './entity.js'; import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; export const UMB_USER_GROUP_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ sectionName: UMB_USER_SECTION_PATHNAME, entityType: UMB_USER_GROUP_ENTITY_TYPE, }); + +export const UMB_USER_GROUP_ROOT_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_USER_SECTION_PATHNAME, + entityType: UMB_USER_GROUP_ROOT_ENTITY_TYPE, +}); diff --git a/src/packages/user/user-group/workspace/constants.ts b/src/packages/user/user-group/workspace/constants.ts new file mode 100644 index 0000000000..6972100cb8 --- /dev/null +++ b/src/packages/user/user-group/workspace/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_GROUP_WORKSPACE_ALIAS = 'Umb.Workspace.UserGroup'; diff --git a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts b/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts index 9374872d2a..a4d129dd04 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts +++ b/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts @@ -1,5 +1,7 @@ import type { UmbUserGroupDetailModel } from '../index.js'; +import { UMB_USER_GROUP_ROOT_WORKSPACE_PATH } from '../paths.js'; import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from './user-group-workspace.context-token.js'; +import { UMB_USER_GROUP_WORKSPACE_ALIAS } from './constants.js'; import type { UUIBooleanInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; @@ -170,9 +172,9 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { return html` + back-path=${UMB_USER_GROUP_ROOT_WORKSPACE_PATH}> ${this.#renderHeader()} ${this.#renderMain()} `; From 85bfc1eff01710a82e67e5879fbccf041145a8d6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:37:27 +0200 Subject: [PATCH 187/322] add to folder --- .../user/section/sidebar-app/index.ts | 2 +- src/packages/user/user-group/manifests.ts | 4 +- ...orkspace-action-user-group-save.element.ts | 2 +- .../user-allow-action-base.condition.ts | 2 +- src/packages/user/user/workspace/manifests.ts | 44 ++----------------- .../user-workspace-action-save.element.ts | 0 .../user-workspace-access.element.ts | 2 +- .../user-workspace-assign-access.element.ts | 2 +- .../user-workspace-avatar.element.ts | 2 +- ...er-workspace-client-credentials.element.ts | 8 ++-- .../user-workspace-info.element.ts | 8 ++-- ...user-workspace-profile-settings.element.ts | 4 +- .../user/workspace/{ => user}/constants.ts | 0 .../user/user/workspace/user/manifests.ts | 42 ++++++++++++++++++ .../user-workspace-editor.element.ts | 6 +-- .../user-workspace.context-token.ts | 2 +- .../{ => user}/user-workspace.context.ts | 10 ++--- .../{ => user}/user-workspace.test.ts | 0 18 files changed, 72 insertions(+), 68 deletions(-) rename src/packages/user/user/workspace/{ => user}/actions/user-workspace-action-save.element.ts (100%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-access/user-workspace-access.element.ts (97%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-assign-access/user-workspace-assign-access.element.ts (99%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-avatar/user-workspace-avatar.element.ts (97%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts (93%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-info/user-workspace-info.element.ts (95%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts (97%) rename src/packages/user/user/workspace/{ => user}/constants.ts (100%) create mode 100644 src/packages/user/user/workspace/user/manifests.ts rename src/packages/user/user/workspace/{ => user}/user-workspace-editor.element.ts (97%) rename src/packages/user/user/workspace/{ => user}/user-workspace.context-token.ts (89%) rename src/packages/user/user/workspace/{ => user}/user-workspace.context.ts (94%) rename src/packages/user/user/workspace/{ => user}/user-workspace.test.ts (100%) diff --git a/src/packages/user/section/sidebar-app/index.ts b/src/packages/user/section/sidebar-app/index.ts index 4f07201dcf..42f853e5be 100644 --- a/src/packages/user/section/sidebar-app/index.ts +++ b/src/packages/user/section/sidebar-app/index.ts @@ -1 +1 @@ -export * from './constants.js'; +export * from '../constants.js'; diff --git a/src/packages/user/user-group/manifests.ts b/src/packages/user/user-group/manifests.ts index 1ac88d4e75..a68693f9c3 100644 --- a/src/packages/user/user-group/manifests.ts +++ b/src/packages/user/user-group/manifests.ts @@ -7,9 +7,9 @@ import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ +export const manifests: Array = [ ...collectionManifests, ...entityActionManifests, ...entityBulkActionManifests, diff --git a/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts b/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts index 1c86ca5b08..530c72b616 100644 --- a/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts +++ b/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts @@ -1,4 +1,4 @@ -import { UMB_USER_WORKSPACE_CONTEXT } from '../../../user/workspace/user-workspace.context-token.js'; +import { UMB_USER_WORKSPACE_CONTEXT } from '../../../user/workspace/user/user-workspace.context-token.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/packages/user/user/conditions/user-allow-action-base.condition.ts b/src/packages/user/user/conditions/user-allow-action-base.condition.ts index bdae21f4af..7dffc20550 100644 --- a/src/packages/user/user/conditions/user-allow-action-base.condition.ts +++ b/src/packages/user/user/conditions/user-allow-action-base.condition.ts @@ -1,5 +1,5 @@ import type { UmbUserStateEnum } from '../types.js'; -import { UMB_USER_WORKSPACE_CONTEXT } from '../workspace/user-workspace.context-token.js'; +import { UMB_USER_WORKSPACE_CONTEXT } from '../workspace/user/user-workspace.context-token.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { isCurrentUser } from '@umbraco-cms/backoffice/current-user'; import type { diff --git a/src/packages/user/user/workspace/manifests.ts b/src/packages/user/user/workspace/manifests.ts index d2c5c90ec4..a8bafd21d8 100644 --- a/src/packages/user/user/workspace/manifests.ts +++ b/src/packages/user/user/workspace/manifests.ts @@ -1,42 +1,4 @@ -import { UMB_USER_ENTITY_TYPE } from '../entity.js'; -import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; -import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; -import type { - ManifestWorkspaces, - ManifestWorkspaceActions, - ManifestTypes, -} from '@umbraco-cms/backoffice/extension-registry'; +import { manifests as userManifests } from './user/manifests.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -const workspace: ManifestWorkspaces = { - type: 'workspace', - kind: 'routable', - alias: UMB_USER_WORKSPACE_ALIAS, - name: 'User Workspace', - api: () => import('./user-workspace.context.js'), - meta: { - entityType: UMB_USER_ENTITY_TYPE, - }, -}; - -const workspaceActions: Array = [ - { - type: 'workspaceAction', - kind: 'default', - alias: 'Umb.WorkspaceAction.User.Save', - name: 'Save User Workspace Action', - api: UmbSubmitWorkspaceAction, - meta: { - label: '#buttons_save', - look: 'primary', - color: 'positive', - }, - conditions: [ - { - alias: 'Umb.Condition.WorkspaceAlias', - match: workspace.alias, - }, - ], - }, -]; - -export const manifests: Array = [workspace, ...workspaceActions]; +export const manifests: Array = [...userManifests]; diff --git a/src/packages/user/user/workspace/actions/user-workspace-action-save.element.ts b/src/packages/user/user/workspace/user/actions/user-workspace-action-save.element.ts similarity index 100% rename from src/packages/user/user/workspace/actions/user-workspace-action-save.element.ts rename to src/packages/user/user/workspace/user/actions/user-workspace-action-save.element.ts diff --git a/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-access/user-workspace-access.element.ts similarity index 97% rename from src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-access/user-workspace-access.element.ts index 7177e91909..86197319e5 100644 --- a/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-access/user-workspace-access.element.ts @@ -1,5 +1,5 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserStartNodesModel } from '../../../types.js'; +import type { UmbUserStartNodesModel } 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'; diff --git a/src/packages/user/user/workspace/components/user-workspace-assign-access/user-workspace-assign-access.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-assign-access/user-workspace-assign-access.element.ts similarity index 99% rename from src/packages/user/user/workspace/components/user-workspace-assign-access/user-workspace-assign-access.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-assign-access/user-workspace-assign-access.element.ts index 6a7a881039..d32bb6e0fd 100644 --- a/src/packages/user/user/workspace/components/user-workspace-assign-access/user-workspace-assign-access.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-assign-access/user-workspace-assign-access.element.ts @@ -1,5 +1,5 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserDetailModel } from '../../../types.js'; +import type { UmbUserDetailModel } from '../../../../types.js'; import { html, customElement, state, nothing, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; diff --git a/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-avatar/user-workspace-avatar.element.ts similarity index 97% rename from src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-avatar/user-workspace-avatar.element.ts index b3c7317d12..9400230d7a 100644 --- a/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-avatar/user-workspace-avatar.element.ts @@ -1,4 +1,4 @@ -import type { UmbUserDetailModel } from '../../../types.js'; +import type { UmbUserDetailModel } from '../../../../types.js'; import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; import { css, html, customElement, query, nothing, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts similarity index 93% rename from src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index 512d97f2d6..7d77417056 100644 --- a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -2,10 +2,10 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.j import type { UmbDeleteUserClientCredentialRequestArgs, UmbUserClientCredentialModel, -} from '../../../client-credential/index.js'; -import { UmbUserClientCredentialRepository } from '../../../client-credential/index.js'; -import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; -import { UmbUserKind } from '../../../utils/index.js'; +} from '../../../../client-credential/index.js'; +import { UmbUserClientCredentialRepository } from '../../../../client-credential/index.js'; +import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; +import { UmbUserKind } from '../../../../utils/index.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'; diff --git a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-info/user-workspace-info.element.ts similarity index 95% rename from src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-info/user-workspace-info.element.ts index 898bea5823..8f5d2437b0 100644 --- a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-info/user-workspace-info.element.ts @@ -1,8 +1,8 @@ -import type { UmbUserDisplayStatus } from '../../../utils.js'; -import { TimeFormatOptions, getDisplayStateFromUserStatus } from '../../../utils.js'; +import type { UmbUserDisplayStatus } from '../../../../utils.js'; +import { TimeFormatOptions, getDisplayStateFromUserStatus } from '../../../../utils.js'; import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserDetailModel } from '../../../types.js'; -import { UmbUserKind } from '../../../utils/index.js'; +import type { UmbUserDetailModel } from '../../../../types.js'; +import { UmbUserKind } from '../../../../utils/index.js'; import { html, customElement, state, css, repeat, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; diff --git a/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts similarity index 97% rename from src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts index fd4e67c615..0d313eb130 100644 --- a/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts @@ -1,11 +1,11 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserDetailModel } from '../../../types.js'; +import type { UmbUserDetailModel } from '../../../../types.js'; +import { UmbUserKind } from '../../../../utils/index.js'; import { html, customElement, state, ifDefined, 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 { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbUiCultureInputElement } from '@umbraco-cms/backoffice/localization'; -import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-workspace-profile-settings') export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { diff --git a/src/packages/user/user/workspace/constants.ts b/src/packages/user/user/workspace/user/constants.ts similarity index 100% rename from src/packages/user/user/workspace/constants.ts rename to src/packages/user/user/workspace/user/constants.ts diff --git a/src/packages/user/user/workspace/user/manifests.ts b/src/packages/user/user/workspace/user/manifests.ts new file mode 100644 index 0000000000..3f4203dd88 --- /dev/null +++ b/src/packages/user/user/workspace/user/manifests.ts @@ -0,0 +1,42 @@ +import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; +import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; +import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import type { + ManifestWorkspaces, + ManifestWorkspaceActions, + ManifestTypes, +} from '@umbraco-cms/backoffice/extension-registry'; + +const workspace: ManifestWorkspaces = { + type: 'workspace', + kind: 'routable', + alias: UMB_USER_WORKSPACE_ALIAS, + name: 'User Workspace', + api: () => import('./user-workspace.context.js'), + meta: { + entityType: UMB_USER_ENTITY_TYPE, + }, +}; + +const workspaceActions: Array = [ + { + type: 'workspaceAction', + kind: 'default', + alias: 'Umb.WorkspaceAction.User.Save', + name: 'Save User Workspace Action', + api: UmbSubmitWorkspaceAction, + meta: { + label: '#buttons_save', + look: 'primary', + color: 'positive', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: workspace.alias, + }, + ], + }, +]; + +export const manifests: Array = [workspace, ...workspaceActions]; diff --git a/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/packages/user/user/workspace/user/user-workspace-editor.element.ts similarity index 97% rename from src/packages/user/user/workspace/user-workspace-editor.element.ts rename to src/packages/user/user/workspace/user/user-workspace-editor.element.ts index 3a1d79c7ef..b65ebebf63 100644 --- a/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/packages/user/user/workspace/user/user-workspace-editor.element.ts @@ -1,6 +1,8 @@ -import type { UmbUserDetailModel } from '../index.js'; +import type { UmbUserDetailModel } from '../../index.js'; +import { UMB_USER_ROOT_WORKSPACE_PATH } from '../../paths.js'; import type { UmbUserWorkspaceContext } from './user-workspace.context.js'; import { UMB_USER_WORKSPACE_CONTEXT } from './user-workspace.context-token.js'; +import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit'; @@ -13,8 +15,6 @@ 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'; import './components/user-workspace-client-credentials/user-workspace-client-credentials.element.js'; -import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; -import { UMB_USER_ROOT_WORKSPACE_PATH } from '../paths.js'; @customElement('umb-user-workspace-editor') export class UmbUserWorkspaceEditorElement extends UmbLitElement { diff --git a/src/packages/user/user/workspace/user-workspace.context-token.ts b/src/packages/user/user/workspace/user/user-workspace.context-token.ts similarity index 89% rename from src/packages/user/user/workspace/user-workspace.context-token.ts rename to src/packages/user/user/workspace/user/user-workspace.context-token.ts index ac99021cc5..bac31a226c 100644 --- a/src/packages/user/user/workspace/user-workspace.context-token.ts +++ b/src/packages/user/user/workspace/user/user-workspace.context-token.ts @@ -1,4 +1,4 @@ -import { UMB_USER_ENTITY_TYPE } from '../entity.js'; +import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; import type { UmbUserWorkspaceContext } from './user-workspace.context.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/packages/user/user/workspace/user-workspace.context.ts b/src/packages/user/user/workspace/user/user-workspace.context.ts similarity index 94% rename from src/packages/user/user/workspace/user-workspace.context.ts rename to src/packages/user/user/workspace/user/user-workspace.context.ts index 69587e191d..18963318ec 100644 --- a/src/packages/user/user/workspace/user-workspace.context.ts +++ b/src/packages/user/user/workspace/user/user-workspace.context.ts @@ -1,8 +1,8 @@ -import type { UmbUserDetailModel, UmbUserStartNodesModel, UmbUserStateEnum } from '../types.js'; -import { UMB_USER_ENTITY_TYPE } from '../entity.js'; -import { UmbUserDetailRepository } from '../repository/index.js'; -import { UmbUserAvatarRepository } from '../repository/avatar/index.js'; -import { UmbUserConfigRepository } from '../repository/config/index.js'; +import type { UmbUserDetailModel, UmbUserStartNodesModel, UmbUserStateEnum } from '../../types.js'; +import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; +import { UmbUserDetailRepository } from '../../repository/index.js'; +import { UmbUserAvatarRepository } from '../../repository/avatar/index.js'; +import { UmbUserConfigRepository } from '../../repository/config/index.js'; import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; import { UmbUserWorkspaceEditorElement } from './user-workspace-editor.element.js'; import type { UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/packages/user/user/workspace/user-workspace.test.ts b/src/packages/user/user/workspace/user/user-workspace.test.ts similarity index 100% rename from src/packages/user/user/workspace/user-workspace.test.ts rename to src/packages/user/user/workspace/user/user-workspace.test.ts From 4a31f36f743bd6af0a0b05c21268f3e6b9ddd283 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:38:05 +0200 Subject: [PATCH 188/322] rename folder --- src/packages/user/user/{section-view => user-root}/manifests.ts | 0 .../{section-view => user-root}/user-root-workspace.element.ts | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/packages/user/user/{section-view => user-root}/manifests.ts (100%) rename src/packages/user/user/{section-view => user-root}/user-root-workspace.element.ts (100%) diff --git a/src/packages/user/user/section-view/manifests.ts b/src/packages/user/user/user-root/manifests.ts similarity index 100% rename from src/packages/user/user/section-view/manifests.ts rename to src/packages/user/user/user-root/manifests.ts diff --git a/src/packages/user/user/section-view/user-root-workspace.element.ts b/src/packages/user/user/user-root/user-root-workspace.element.ts similarity index 100% rename from src/packages/user/user/section-view/user-root-workspace.element.ts rename to src/packages/user/user/user-root/user-root-workspace.element.ts From 025bc5bd56ce83e2107e0885b4fc28b0dfcf14f9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:38:59 +0200 Subject: [PATCH 189/322] move into workspace folder --- src/packages/user/user/manifests.ts | 2 -- src/packages/user/user/workspace/manifests.ts | 3 ++- src/packages/user/user/{ => workspace}/user-root/manifests.ts | 2 +- .../{ => workspace}/user-root/user-root-workspace.element.ts | 0 4 files changed, 3 insertions(+), 4 deletions(-) rename src/packages/user/user/{ => workspace}/user-root/manifests.ts (86%) rename src/packages/user/user/{ => workspace}/user-root/user-root-workspace.element.ts (100%) diff --git a/src/packages/user/user/manifests.ts b/src/packages/user/user/manifests.ts index d842d25b03..8d11c2dc37 100644 --- a/src/packages/user/user/manifests.ts +++ b/src/packages/user/user/manifests.ts @@ -7,7 +7,6 @@ import { manifests as inviteManifests } from './invite/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; -import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; import { manifests as menuItemManifests } from './menu-item/manifests.js'; import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; @@ -22,7 +21,6 @@ export const manifests: Array = [ ...modalManifests, ...propertyEditorManifests, ...repositoryManifests, - ...sectionViewManifests, ...workspaceManifests, ...menuItemManifests, ]; diff --git a/src/packages/user/user/workspace/manifests.ts b/src/packages/user/user/workspace/manifests.ts index a8bafd21d8..09e4d463e9 100644 --- a/src/packages/user/user/workspace/manifests.ts +++ b/src/packages/user/user/workspace/manifests.ts @@ -1,4 +1,5 @@ import { manifests as userManifests } from './user/manifests.js'; +import { manifests as userRootManifests } from './user-root/manifests.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...userManifests]; +export const manifests: Array = [...userManifests, ...userRootManifests]; diff --git a/src/packages/user/user/user-root/manifests.ts b/src/packages/user/user/workspace/user-root/manifests.ts similarity index 86% rename from src/packages/user/user/user-root/manifests.ts rename to src/packages/user/user/workspace/user-root/manifests.ts index 96eea28eda..9cb07892d3 100644 --- a/src/packages/user/user/user-root/manifests.ts +++ b/src/packages/user/user/workspace/user-root/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_ROOT_ENTITY_TYPE } from '../entity.js'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ diff --git a/src/packages/user/user/user-root/user-root-workspace.element.ts b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts similarity index 100% rename from src/packages/user/user/user-root/user-root-workspace.element.ts rename to src/packages/user/user/workspace/user-root/user-root-workspace.element.ts From b40d0cf6d304599be66877698a940150089aac73 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:40:31 +0200 Subject: [PATCH 190/322] add missing type --- src/packages/user/user/workspace/manifests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/user/user/workspace/manifests.ts b/src/packages/user/user/workspace/manifests.ts index 09e4d463e9..2208cee94d 100644 --- a/src/packages/user/user/workspace/manifests.ts +++ b/src/packages/user/user/workspace/manifests.ts @@ -1,5 +1,5 @@ import { manifests as userManifests } from './user/manifests.js'; import { manifests as userRootManifests } from './user-root/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...userManifests, ...userRootManifests]; +export const manifests: Array = [...userManifests, ...userRootManifests]; From 5f843ca620d6f969ebd1b00d50cbf3496b854723 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:40:37 +0200 Subject: [PATCH 191/322] fix path --- .../user/workspace/user-root/user-root-workspace.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts index 6e286dada3..65ec9cd88c 100644 --- a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts +++ b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts @@ -1,4 +1,4 @@ -import { UMB_USER_COLLECTION_ALIAS } from '../collection/index.js'; +import { UMB_USER_COLLECTION_ALIAS } from '../../collection/index.js'; import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; From db4ec145d339d14bc2b3ba43a1019f5c66eec70e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:43:55 +0200 Subject: [PATCH 192/322] delete unused code --- ...orkspace-action-user-group-save.element.ts | 52 ------------------- 1 file changed, 52 deletions(-) delete mode 100644 src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts diff --git a/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts b/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts deleted file mode 100644 index 530c72b616..0000000000 --- a/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { UMB_USER_WORKSPACE_CONTEXT } from '../../../user/workspace/user/user-workspace.context-token.js'; -import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -// TODO: Revisit this component, it can be made via a kind with api instead. [NL] -// TODO: This seems like legacy code [NL] -@customElement('umb-workspace-action-user-group-save') -export class UmbWorkspaceActionUserGroupSaveElement extends UmbLitElement { - @state() - private _saveButtonState?: UUIButtonState; - - private _workspaceContext?: typeof UMB_USER_WORKSPACE_CONTEXT.TYPE; - - constructor() { - super(); - - this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (instance) => { - this._workspaceContext = instance; - }); - } - - private async _handleSave() { - if (!this._workspaceContext) return; - - this._saveButtonState = 'waiting'; - await this._workspaceContext - .requestSubmit() - .then(() => { - this._saveButtonState = 'success'; - }) - .catch(() => { - this._saveButtonState = 'failed'; - }); - } - - override render() { - return html``; - } -} - -export default UmbWorkspaceActionUserGroupSaveElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-workspace-action-user-group-save': UmbWorkspaceActionUserGroupSaveElement; - } -} From a75f84eca778b0ae5f4191a82a71d524fa183b31 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 16:04:02 +0200 Subject: [PATCH 193/322] set up entity context --- .../workspace/user-root/user-root-workspace.element.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts index 65ec9cd88c..2411336b55 100644 --- a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts +++ b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts @@ -1,10 +1,20 @@ import { UMB_USER_COLLECTION_ALIAS } from '../../collection/index.js'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; const elementName = 'umb-user-root-workspace'; @customElement(elementName) export class UmbUserRootWorkspaceElement extends UmbLitElement { + constructor() { + super(); + // TODO: this.should happen automatically + const entityContext = new UmbEntityContext(this); + entityContext.setEntityType(UMB_USER_ROOT_ENTITY_TYPE); + entityContext.setUnique(null); + } + override render() { return html` ; From f4d34209f417e27c631c3c9a7d31c6bd11749bb3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 16:09:03 +0200 Subject: [PATCH 194/322] add invite entity action + clean up --- .../user/user/entity-actions/manifests.ts | 7 +---- .../invite/invite-user-entity-action.ts | 4 ++- .../entity-action}/invite/manifests.ts | 2 +- .../user/invite/entity-action/manifests.ts | 28 ++++--------------- .../entity-action/resend-invite/manifests.ts | 19 +++++++++++++ src/packages/user/user/invite/manifests.ts | 4 +-- 6 files changed, 31 insertions(+), 33 deletions(-) rename src/packages/user/user/{entity-actions => invite/entity-action}/invite/invite-user-entity-action.ts (70%) rename src/packages/user/user/{entity-actions => invite/entity-action}/invite/manifests.ts (88%) diff --git a/src/packages/user/user/entity-actions/manifests.ts b/src/packages/user/user/entity-actions/manifests.ts index 493f108ff1..f59da30aeb 100644 --- a/src/packages/user/user/entity-actions/manifests.ts +++ b/src/packages/user/user/entity-actions/manifests.ts @@ -2,7 +2,6 @@ import { UMB_USER_DETAIL_REPOSITORY_ALIAS, UMB_USER_ITEM_REPOSITORY_ALIAS } from import { UMB_USER_ENTITY_TYPE } from '../entity.js'; import { manifests as createManifests } from './create/manifests.js'; -import { manifests as inviteManifests } from './invite/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; @@ -97,8 +96,4 @@ const entityActions: Array = [ }, ]; -export const manifests: Array = [ - ...entityActions, - ...createManifests, - ...inviteManifests, -]; +export const manifests: Array = [...entityActions, ...createManifests]; diff --git a/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts b/src/packages/user/user/invite/entity-action/invite/invite-user-entity-action.ts similarity index 70% rename from src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts rename to src/packages/user/user/invite/entity-action/invite/invite-user-entity-action.ts index 4ac61a28d5..7d7f86ec79 100644 --- a/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts +++ b/src/packages/user/user/invite/entity-action/invite/invite-user-entity-action.ts @@ -1,10 +1,12 @@ +import { UMB_INVITE_USER_MODAL } from '../../index.js'; import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; export class UmbCreateUserEntityAction extends UmbEntityActionBase { override async execute() { const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - debugger; + const modalContext = modalManager.open(this, UMB_INVITE_USER_MODAL); + await modalContext?.onSubmit(); } } diff --git a/src/packages/user/user/entity-actions/invite/manifests.ts b/src/packages/user/user/invite/entity-action/invite/manifests.ts similarity index 88% rename from src/packages/user/user/entity-actions/invite/manifests.ts rename to src/packages/user/user/invite/entity-action/invite/manifests.ts index 0fc1e67e74..64ca8e8772 100644 --- a/src/packages/user/user/entity-actions/invite/manifests.ts +++ b/src/packages/user/user/invite/entity-action/invite/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../../entity.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/packages/user/user/invite/entity-action/manifests.ts b/src/packages/user/user/invite/entity-action/manifests.ts index af09b5ff79..0958868a9f 100644 --- a/src/packages/user/user/invite/entity-action/manifests.ts +++ b/src/packages/user/user/invite/entity-action/manifests.ts @@ -1,27 +1,9 @@ -import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; +import { manifests as inviteManifests } from './invite/manifests.js'; import { manifests as resendInviteManifests } from './resend-invite/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -const entityActions: Array = [ - { - type: 'entityAction', - kind: 'default', - alias: 'Umb.EntityAction.User.ResendInvite', - name: 'Resend Invite User Entity Action', - weight: 500, - api: () => import('./resend-invite/resend-invite.action.js'), - forEntityTypes: [UMB_USER_ENTITY_TYPE], - meta: { - icon: 'icon-message', - label: '#actions_resendInvite', - }, - conditions: [ - { - alias: 'Umb.Condition.User.AllowResendInviteAction', - }, - ], - }, +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + ...inviteManifests, ...resendInviteManifests, ]; - -export const manifests: Array = [...entityActions]; diff --git a/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts b/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts index 87dac3af79..1525273137 100644 --- a/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts +++ b/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts @@ -1,6 +1,25 @@ +import { UMB_USER_ENTITY_TYPE } from '../../../entity.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ + { + type: 'entityAction', + kind: 'default', + alias: 'Umb.EntityAction.User.ResendInvite', + name: 'Resend Invite User Entity Action', + weight: 500, + api: () => import('./resend-invite.action.js'), + forEntityTypes: [UMB_USER_ENTITY_TYPE], + meta: { + icon: 'icon-message', + label: '#actions_resendInvite', + }, + conditions: [ + { + alias: 'Umb.Condition.User.AllowResendInviteAction', + }, + ], + }, { type: 'condition', name: 'User Allow Resend Invite Action Condition', diff --git a/src/packages/user/user/invite/manifests.ts b/src/packages/user/user/invite/manifests.ts index 63b76f1ec9..3d56168a11 100644 --- a/src/packages/user/user/invite/manifests.ts +++ b/src/packages/user/user/invite/manifests.ts @@ -2,9 +2,9 @@ import { manifests as collectionActionManifests } from './collection-action/mani import { manifests as modalManifests } from './modal/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as entityActionManifests } from './entity-action/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ +export const manifests: Array = [ ...collectionActionManifests, ...modalManifests, ...repositoryManifests, From 63ff3ef3e79c447657e44c522ff3a20af4d66f3c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 16:23:51 +0200 Subject: [PATCH 195/322] update user group create path --- src/packages/user/user-group/collection/action/manifests.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user-group/collection/action/manifests.ts b/src/packages/user/user-group/collection/action/manifests.ts index 1168e303e3..3f67cc84e1 100644 --- a/src/packages/user/user-group/collection/action/manifests.ts +++ b/src/packages/user/user-group/collection/action/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_USER_GROUP_WORKSPACE_PATH } from '../../paths.js'; import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; @@ -9,7 +10,7 @@ export const createManifest: ManifestTypes = { weight: 200, meta: { label: '#general_create', - href: 'section/user-management/view/user-groups/user-group/create', + href: `${UMB_USER_GROUP_WORKSPACE_PATH}/create`, }, conditions: [ { From 1799a95fd1042dd9a8f8b6e32e37cccdad7522cb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 21:58:23 +0200 Subject: [PATCH 196/322] revert merge mistake --- src/packages/settings/advanced/manifests.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packages/settings/advanced/manifests.ts b/src/packages/settings/advanced/manifests.ts index 3931a9edb9..5a452d9e3d 100644 --- a/src/packages/settings/advanced/manifests.ts +++ b/src/packages/settings/advanced/manifests.ts @@ -10,11 +10,11 @@ export const manifests = [ { type: 'sectionSidebarApp', kind: 'menu', - alias: 'Umb.SectionSidebarApp.Menu.Users', - name: 'Users Section Sidebar Menu', + alias: 'Umb.SectionSidebarMenu.AdvancedSettings', + name: 'Advanced Settings Sidebar Menu', weight: 100, meta: { - label: 'Users', + label: '#treeHeaders_advancedGroup', menu: UMB_ADVANCED_SETTINGS_MENU_ALIAS, }, conditions: [ From befea8161eb14147835724839d61de1631b41aa4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:48:41 +0200 Subject: [PATCH 197/322] move into folder --- .../user/user-group/workspace/manifests.ts | 44 ++----------------- ...oup-entity-user-permission-list.element.ts | 0 ...-group-granular-permission-list.element.ts | 0 .../workspace/{ => user-group}/constants.ts | 0 .../workspace/user-group/manifests.ts | 42 ++++++++++++++++++ .../user-group-workspace-editor.element.ts | 4 +- .../user-group-workspace.context-token.ts | 2 +- .../user-group-workspace.context.ts | 4 +- 8 files changed, 50 insertions(+), 46 deletions(-) rename src/packages/user/user-group/workspace/{ => user-group}/components/user-group-entity-user-permission-list.element.ts (100%) rename src/packages/user/user-group/workspace/{ => user-group}/components/user-group-granular-permission-list.element.ts (100%) rename src/packages/user/user-group/workspace/{ => user-group}/constants.ts (100%) create mode 100644 src/packages/user/user-group/workspace/user-group/manifests.ts rename src/packages/user/user-group/workspace/{ => user-group}/user-group-workspace-editor.element.ts (98%) rename src/packages/user/user-group/workspace/{ => user-group}/user-group-workspace.context-token.ts (89%) rename src/packages/user/user-group/workspace/{ => user-group}/user-group-workspace.context.ts (97%) diff --git a/src/packages/user/user-group/workspace/manifests.ts b/src/packages/user/user-group/workspace/manifests.ts index 4a593776bc..806ce0f556 100644 --- a/src/packages/user/user-group/workspace/manifests.ts +++ b/src/packages/user/user-group/workspace/manifests.ts @@ -1,42 +1,4 @@ -import type { - ManifestWorkspaces, - ManifestWorkspaceActions, - ManifestWorkspaceView, - ManifestTypes, -} from '@umbraco-cms/backoffice/extension-registry'; -import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import { manifests as userGroupManifests } from './user-group/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -const workspace: ManifestWorkspaces = { - type: 'workspace', - kind: 'routable', - alias: 'Umb.Workspace.UserGroup', - name: 'User Group Workspace', - api: () => import('./user-group-workspace.context.js'), - meta: { - entityType: 'user-group', - }, -}; - -const workspaceViews: Array = []; -const workspaceActions: Array = [ - { - type: 'workspaceAction', - kind: 'default', - alias: 'Umb.WorkspaceAction.UserGroup.Save', - name: 'Save User Group Workspace Action', - api: UmbSubmitWorkspaceAction, - meta: { - label: '#buttons_save', - look: 'primary', - color: 'positive', - }, - conditions: [ - { - alias: 'Umb.Condition.WorkspaceAlias', - match: workspace.alias, - }, - ], - }, -]; - -export const manifests: Array = [workspace, ...workspaceViews, ...workspaceActions]; +export const manifests: Array = [...userGroupManifests]; diff --git a/src/packages/user/user-group/workspace/components/user-group-entity-user-permission-list.element.ts b/src/packages/user/user-group/workspace/user-group/components/user-group-entity-user-permission-list.element.ts similarity index 100% rename from src/packages/user/user-group/workspace/components/user-group-entity-user-permission-list.element.ts rename to src/packages/user/user-group/workspace/user-group/components/user-group-entity-user-permission-list.element.ts diff --git a/src/packages/user/user-group/workspace/components/user-group-granular-permission-list.element.ts b/src/packages/user/user-group/workspace/user-group/components/user-group-granular-permission-list.element.ts similarity index 100% rename from src/packages/user/user-group/workspace/components/user-group-granular-permission-list.element.ts rename to src/packages/user/user-group/workspace/user-group/components/user-group-granular-permission-list.element.ts diff --git a/src/packages/user/user-group/workspace/constants.ts b/src/packages/user/user-group/workspace/user-group/constants.ts similarity index 100% rename from src/packages/user/user-group/workspace/constants.ts rename to src/packages/user/user-group/workspace/user-group/constants.ts diff --git a/src/packages/user/user-group/workspace/user-group/manifests.ts b/src/packages/user/user-group/workspace/user-group/manifests.ts new file mode 100644 index 0000000000..4a593776bc --- /dev/null +++ b/src/packages/user/user-group/workspace/user-group/manifests.ts @@ -0,0 +1,42 @@ +import type { + ManifestWorkspaces, + ManifestWorkspaceActions, + ManifestWorkspaceView, + ManifestTypes, +} from '@umbraco-cms/backoffice/extension-registry'; +import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; + +const workspace: ManifestWorkspaces = { + type: 'workspace', + kind: 'routable', + alias: 'Umb.Workspace.UserGroup', + name: 'User Group Workspace', + api: () => import('./user-group-workspace.context.js'), + meta: { + entityType: 'user-group', + }, +}; + +const workspaceViews: Array = []; +const workspaceActions: Array = [ + { + type: 'workspaceAction', + kind: 'default', + alias: 'Umb.WorkspaceAction.UserGroup.Save', + name: 'Save User Group Workspace Action', + api: UmbSubmitWorkspaceAction, + meta: { + label: '#buttons_save', + look: 'primary', + color: 'positive', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: workspace.alias, + }, + ], + }, +]; + +export const manifests: Array = [workspace, ...workspaceViews, ...workspaceActions]; diff --git a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts b/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts similarity index 98% rename from src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts rename to src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts index a4d129dd04..01835e7c2a 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts +++ b/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts @@ -1,5 +1,5 @@ -import type { UmbUserGroupDetailModel } from '../index.js'; -import { UMB_USER_GROUP_ROOT_WORKSPACE_PATH } from '../paths.js'; +import type { UmbUserGroupDetailModel } from '../../index.js'; +import { UMB_USER_GROUP_ROOT_WORKSPACE_PATH } from '../../paths.js'; import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from './user-group-workspace.context-token.js'; import { UMB_USER_GROUP_WORKSPACE_ALIAS } from './constants.js'; import type { UUIBooleanInputEvent } from '@umbraco-cms/backoffice/external/uui'; diff --git a/src/packages/user/user-group/workspace/user-group-workspace.context-token.ts b/src/packages/user/user-group/workspace/user-group/user-group-workspace.context-token.ts similarity index 89% rename from src/packages/user/user-group/workspace/user-group-workspace.context-token.ts rename to src/packages/user/user-group/workspace/user-group/user-group-workspace.context-token.ts index a09ae6a716..3a11176569 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace.context-token.ts +++ b/src/packages/user/user-group/workspace/user-group/user-group-workspace.context-token.ts @@ -1,4 +1,4 @@ -import { UMB_USER_GROUP_ENTITY_TYPE } from '../index.js'; +import { UMB_USER_GROUP_ENTITY_TYPE } from '../../index.js'; import type { UmbUserGroupWorkspaceContext } from './user-group-workspace.context.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/packages/user/user-group/workspace/user-group-workspace.context.ts b/src/packages/user/user-group/workspace/user-group/user-group-workspace.context.ts similarity index 97% rename from src/packages/user/user-group/workspace/user-group-workspace.context.ts rename to src/packages/user/user-group/workspace/user-group/user-group-workspace.context.ts index c360e2057f..6f81961747 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace.context.ts +++ b/src/packages/user/user-group/workspace/user-group/user-group-workspace.context.ts @@ -1,5 +1,5 @@ -import { UmbUserGroupDetailRepository } from '../repository/detail/index.js'; -import type { UmbUserGroupDetailModel } from '../types.js'; +import { UmbUserGroupDetailRepository } from '../../repository/detail/index.js'; +import type { UmbUserGroupDetailModel } from '../../types.js'; import { UmbUserGroupWorkspaceEditorElement } from './user-group-workspace-editor.element.js'; import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; import type { UmbRoutableWorkspaceContext, UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; From 7b54c75d128886c821b5ddf437cb5fd7c9ebb2de Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:49:09 +0200 Subject: [PATCH 198/322] rename folder --- .../user-group/{section-view => user-group-root}/manifests.ts | 0 .../user-group-root-workspace.element.ts | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/packages/user/user-group/{section-view => user-group-root}/manifests.ts (100%) rename src/packages/user/user-group/{section-view => user-group-root}/user-group-root-workspace.element.ts (100%) diff --git a/src/packages/user/user-group/section-view/manifests.ts b/src/packages/user/user-group/user-group-root/manifests.ts similarity index 100% rename from src/packages/user/user-group/section-view/manifests.ts rename to src/packages/user/user-group/user-group-root/manifests.ts diff --git a/src/packages/user/user-group/section-view/user-group-root-workspace.element.ts b/src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts similarity index 100% rename from src/packages/user/user-group/section-view/user-group-root-workspace.element.ts rename to src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts From cf470a9dfaf6f4b3c8b3ead05d8c4e2ed3209ee4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:49:35 +0200 Subject: [PATCH 199/322] move folder into workspace --- src/packages/user/user-group/manifests.ts | 2 +- .../user-group/{ => workspace}/user-group-root/manifests.ts | 2 +- .../user-group-root/user-group-root-workspace.element.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/packages/user/user-group/{ => workspace}/user-group-root/manifests.ts (86%) rename src/packages/user/user-group/{ => workspace}/user-group-root/user-group-root-workspace.element.ts (89%) diff --git a/src/packages/user/user-group/manifests.ts b/src/packages/user/user-group/manifests.ts index a68693f9c3..7db75cbebf 100644 --- a/src/packages/user/user-group/manifests.ts +++ b/src/packages/user/user-group/manifests.ts @@ -4,7 +4,7 @@ import { manifests as entityBulkActionManifests } from './entity-bulk-actions/ma import { manifests as menuItemManifests } from './menu-item/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; -import { manifests as sectionViewManifests } from './section-view/manifests.js'; +import { manifests as sectionViewManifests } from './workspace/user-group-root/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/packages/user/user-group/user-group-root/manifests.ts b/src/packages/user/user-group/workspace/user-group-root/manifests.ts similarity index 86% rename from src/packages/user/user-group/user-group-root/manifests.ts rename to src/packages/user/user-group/workspace/user-group-root/manifests.ts index ade0536011..ac7b088e93 100644 --- a/src/packages/user/user-group/user-group-root/manifests.ts +++ b/src/packages/user/user-group/workspace/user-group-root/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../entity.js'; +import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../../entity.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ diff --git a/src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts b/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts similarity index 89% rename from src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts rename to src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts index f02687d62d..0a77413d07 100644 --- a/src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts +++ b/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts @@ -1,4 +1,4 @@ -import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../collection/index.js'; +import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../../collection/index.js'; import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; From e287af848c30d7fb1b5babfc259c5085828f1337 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:50:58 +0200 Subject: [PATCH 200/322] localize headline --- .../user-group-root/user-group-root-workspace.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts b/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts index 0a77413d07..0900cee472 100644 --- a/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts +++ b/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts @@ -6,7 +6,7 @@ const elementName = 'umb-user-group-root-workspace'; @customElement(elementName) export class UmbUserGroupRootWorkspaceElement extends UmbLitElement { override render() { - return html` + return html` ; `; } From ea60185456e7b0a80fcb9897aeb4e31dc76e1095 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:56:11 +0200 Subject: [PATCH 201/322] localize header --- .../user/workspace/user-root/user-root-workspace.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts index 2411336b55..335f7b9590 100644 --- a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts +++ b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts @@ -16,7 +16,7 @@ export class UmbUserRootWorkspaceElement extends UmbLitElement { } override render() { - return html` + return html` ; `; } From 05f3f6f968a6dc69fd44ad96451b325e5ba53364 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 23:12:53 +0200 Subject: [PATCH 202/322] remove lorem ipsum --- .../create/modal/user-create-options-modal.element.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts b/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts index 29932ea273..74e8646990 100644 --- a/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts +++ b/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts @@ -9,7 +9,7 @@ import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/e interface UmbUserCreateOptionModel { label: string; - description: string; + description?: string; icon: string; kind: UmbUserKindType; } @@ -20,13 +20,11 @@ export class UmbUserCreateOptionsModalElement extends UmbModalBaseElement { #options: Array = [ { label: this.localize.term('user_userKindDefault'), - description: 'Donec augue nunc, ullamcorper non turpis ut, maximus facilisis lorem. Nunc id sagittis magna.', icon: 'icon-user', kind: UmbUserKind.DEFAULT, }, { label: this.localize.term('user_userKindApi'), - description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', icon: 'icon-unplug', kind: UmbUserKind.API, }, From bbacb93206659f51c90779114d5e105cfa7aa0ad Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 17:59:20 +0200 Subject: [PATCH 203/322] scaffold help package + header app --- src/apps/backoffice/backoffice.element.ts | 1 + src/packages/help/help-header-app.element.ts | 21 ++++++++++++++++++++ src/packages/help/manifests.ts | 16 +++++++++++++++ src/packages/help/umbraco-package.ts | 9 +++++++++ src/packages/help/vite.config.ts | 12 +++++++++++ 5 files changed, 59 insertions(+) create mode 100644 src/packages/help/help-header-app.element.ts create mode 100644 src/packages/help/manifests.ts create mode 100644 src/packages/help/umbraco-package.ts create mode 100644 src/packages/help/vite.config.ts diff --git a/src/apps/backoffice/backoffice.element.ts b/src/apps/backoffice/backoffice.element.ts index 144e8eda69..d54b7fc79e 100644 --- a/src/apps/backoffice/backoffice.element.ts +++ b/src/apps/backoffice/backoffice.element.ts @@ -18,6 +18,7 @@ const CORE_PACKAGES = [ import('../../packages/dictionary/umbraco-package.js'), import('../../packages/documents/umbraco-package.js'), import('../../packages/health-check/umbraco-package.js'), + import('../../packages/help/umbraco-package.js'), import('../../packages/language/umbraco-package.js'), import('../../packages/log-viewer/umbraco-package.js'), import('../../packages/markdown-editor/umbraco-package.js'), diff --git a/src/packages/help/help-header-app.element.ts b/src/packages/help/help-header-app.element.ts new file mode 100644 index 0000000000..e34b0d906b --- /dev/null +++ b/src/packages/help/help-header-app.element.ts @@ -0,0 +1,21 @@ +import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; + +const elementName = 'umb-help-header-app'; +@customElement(elementName) +export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { + override render() { + return html`
My Header App
`; + } + + static override styles: CSSResultGroup = [UmbHeaderAppButtonElement.styles, css``]; +} + +export { UmbHelpHeaderAppElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbHelpHeaderAppElement; + } +} diff --git a/src/packages/help/manifests.ts b/src/packages/help/manifests.ts new file mode 100644 index 0000000000..9504557d0d --- /dev/null +++ b/src/packages/help/manifests.ts @@ -0,0 +1,16 @@ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'headerApp', + alias: 'Umb.HeaderApp.Help', + name: 'Help Header App', + element: () => import('./help-header-app.element.js'), + weight: 0, + meta: { + label: 'TODO: how should we enable this to not be set.', + icon: 'TODO: how should we enable this to not be set.', + pathname: 'help', + }, + }, +]; diff --git a/src/packages/help/umbraco-package.ts b/src/packages/help/umbraco-package.ts new file mode 100644 index 0000000000..bbf3a996b9 --- /dev/null +++ b/src/packages/help/umbraco-package.ts @@ -0,0 +1,9 @@ +export const name = 'Umbraco.Core.Help'; +export const extensions = [ + { + name: 'Help Bundle', + alias: 'Umb.Bundle.Help', + type: 'bundle', + js: () => import('./manifests.js'), + }, +]; diff --git a/src/packages/help/vite.config.ts b/src/packages/help/vite.config.ts new file mode 100644 index 0000000000..a320e9a053 --- /dev/null +++ b/src/packages/help/vite.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vite'; +import { rmSync } from 'fs'; +import { getDefaultConfig } from '../../vite-config-base'; + +const dist = '../../../dist-cms/packages/help'; + +// delete the unbundled dist folder +rmSync(dist, { recursive: true, force: true }); + +export default defineConfig({ + ...getDefaultConfig({ dist, entry: ['manifests.ts', 'umbraco-package.ts'] }), +}); From 7779ec468169816094f445cd6aa4f3acaf51b4b4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 18:04:44 +0200 Subject: [PATCH 204/322] render button with icon --- src/packages/help/help-header-app.element.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/packages/help/help-header-app.element.ts b/src/packages/help/help-header-app.element.ts index e34b0d906b..bafddc24b0 100644 --- a/src/packages/help/help-header-app.element.ts +++ b/src/packages/help/help-header-app.element.ts @@ -6,7 +6,11 @@ const elementName = 'umb-help-header-app'; @customElement(elementName) export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { override render() { - return html`
My Header App
`; + return html` + + + + `; } static override styles: CSSResultGroup = [UmbHeaderAppButtonElement.styles, css``]; From f935bf3d19016af0385aa497414219a149958500 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 19:07:43 +0200 Subject: [PATCH 205/322] split into header app and menu + register two menu items --- .../header-app/help-header-app.element.ts | 48 +++++++++++++++++++ src/packages/help/header-app/manifests.ts | 11 +++++ src/packages/help/help-header-app.element.ts | 25 ---------- src/packages/help/manifests.ts | 17 ++----- src/packages/help/menu/constants.ts | 1 + src/packages/help/menu/index.ts | 1 + src/packages/help/menu/manifests.ts | 32 +++++++++++++ 7 files changed, 96 insertions(+), 39 deletions(-) create mode 100644 src/packages/help/header-app/help-header-app.element.ts create mode 100644 src/packages/help/header-app/manifests.ts delete mode 100644 src/packages/help/help-header-app.element.ts create mode 100644 src/packages/help/menu/constants.ts create mode 100644 src/packages/help/menu/index.ts create mode 100644 src/packages/help/menu/manifests.ts diff --git a/src/packages/help/header-app/help-header-app.element.ts b/src/packages/help/header-app/help-header-app.element.ts new file mode 100644 index 0000000000..7b0b767d13 --- /dev/null +++ b/src/packages/help/header-app/help-header-app.element.ts @@ -0,0 +1,48 @@ +import { UMB_HELP_MENU_ALIAS } from '../menu/index.js'; +import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; +import type { ManifestMenu } from '@umbraco-cms/backoffice/extension-registry'; + +const elementName = 'umb-help-header-app'; +@customElement(elementName) +export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { + @state() + private _popoverOpen = false; + + #onPopoverToggle(event: ToggleEvent) { + // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this._popoverOpen = event.newState === 'open'; + } + + override render() { + return html` + + + + + + + + + + + + `; + } + + static override styles: CSSResultGroup = [UmbHeaderAppButtonElement.styles, css``]; +} + +export { UmbHelpHeaderAppElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbHelpHeaderAppElement; + } +} diff --git a/src/packages/help/header-app/manifests.ts b/src/packages/help/header-app/manifests.ts new file mode 100644 index 0000000000..46bb441c2c --- /dev/null +++ b/src/packages/help/header-app/manifests.ts @@ -0,0 +1,11 @@ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'headerApp', + alias: 'Umb.HeaderApp.Help', + name: 'Help Header App', + element: () => import('./help-header-app.element.js'), + weight: 500, + }, +]; diff --git a/src/packages/help/help-header-app.element.ts b/src/packages/help/help-header-app.element.ts deleted file mode 100644 index bafddc24b0..0000000000 --- a/src/packages/help/help-header-app.element.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; - -const elementName = 'umb-help-header-app'; -@customElement(elementName) -export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { - override render() { - return html` - - - - `; - } - - static override styles: CSSResultGroup = [UmbHeaderAppButtonElement.styles, css``]; -} - -export { UmbHelpHeaderAppElement as element }; - -declare global { - interface HTMLElementTagNameMap { - [elementName]: UmbHelpHeaderAppElement; - } -} diff --git a/src/packages/help/manifests.ts b/src/packages/help/manifests.ts index 9504557d0d..223544e6db 100644 --- a/src/packages/help/manifests.ts +++ b/src/packages/help/manifests.ts @@ -1,16 +1,5 @@ +import { manifests as headerAppManifests } from './header-app/manifests.js'; +import { manifests as menuManifests } from './menu/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ - { - type: 'headerApp', - alias: 'Umb.HeaderApp.Help', - name: 'Help Header App', - element: () => import('./help-header-app.element.js'), - weight: 0, - meta: { - label: 'TODO: how should we enable this to not be set.', - icon: 'TODO: how should we enable this to not be set.', - pathname: 'help', - }, - }, -]; +export const manifests: Array = [...menuManifests, ...headerAppManifests]; diff --git a/src/packages/help/menu/constants.ts b/src/packages/help/menu/constants.ts new file mode 100644 index 0000000000..cae4c017c3 --- /dev/null +++ b/src/packages/help/menu/constants.ts @@ -0,0 +1 @@ +export const UMB_HELP_MENU_ALIAS = 'Umb.Menu.Help'; diff --git a/src/packages/help/menu/index.ts b/src/packages/help/menu/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/help/menu/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/help/menu/manifests.ts b/src/packages/help/menu/manifests.ts new file mode 100644 index 0000000000..06cab3d506 --- /dev/null +++ b/src/packages/help/menu/manifests.ts @@ -0,0 +1,32 @@ +import { UMB_HELP_MENU_ALIAS } from './constants.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'menu', + alias: UMB_HELP_MENU_ALIAS, + name: 'Help Menu', + }, + { + type: 'menuItem', + alias: 'Umb.MenuItem.Help.LearningBase', + name: 'Learning Base Help Menu Item', + weight: 200, + meta: { + label: 'Umbraco Learning Base', + icon: 'icon-movie-alt', + menus: [UMB_HELP_MENU_ALIAS], + }, + }, + { + type: 'menuItem', + alias: 'Umb.MenuItem.Help.CommunityWebsite', + name: 'Community Website Help Menu Item', + weight: 100, + meta: { + label: 'Community Website', + icon: 'icon-hearts', + menus: [UMB_HELP_MENU_ALIAS], + }, + }, +]; From 02b990e84445b313fdfc8d9cf601cb03b0e832fb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 08:53:36 +0200 Subject: [PATCH 206/322] add link menu item kind --- .../core/extension-registry/models/index.ts | 3 +- .../models/menu-item.model.ts | 10 +++++++ src/packages/core/manifests.ts | 2 ++ .../menu-item-layout.element.ts | 11 +++++++- .../menu-item/link/link-menu-item.element.ts | 28 +++++++++++++++++++ .../components/menu-item/link/manifests.ts | 14 ++++++++++ .../menu/components/menu-item/manifests.ts | 4 +++ src/packages/core/menu/manifests.ts | 4 +++ src/packages/help/menu/manifests.ts | 8 ++++-- 9 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 src/packages/core/menu/components/menu-item/link/link-menu-item.element.ts create mode 100644 src/packages/core/menu/components/menu-item/link/manifests.ts create mode 100644 src/packages/core/menu/components/menu-item/manifests.ts create mode 100644 src/packages/core/menu/manifests.ts diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts index 97ef8fd968..8a297a6ac8 100644 --- a/src/packages/core/extension-registry/models/index.ts +++ b/src/packages/core/extension-registry/models/index.ts @@ -29,7 +29,7 @@ import type { ManifestHealthCheck } from './health-check.model.js'; import type { ManifestIcons } from './icons.model.js'; import type { ManifestLocalization } from './localization.model.js'; import type { ManifestMenu } from './menu.model.js'; -import type { ManifestMenuItem, ManifestMenuItemTreeKind } from './menu-item.model.js'; +import type { ManifestMenuItem, ManifestMenuItemLinkKind, ManifestMenuItemTreeKind } from './menu-item.model.js'; import type { ManifestModal } from './modal.model.js'; import type { ManifestPackageView } from './package-view.model.js'; import type { ManifestPreviewAppProvider } from './preview-app.model.js'; @@ -185,6 +185,7 @@ export type ManifestTypes = | ManifestMenu | ManifestMenuItem | ManifestMenuItemTreeKind + | ManifestMenuItemLinkKind | ManifestMfaLoginProvider | ManifestModal | ManifestMonacoMarkdownEditorAction diff --git a/src/packages/core/extension-registry/models/menu-item.model.ts b/src/packages/core/extension-registry/models/menu-item.model.ts index 05eeb81b78..68f7d2f354 100644 --- a/src/packages/core/extension-registry/models/menu-item.model.ts +++ b/src/packages/core/extension-registry/models/menu-item.model.ts @@ -26,3 +26,13 @@ export interface MetaMenuItemTreeKind extends MetaMenuItem { treeAlias: string; hideTreeRoot?: boolean; } + +export interface ManifestMenuItemLinkKind extends ManifestMenuItem { + type: 'menuItem'; + kind: 'link'; + meta: MetaMenuItemLinkKind; +} + +export interface MetaMenuItemLinkKind extends MetaMenuItem { + href: string; +} diff --git a/src/packages/core/manifests.ts b/src/packages/core/manifests.ts index 893b161f1f..5fc8f5c5a8 100644 --- a/src/packages/core/manifests.ts +++ b/src/packages/core/manifests.ts @@ -9,6 +9,7 @@ import { manifests as entityBulkActionManifests } from './entity-bulk-action/man import { manifests as extensionManifests } from './extension-registry/manifests.js'; import { manifests as iconRegistryManifests } from './icon-registry/manifests.js'; import { manifests as localizationManifests } from './localization/manifests.js'; +import { manifests as menuManifests } from './menu/manifests.js'; import { manifests as modalManifests } from './modal/common/manifests.js'; import { manifests as pickerManifests } from './picker/manifests.js'; import { manifests as propertyActionManifests } from './property-action/manifests.js'; @@ -35,6 +36,7 @@ export const manifests: Array = [ ...extensionManifests, ...iconRegistryManifests, ...localizationManifests, + ...menuManifests, ...modalManifests, ...pickerManifests, ...propertyActionManifests, diff --git a/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts b/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts index e9d7291e34..af64f06949 100644 --- a/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts +++ b/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts @@ -47,6 +47,14 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { #debouncedCheckIsActive = debounce(() => this.#checkIsActive(), 100); + #getTarget() { + if (this.href && this.href.startsWith('http')) { + return '_blank'; + } + + return '_self'; + } + #checkIsActive() { if (!this.href) { this._isActive = false; @@ -63,7 +71,8 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { label=${this.label} .caretLabel=${this.localize.term('visuallyHiddenTexts_expandChildItems') + ' ' + this.label} ?active=${this._isActive} - ?has-children=${this.hasChildren}> + ?has-children=${this.hasChildren} + target=${this.#getTarget()}> ${this.entityType ? html` + + `; + } +} + +export { UmbLinkMenuItemElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbLinkMenuItemElement; + } +} diff --git a/src/packages/core/menu/components/menu-item/link/manifests.ts b/src/packages/core/menu/components/menu-item/link/manifests.ts new file mode 100644 index 0000000000..1645bd2edc --- /dev/null +++ b/src/packages/core/menu/components/menu-item/link/manifests.ts @@ -0,0 +1,14 @@ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'kind', + alias: 'Umb.Kind.MenuItem.Link', + matchKind: 'link', + matchType: 'menuItem', + manifest: { + type: 'menuItem', + element: () => import('./link-menu-item.element.js'), + }, + }, +]; diff --git a/src/packages/core/menu/components/menu-item/manifests.ts b/src/packages/core/menu/components/menu-item/manifests.ts new file mode 100644 index 0000000000..08daa5be16 --- /dev/null +++ b/src/packages/core/menu/components/menu-item/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as linkManifests } from './link/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...linkManifests]; diff --git a/src/packages/core/menu/manifests.ts b/src/packages/core/menu/manifests.ts new file mode 100644 index 0000000000..88cfb7bd3d --- /dev/null +++ b/src/packages/core/menu/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as menuItemManifests } from './components/menu-item/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...menuItemManifests]; diff --git a/src/packages/help/menu/manifests.ts b/src/packages/help/menu/manifests.ts index 06cab3d506..4d9985a5b5 100644 --- a/src/packages/help/menu/manifests.ts +++ b/src/packages/help/menu/manifests.ts @@ -9,24 +9,28 @@ export const manifests: Array = [ }, { type: 'menuItem', + kind: 'link', alias: 'Umb.MenuItem.Help.LearningBase', name: 'Learning Base Help Menu Item', weight: 200, meta: { + menus: [UMB_HELP_MENU_ALIAS], label: 'Umbraco Learning Base', icon: 'icon-movie-alt', - menus: [UMB_HELP_MENU_ALIAS], + href: 'https://learn.umbraco.com', }, }, { type: 'menuItem', + kind: 'link', alias: 'Umb.MenuItem.Help.CommunityWebsite', name: 'Community Website Help Menu Item', weight: 100, meta: { + menus: [UMB_HELP_MENU_ALIAS], label: 'Community Website', icon: 'icon-hearts', - menus: [UMB_HELP_MENU_ALIAS], + href: 'https://our.umbraco.com', }, }, ]; From 14347779c8660e67fe5e4a42ea61b53333c8af2e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 14:36:00 +0200 Subject: [PATCH 207/322] move target logic to link element --- .../menu-item-layout.element.ts | 19 ++++++++++--------- .../menu-item/link/link-menu-item.element.ts | 11 +++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts b/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts index af64f06949..b6471e064d 100644 --- a/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts +++ b/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts @@ -37,6 +37,15 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { @property({ type: String }) public href?: string; + /** + * Set an anchor tag target, only used when using href. + * @type {string} + * @attr + * @default undefined + */ + @property({ type: String }) + public target?: '_blank' | '_parent' | '_self' | '_top'; + @state() private _isActive = false; @@ -47,14 +56,6 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { #debouncedCheckIsActive = debounce(() => this.#checkIsActive(), 100); - #getTarget() { - if (this.href && this.href.startsWith('http')) { - return '_blank'; - } - - return '_self'; - } - #checkIsActive() { if (!this.href) { this._isActive = false; @@ -72,7 +73,7 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { .caretLabel=${this.localize.term('visuallyHiddenTexts_expandChildItems') + ' ' + this.label} ?active=${this._isActive} ?has-children=${this.hasChildren} - target=${this.#getTarget()}> + target=${ifDefined(this.href && this.target ? this.target : undefined)}> ${this.entityType ? html` From b72cf681f9d51edd81eb0c0a96a1dc1fcd4bb085 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 14:59:31 +0200 Subject: [PATCH 208/322] add condition to check if the current user is admin --- .../conditions/is-admin/constants.ts | 1 + .../current-user/conditions/is-admin/index.ts | 1 + .../is-admin/is-admin.condition.manifest.ts | 9 +++++++++ .../conditions/is-admin/is-admin.condition.ts | 20 +++++++++++++++++++ .../user/current-user/conditions/manifests.ts | 3 +++ src/packages/user/current-user/manifests.ts | 16 +++++++-------- 6 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 src/packages/user/current-user/conditions/is-admin/constants.ts create mode 100644 src/packages/user/current-user/conditions/is-admin/index.ts create mode 100644 src/packages/user/current-user/conditions/is-admin/is-admin.condition.manifest.ts create mode 100644 src/packages/user/current-user/conditions/is-admin/is-admin.condition.ts create mode 100644 src/packages/user/current-user/conditions/manifests.ts diff --git a/src/packages/user/current-user/conditions/is-admin/constants.ts b/src/packages/user/current-user/conditions/is-admin/constants.ts new file mode 100644 index 0000000000..2d3a8d78da --- /dev/null +++ b/src/packages/user/current-user/conditions/is-admin/constants.ts @@ -0,0 +1 @@ +export const UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS = 'Umb.Condition.CurrentUser.IsAdmin'; diff --git a/src/packages/user/current-user/conditions/is-admin/index.ts b/src/packages/user/current-user/conditions/is-admin/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/user/current-user/conditions/is-admin/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/user/current-user/conditions/is-admin/is-admin.condition.manifest.ts b/src/packages/user/current-user/conditions/is-admin/is-admin.condition.manifest.ts new file mode 100644 index 0000000000..b9c81293e0 --- /dev/null +++ b/src/packages/user/current-user/conditions/is-admin/is-admin.condition.manifest.ts @@ -0,0 +1,9 @@ +import { UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS } from './constants.js'; +import type { ManifestCondition } from '@umbraco-cms/backoffice/extension-api'; + +export const manifest: ManifestCondition = { + type: 'condition', + name: 'Current user is admin Condition', + alias: UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS, + api: () => import('./is-admin.condition.js'), +}; diff --git a/src/packages/user/current-user/conditions/is-admin/is-admin.condition.ts b/src/packages/user/current-user/conditions/is-admin/is-admin.condition.ts new file mode 100644 index 0000000000..438258d6f4 --- /dev/null +++ b/src/packages/user/current-user/conditions/is-admin/is-admin.condition.ts @@ -0,0 +1,20 @@ +import { isCurrentUserAnAdmin } from '../../utils/is-current-user.function.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { + UmbConditionConfigBase, + UmbConditionControllerArguments, + UmbExtensionCondition, +} from '@umbraco-cms/backoffice/extension-api'; +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; + +export class UmbContentHasPropertiesWorkspaceCondition + extends UmbConditionBase + implements UmbExtensionCondition +{ + constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { + super(host, args); + isCurrentUserAnAdmin(host).then((isAdmin) => (this.permitted = isAdmin)); + } +} + +export { UmbContentHasPropertiesWorkspaceCondition as api }; diff --git a/src/packages/user/current-user/conditions/manifests.ts b/src/packages/user/current-user/conditions/manifests.ts new file mode 100644 index 0000000000..63918c839e --- /dev/null +++ b/src/packages/user/current-user/conditions/manifests.ts @@ -0,0 +1,3 @@ +import { manifest as isAdminManifests } from './is-admin/is-admin.condition.manifest.js'; + +export const manifests = [isAdminManifests]; diff --git a/src/packages/user/current-user/manifests.ts b/src/packages/user/current-user/manifests.ts index dce911901e..32ebb91d36 100644 --- a/src/packages/user/current-user/manifests.ts +++ b/src/packages/user/current-user/manifests.ts @@ -1,11 +1,13 @@ import { manifest as actionDefaultKindManifest } from './action/default.kind.js'; -import { manifests as modalManifests } from './modals/manifests.js'; -import { manifests as historyManifests } from './history/manifests.js'; +import { manifests as conditionManifests } from './conditions/manifests.js'; import { manifests as externalLoginProviderManifests } from './external-login/manifests.js'; +import { manifests as historyManifests } from './history/manifests.js'; import { manifests as mfaLoginProviderManifests } from './mfa-login/manifests.js'; +import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as profileManifests } from './profile/manifests.js'; -import { manifests as themeManifests } from './theme/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; +import { manifests as themeManifests } from './theme/manifests.js'; + import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const headerApps: Array = [ @@ -21,19 +23,15 @@ export const headerApps: Array = [ name: 'Current User', element: () => import('./current-user-header-app.element.js'), weight: 0, - meta: { - label: 'TODO: how should we enable this to not be set.', - icon: 'TODO: how should we enable this to not be set.', - pathname: 'user', - }, }, ]; export const manifests = [ actionDefaultKindManifest, + ...conditionManifests, + ...externalLoginProviderManifests, ...headerApps, ...historyManifests, - ...externalLoginProviderManifests, ...mfaLoginProviderManifests, ...modalManifests, ...profileManifests, From 9e306d30a3180f4f6cbdd359eaf18fd507098002 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 15:01:55 +0200 Subject: [PATCH 209/322] export condition alias --- src/packages/user/current-user/conditions/index.ts | 1 + src/packages/user/current-user/index.ts | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 src/packages/user/current-user/conditions/index.ts diff --git a/src/packages/user/current-user/conditions/index.ts b/src/packages/user/current-user/conditions/index.ts new file mode 100644 index 0000000000..8e80a3f329 --- /dev/null +++ b/src/packages/user/current-user/conditions/index.ts @@ -0,0 +1 @@ +export * from './is-admin/index.js'; diff --git a/src/packages/user/current-user/index.ts b/src/packages/user/current-user/index.ts index 343c0ed765..606a128e69 100644 --- a/src/packages/user/current-user/index.ts +++ b/src/packages/user/current-user/index.ts @@ -1,9 +1,10 @@ export * from './action/index.js'; export * from './components/index.js'; -export * from './history/current-user-history.store.js'; -export * from './utils/index.js'; -export * from './repository/index.js'; +export * from './conditions/index.js'; export * from './current-user.context.js'; export * from './current-user.context.token.js'; +export * from './history/current-user-history.store.js'; +export * from './repository/index.js'; +export * from './utils/index.js'; export type * from './types.js'; From 83da6765515adac029fc7dca50faa6c7c533a917 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 15:02:09 +0200 Subject: [PATCH 210/322] add conditions to links --- src/packages/help/menu/manifests.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/packages/help/menu/manifests.ts b/src/packages/help/menu/manifests.ts index 4d9985a5b5..aa4b9d68c9 100644 --- a/src/packages/help/menu/manifests.ts +++ b/src/packages/help/menu/manifests.ts @@ -1,4 +1,5 @@ import { UMB_HELP_MENU_ALIAS } from './constants.js'; +import { UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS } from '@umbraco-cms/backoffice/current-user'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ @@ -19,6 +20,11 @@ export const manifests: Array = [ icon: 'icon-movie-alt', href: 'https://learn.umbraco.com', }, + conditions: [ + { + alias: UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS, + }, + ], }, { type: 'menuItem', @@ -32,5 +38,10 @@ export const manifests: Array = [ icon: 'icon-hearts', href: 'https://our.umbraco.com', }, + conditions: [ + { + alias: UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS, + }, + ], }, ]; From 1a79437df9f89b7b2731cb1f23c1a2d8bae15b5f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 15:54:25 +0200 Subject: [PATCH 211/322] update links --- src/packages/help/menu/manifests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/help/menu/manifests.ts b/src/packages/help/menu/manifests.ts index aa4b9d68c9..ee466c9a80 100644 --- a/src/packages/help/menu/manifests.ts +++ b/src/packages/help/menu/manifests.ts @@ -18,7 +18,7 @@ export const manifests: Array = [ menus: [UMB_HELP_MENU_ALIAS], label: 'Umbraco Learning Base', icon: 'icon-movie-alt', - href: 'https://learn.umbraco.com', + href: 'https://umbra.co/ulb', }, conditions: [ { @@ -36,7 +36,7 @@ export const manifests: Array = [ menus: [UMB_HELP_MENU_ALIAS], label: 'Community Website', icon: 'icon-hearts', - href: 'https://our.umbraco.com', + href: 'https://our.umbraco.com?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=our', }, conditions: [ { From d50ea877bf8cc08f36d62ee60d35910664dbb4d0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 10:34:20 +0200 Subject: [PATCH 212/322] add help module --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index bb90de7a06..cefbbb4419 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "./entity": "./dist-cms/packages/core/entity/index.js", "./event": "./dist-cms/packages/core/event/index.js", "./extension-registry": "./dist-cms/packages/core/extension-registry/index.js", + "./help": "./dist-cms/packages/core/help/index.js", "./icon": "./dist-cms/packages/core/icon-registry/index.js", "./id": "./dist-cms/packages/core/id/index.js", "./imaging": "./dist-cms/packages/media/imaging/index.js", From 4641854b4584ab0c6e1f30519431e764e95aea84 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 10:34:29 +0200 Subject: [PATCH 213/322] export alias --- src/packages/help/index.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/packages/help/index.ts diff --git a/src/packages/help/index.ts b/src/packages/help/index.ts new file mode 100644 index 0000000000..f15384a062 --- /dev/null +++ b/src/packages/help/index.ts @@ -0,0 +1 @@ +export * from './menu/index.js'; From 724cb03d7c1a234b6dde2e3141342bb4b84b8ff2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 10:34:45 +0200 Subject: [PATCH 214/322] Update tsconfig.json --- tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tsconfig.json b/tsconfig.json index cce8eece25..ee2325c332 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -69,6 +69,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@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"], + "@umbraco-cms/backoffice/help": ["./src/packages/core/help/index.ts"], "@umbraco-cms/backoffice/icon": ["./src/packages/core/icon-registry/index.ts"], "@umbraco-cms/backoffice/id": ["./src/packages/core/id/index.ts"], "@umbraco-cms/backoffice/imaging": ["./src/packages/media/imaging/index.ts"], From 462b2f14ab0394df1b3d5749aba8956bb2e067a0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 12:11:12 +0200 Subject: [PATCH 215/322] only render header app if menu has items --- .../header-app/help-header-app.element.ts | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/packages/help/header-app/help-header-app.element.ts b/src/packages/help/header-app/help-header-app.element.ts index 7b0b767d13..0c8ff69b84 100644 --- a/src/packages/help/header-app/help-header-app.element.ts +++ b/src/packages/help/header-app/help-header-app.element.ts @@ -1,8 +1,9 @@ import { UMB_HELP_MENU_ALIAS } from '../menu/index.js'; import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; -import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; -import type { ManifestMenu } from '@umbraco-cms/backoffice/extension-registry'; +import { umbExtensionsRegistry, type ManifestMenu } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; const elementName = 'umb-help-header-app'; @customElement(elementName) @@ -10,6 +11,24 @@ export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { @state() private _popoverOpen = false; + @state() + private _helpMenuHasMenuItems = false; + + constructor() { + super(); + + new UmbExtensionsManifestInitializer( + this, + umbExtensionsRegistry, + 'menuItem', + (manifest) => manifest.meta.menus.includes(UMB_HELP_MENU_ALIAS), + (menuItems) => { + const manifests = menuItems.map((menuItem) => menuItem.manifest); + this._helpMenuHasMenuItems = manifests.length > 0; + }, + ); + } + #onPopoverToggle(event: ToggleEvent) { // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -18,11 +37,21 @@ export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { } override render() { + return html` ${this.#renderButton()} ${this.#renderPopover()} `; + } + + #renderButton() { + if (!this._helpMenuHasMenuItems) return nothing; + return html` + `; + } + #renderPopover() { + return html` From a63c5f3e189fbb7b87a282567c76b195c303c715 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 12:19:56 +0200 Subject: [PATCH 216/322] update package build --- package.json | 2 +- src/packages/help/package.json | 8 ++++++++ src/packages/help/vite.config.ts | 2 +- tsconfig.json | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/packages/help/package.json diff --git a/package.json b/package.json index cefbbb4419..a522d9d100 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "./entity": "./dist-cms/packages/core/entity/index.js", "./event": "./dist-cms/packages/core/event/index.js", "./extension-registry": "./dist-cms/packages/core/extension-registry/index.js", - "./help": "./dist-cms/packages/core/help/index.js", + "./help": "./dist-cms/packages/help/index.js", "./icon": "./dist-cms/packages/core/icon-registry/index.js", "./id": "./dist-cms/packages/core/id/index.js", "./imaging": "./dist-cms/packages/media/imaging/index.js", diff --git a/src/packages/help/package.json b/src/packages/help/package.json new file mode 100644 index 0000000000..3cae8e94ec --- /dev/null +++ b/src/packages/help/package.json @@ -0,0 +1,8 @@ +{ + "name": "@umbraco-backoffice/help", + "private": true, + "type": "module", + "scripts": { + "build": "vite build" + } +} \ No newline at end of file diff --git a/src/packages/help/vite.config.ts b/src/packages/help/vite.config.ts index a320e9a053..965d250b98 100644 --- a/src/packages/help/vite.config.ts +++ b/src/packages/help/vite.config.ts @@ -8,5 +8,5 @@ const dist = '../../../dist-cms/packages/help'; rmSync(dist, { recursive: true, force: true }); export default defineConfig({ - ...getDefaultConfig({ dist, entry: ['manifests.ts', 'umbraco-package.ts'] }), + ...getDefaultConfig({ dist }), }); diff --git a/tsconfig.json b/tsconfig.json index ee2325c332..bcfc0e0b33 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -69,7 +69,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@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"], - "@umbraco-cms/backoffice/help": ["./src/packages/core/help/index.ts"], + "@umbraco-cms/backoffice/help": ["./src/packages/help/index.ts"], "@umbraco-cms/backoffice/icon": ["./src/packages/core/icon-registry/index.ts"], "@umbraco-cms/backoffice/id": ["./src/packages/core/id/index.ts"], "@umbraco-cms/backoffice/imaging": ["./src/packages/media/imaging/index.ts"], From 165ae6fd57fb039b1a10fffd5ab66326a3efdc76 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 12:38:12 +0200 Subject: [PATCH 217/322] Update package-lock.json --- package-lock.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package-lock.json b/package-lock.json index 5f5ada3f20..1800a286b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7811,6 +7811,10 @@ "resolved": "src/packages/health-check", "link": true }, + "node_modules/@umbraco-backoffice/help": { + "resolved": "src/packages/help", + "link": true + }, "node_modules/@umbraco-backoffice/language": { "resolved": "src/packages/language", "link": true @@ -23078,6 +23082,7 @@ "src/packages/health-check": { "name": "@umbraco-backoffice/health-check" }, + "src/packages/help": {}, "src/packages/language": { "name": "@umbraco-backoffice/language" }, From 6379bdd077a3f0f1a597903ece9d674da9ff4c3b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 14:57:08 +0200 Subject: [PATCH 218/322] add pattern validation --- ...ate-user-client-credential-modal.element.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts index dc48873e55..c18ac77d4b 100644 --- a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts +++ b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts @@ -7,6 +7,7 @@ import type { import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, query } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; const elementName = 'umb-create-user-client-credential-modal'; @customElement(elementName) @@ -17,10 +18,27 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement< @query('#CreateUserClientCredentialForm') _form?: HTMLFormElement; + @query('#unique') + _inputUniqueElement?: UUIInputElement; + #userClientCredentialRepository = new UmbUserClientCredentialRepository(this); #uniquePrefix = 'umbraco-back-office-'; + protected override firstUpdated(): void { + // For some reason the pattern attribute is not working with this specific regex. It complains about the regex is invalid. + // TODO: investigate why this is happening. + this._inputUniqueElement?.addValidator( + 'patternMismatch', + () => 'Only alphanumeric characters and hyphens are allowed', + () => { + const value = (this._inputUniqueElement?.value as string) || ''; + // eslint-disable-next-line no-useless-escape + return !new RegExp(/^[a-zA-Z0-9\-]+$/).test(value); + }, + ); + } + async #onSubmit(e: SubmitEvent) { e.preventDefault(); From 706410dd996641dfced101f52fcc75603082cb0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2024 10:56:38 +0200 Subject: [PATCH 219/322] extension api interface --- src/libs/extension-api/models/extension-api.interface.ts | 9 +++++++++ src/libs/extension-api/models/index.ts | 1 + 2 files changed, 10 insertions(+) create mode 100644 src/libs/extension-api/models/extension-api.interface.ts diff --git a/src/libs/extension-api/models/extension-api.interface.ts b/src/libs/extension-api/models/extension-api.interface.ts new file mode 100644 index 0000000000..0183b99fe1 --- /dev/null +++ b/src/libs/extension-api/models/extension-api.interface.ts @@ -0,0 +1,9 @@ +import type { ManifestBase } from '../types/index.js'; +import type { UmbApi } from './api.interface.js'; + +/** + * Interface for APIs of a Extension. + */ +export interface UmbExtensionApi extends UmbApi { + manifest?: ManifestType; +} diff --git a/src/libs/extension-api/models/index.ts b/src/libs/extension-api/models/index.ts index bb52c4681d..45548d385c 100644 --- a/src/libs/extension-api/models/index.ts +++ b/src/libs/extension-api/models/index.ts @@ -1,2 +1,3 @@ export * from './entry-point.interface.js'; export * from './api.interface.js'; +export * from './extension-api.interface.js'; From 6b19f2ae826de1dd5357008c3c500cda0599491a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2024 11:14:33 +0200 Subject: [PATCH 220/322] refactor block packages --- package.json | 1 + .../block-editor-custom-view.extension.ts} | 4 +-- src/packages/block/block-custom-view/index.ts | 1 + src/packages/block/block-custom-view/types.ts | 36 +++++++++++++++++++ src/packages/block/block-type/types.ts | 1 + src/packages/block/block/types.ts | 35 ------------------ src/packages/block/vite.config.ts | 1 + 7 files changed, 42 insertions(+), 37 deletions(-) rename src/packages/block/{block/block-editor-custom-view.model.ts => block-custom-view/block-editor-custom-view.extension.ts} (77%) create mode 100644 src/packages/block/block-custom-view/index.ts create mode 100644 src/packages/block/block-custom-view/types.ts diff --git a/package.json b/package.json index a522d9d100..40890bb7e1 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "./action": "./dist-cms/packages/core/action/index.js", "./audit-log": "./dist-cms/packages/core/audit-log/index.js", "./auth": "./dist-cms/packages/core/auth/index.js", + "./block-custom-view": "./dist-cms/packages/block/block-custom-view/index.js", "./block-grid": "./dist-cms/packages/block/block-grid/index.js", "./block-list": "./dist-cms/packages/block/block-list/index.js", "./block-rte": "./dist-cms/packages/block/block-rte/index.js", diff --git a/src/packages/block/block/block-editor-custom-view.model.ts b/src/packages/block/block-custom-view/block-editor-custom-view.extension.ts similarity index 77% rename from src/packages/block/block/block-editor-custom-view.model.ts rename to src/packages/block/block-custom-view/block-editor-custom-view.extension.ts index 9bbb3cd298..b82d46ec03 100644 --- a/src/packages/block/block/block-editor-custom-view.model.ts +++ b/src/packages/block/block-custom-view/block-editor-custom-view.extension.ts @@ -4,14 +4,14 @@ import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api'; export interface ManifestBlockEditorCustomView extends ManifestElement { type: 'blockEditorCustomView'; /** - * @property {string | Array } - Declare if this Custom View only must appear at specific Content Types by Alias. + * @property {string | Array } forContentTypeAlias - Declare if this Custom View only must appear at specific Content Types by Alias. * @description Optional condition if you like this custom view to only appear at for one or more specific Content Types. * @example 'my-element-type-alias' * @example ['my-element-type-alias-A', 'my-element-type-alias-B'] */ forContentTypeAlias?: string | Array; /** - * @property {string | Array } - Declare if this Custom View only must appear at specific Block Editors. + * @property {string | Array } forBlockEditor - Declare if this Custom View only must appear at specific Block Editors. * @description Optional condition if you like this custom view to only appear at a specific type of Block Editor. * @example 'block-list' * @example ['block-list', 'block-grid'] diff --git a/src/packages/block/block-custom-view/index.ts b/src/packages/block/block-custom-view/index.ts new file mode 100644 index 0000000000..06c33f562f --- /dev/null +++ b/src/packages/block/block-custom-view/index.ts @@ -0,0 +1 @@ +export type * from './types.js'; diff --git a/src/packages/block/block-custom-view/types.ts b/src/packages/block/block-custom-view/types.ts new file mode 100644 index 0000000000..63c13123f3 --- /dev/null +++ b/src/packages/block/block-custom-view/types.ts @@ -0,0 +1,36 @@ +import type { ManifestBlockEditorCustomView } from './block-editor-custom-view.extension.js'; +import type { UmbBlockLayoutBaseModel, UmbBlockDataType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; + +export type * from './block-editor-custom-view.extension.js'; + +export interface UmbBlockEditorCustomViewConfiguration { + editContentPath?: string; + editSettingsPath?: string; + showContentEdit: boolean; + showSettingsEdit: boolean; +} + +export interface UmbBlockEditorCustomViewProperties< + LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, + BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, +> { + manifest?: ManifestBlockEditorCustomView; + config?: Partial; + blockType?: BlockType; + contentUdi?: string; + label?: string; + icon?: string; + index?: number; + layout?: LayoutType; + content?: UmbBlockDataType; + settings?: UmbBlockDataType; + contentInvalid?: boolean; + settingsInvalid?: boolean; +} + +export interface UmbBlockEditorCustomViewElement< + LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, + BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, +> extends UmbBlockEditorCustomViewProperties, + HTMLElement {} diff --git a/src/packages/block/block-type/types.ts b/src/packages/block/block-type/types.ts index ece8e83203..58b67597e8 100644 --- a/src/packages/block/block-type/types.ts +++ b/src/packages/block/block-type/types.ts @@ -1,4 +1,5 @@ import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; + // Shared with the Property Editor export interface UmbBlockTypeBaseModel { contentElementTypeKey: string; diff --git a/src/packages/block/block/types.ts b/src/packages/block/block/types.ts index 55a2123751..0df9c79277 100644 --- a/src/packages/block/block/types.ts +++ b/src/packages/block/block/types.ts @@ -1,7 +1,3 @@ -import type { ManifestBlockEditorCustomView } from './block-editor-custom-view.model.js'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; -export type { ManifestBlockEditorCustomView } from './block-editor-custom-view.model.js'; - // Shared with the Property Editor export interface UmbBlockLayoutBaseModel { contentUdi: string; @@ -15,37 +11,6 @@ export interface UmbBlockDataType { [key: string]: unknown; } -export interface UmbBlockEditorCustomViewConfiguration { - editContentPath?: string; - editSettingsPath?: string; - showContentEdit: boolean; - showSettingsEdit: boolean; -} - -export interface UmbBlockEditorCustomViewProperties< - LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, - BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, -> { - manifest?: ManifestBlockEditorCustomView; - config?: Partial; - blockType?: BlockType; - contentUdi?: string; - label?: string; - icon?: string; - index?: number; - layout?: LayoutType; - content?: UmbBlockDataType; - settings?: UmbBlockDataType; - contentInvalid?: boolean; - settingsInvalid?: boolean; -} - -export interface UmbBlockEditorCustomViewElement< - LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, - BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, -> extends UmbBlockEditorCustomViewProperties, - HTMLElement {} - export interface UmbBlockValueType { layout: { [key: string]: Array | undefined }; contentData: Array; diff --git a/src/packages/block/vite.config.ts b/src/packages/block/vite.config.ts index a8a9c55143..47b4244ed0 100644 --- a/src/packages/block/vite.config.ts +++ b/src/packages/block/vite.config.ts @@ -12,6 +12,7 @@ export default defineConfig({ dist, entry: { 'block/index': 'block/index.ts', + 'block-custom-view/index': 'block-custom-view/index.ts', 'block-grid/index': 'block-grid/index.ts', 'block-list/index': 'block-list/index.ts', 'block-rte/index': 'block-rte/index.ts', From 3bf04f6add71ff40e81d66b581a7aba77af6ac25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2024 11:23:37 +0200 Subject: [PATCH 221/322] tsc corrections --- examples/block-custom-view/block-custom-view.ts | 3 ++- .../block-grid-block-inline.element.ts | 2 +- .../block-grid-block/block-grid-block.element.ts | 3 ++- .../block-grid-entry/block-grid-entry.element.ts | 10 +++++----- .../block-list-entry/block-list-entry.element.ts | 5 ++++- .../block-rte-entry/block-rte-entry.element.ts | 2 +- .../block-type-custom-view-guide.element.ts | 2 +- src/packages/block/custom-view/custom-view.element.ts | 3 ++- tsconfig.json | 1 + 9 files changed, 19 insertions(+), 12 deletions(-) diff --git a/examples/block-custom-view/block-custom-view.ts b/examples/block-custom-view/block-custom-view.ts index 61f207d30c..78de43087d 100644 --- a/examples/block-custom-view/block-custom-view.ts +++ b/examples/block-custom-view/block-custom-view.ts @@ -1,7 +1,8 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { html, customElement, LitElement, property, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; -import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view'; // eslint-disable-next-line local-rules/enforce-umb-prefix-on-element-name @customElement('example-block-custom-view') diff --git a/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts b/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts index 7aac7408c7..076752e03a 100644 --- a/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts +++ b/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts @@ -5,7 +5,7 @@ import { css, customElement, html, property, state } from '@umbraco-cms/backoffi import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import '../block-grid-areas-container/index.js'; import '../ref-grid-block/index.js'; -import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block-custom-view'; /** * @element umb-block-grid-block-inline diff --git a/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts b/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts index 325db2f6d9..1e16df8024 100644 --- a/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts +++ b/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts @@ -1,7 +1,8 @@ import { UMB_BLOCK_GRID_ENTRY_CONTEXT } from '../../context/block-grid-entry.context-token.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbBlockDataType, UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block-custom-view'; import '@umbraco-cms/backoffice/ufm'; import '../block-grid-areas-container/index.js'; diff --git a/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts b/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts index b8e9ccf1e9..a2091a3c91 100644 --- a/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts +++ b/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts @@ -10,11 +10,11 @@ import '../block-grid-block-inline/index.js'; import '../block-grid-block/index.js'; import '../block-scale-handler/index.js'; import { UmbObserveValidationStateController } from '@umbraco-cms/backoffice/validation'; -import { - type ManifestBlockEditorCustomView, - UmbDataPathBlockElementDataQuery, - type UmbBlockEditorCustomViewProperties, -} from '@umbraco-cms/backoffice/block'; +import { UmbDataPathBlockElementDataQuery } from '@umbraco-cms/backoffice/block'; +import type { + ManifestBlockEditorCustomView, + UmbBlockEditorCustomViewProperties, +} from '@umbraco-cms/backoffice/block-custom-view'; import { UUIBlinkAnimationValue, UUIBlinkKeyframes } from '@umbraco-cms/backoffice/external/uui'; import type { UmbExtensionElementInitializer } from '@umbraco-cms/backoffice/extension-api'; /** diff --git a/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts b/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts index 22b5780558..e378af99d2 100644 --- a/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts +++ b/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts @@ -8,7 +8,10 @@ import '../inline-list-block/index.js'; import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import { UmbObserveValidationStateController } from '@umbraco-cms/backoffice/validation'; import { UmbDataPathBlockElementDataQuery } from '@umbraco-cms/backoffice/block'; -import type { ManifestBlockEditorCustomView, UmbBlockEditorCustomViewProperties } from '@umbraco-cms/backoffice/block'; +import type { + ManifestBlockEditorCustomView, + UmbBlockEditorCustomViewProperties, +} from '@umbraco-cms/backoffice/block-custom-view'; /** * @element umb-block-list-entry diff --git a/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts b/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts index 8c52ee27a9..54a59940f8 100644 --- a/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts +++ b/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts @@ -4,7 +4,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, property, state, customElement } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbBlockEditorCustomViewProperties } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockEditorCustomViewProperties } from '@umbraco-cms/backoffice/block-custom-view'; import '../ref-rte-block/index.js'; diff --git a/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts b/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts index 7dbbe77f25..b2fce3bef7 100644 --- a/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts +++ b/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts @@ -7,7 +7,7 @@ import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import { UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; -import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/block'; +import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/block-custom-view'; @customElement('umb-block-type-custom-view-guide') export class UmbBlockTypeCustomViewGuideElement extends UmbLitElement { diff --git a/src/packages/block/custom-view/custom-view.element.ts b/src/packages/block/custom-view/custom-view.element.ts index 3160976674..f06fb85444 100644 --- a/src/packages/block/custom-view/custom-view.element.ts +++ b/src/packages/block/custom-view/custom-view.element.ts @@ -1,4 +1,5 @@ -import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view'; import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/tsconfig.json b/tsconfig.json index bcfc0e0b33..d6914be56f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -45,6 +45,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@umbraco-cms/backoffice/action": ["./src/packages/core/action/index.ts"], "@umbraco-cms/backoffice/audit-log": ["./src/packages/core/audit-log/index.ts"], "@umbraco-cms/backoffice/auth": ["./src/packages/core/auth/index.ts"], + "@umbraco-cms/backoffice/block-custom-view": ["./src/packages/block/block-custom-view/index.ts"], "@umbraco-cms/backoffice/block-grid": ["./src/packages/block/block-grid/index.ts"], "@umbraco-cms/backoffice/block-list": ["./src/packages/block/block-list/index.ts"], "@umbraco-cms/backoffice/block-rte": ["./src/packages/block/block-rte/index.ts"], From 9b0c8b174e627832d435761a05e1252c206b6cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2024 11:25:10 +0200 Subject: [PATCH 222/322] rename test umbraco package --- .../json-schema/{test-package.json => test-umbraco-package.json} | 1 + 1 file changed, 1 insertion(+) rename utils/json-schema/{test-package.json => test-umbraco-package.json} (99%) diff --git a/utils/json-schema/test-package.json b/utils/json-schema/test-umbraco-package.json similarity index 99% rename from utils/json-schema/test-package.json rename to utils/json-schema/test-umbraco-package.json index 26812fa8b7..11b6cf37e8 100644 --- a/utils/json-schema/test-package.json +++ b/utils/json-schema/test-umbraco-package.json @@ -8,6 +8,7 @@ "name": "My Dashboard", "alias": "myDashboard", + "weight": -10, "elementName": "my-dashboard", "js": "js/my-dashboard.js", From 820fafad9a4084088df79fb59df71b82efbfce33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2024 11:28:06 +0200 Subject: [PATCH 223/322] rename global manifest type --- examples/block-custom-view/index.ts | 2 +- src/libs/extension-api/types/manifest-bundle.interface.ts | 4 ++-- .../block-type-custom-view-guide.element.ts | 2 +- src/packages/block/custom-view/manifest.ts | 2 +- src/packages/core/extension-registry/models/index.ts | 2 +- src/packages/core/extension-registry/registry.ts | 6 +++--- src/packages/core/extension-registry/umbraco-package.ts | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/block-custom-view/index.ts b/examples/block-custom-view/index.ts index 25c1f19d2a..9bf95dc267 100644 --- a/examples/block-custom-view/index.ts +++ b/examples/block-custom-view/index.ts @@ -1,4 +1,4 @@ -export const manifests: Array = [ +export const manifests: Array = [ { type: 'blockEditorCustomView', alias: 'Umb.blockEditorCustomView.TestView', diff --git a/src/libs/extension-api/types/manifest-bundle.interface.ts b/src/libs/extension-api/types/manifest-bundle.interface.ts index f0e62ede1b..9531fb9396 100644 --- a/src/libs/extension-api/types/manifest-bundle.interface.ts +++ b/src/libs/extension-api/types/manifest-bundle.interface.ts @@ -4,7 +4,7 @@ import type { ManifestBase } from './manifest-base.interface.js'; /** * This type of extension takes a JS module and registers all exported manifests from the pointed JS file. */ -export interface ManifestBundle - extends ManifestPlainJs<{ [key: string]: Array }> { +export interface ManifestBundle + extends ManifestPlainJs<{ [key: string]: Array }> { type: 'bundle'; } diff --git a/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts b/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts index b2fce3bef7..923339fc71 100644 --- a/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts +++ b/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts @@ -89,7 +89,7 @@ export class UmbBlockTypeCustomViewGuideElement extends UmbLitElement { async #generateManifest() { const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const manifest: UmbManifestTypes = { + const manifest: UmbExtensionManifest = { type: 'blockEditorCustomView', alias: 'Local.blockEditorCustomView.' + this.#contentTypeAlias, name: 'Block Editor Custom View for ' + this.#contentTypeName, diff --git a/src/packages/block/custom-view/manifest.ts b/src/packages/block/custom-view/manifest.ts index f99b3893f1..46e74f3b3a 100644 --- a/src/packages/block/custom-view/manifest.ts +++ b/src/packages/block/custom-view/manifest.ts @@ -1,4 +1,4 @@ -export const manifest: UmbManifestTypes = { +export const manifest: UmbExtensionManifest = { type: 'blockEditorCustomView', alias: 'Umb.blockEditorCustomView.TestView', name: 'Block Editor Custom View Test', diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts index 8a297a6ac8..819ea6af8d 100644 --- a/src/packages/core/extension-registry/models/index.ts +++ b/src/packages/core/extension-registry/models/index.ts @@ -242,5 +242,5 @@ declare global { * This global type provides a union of all declared manifest types. * If this is a local package that declares additional Manifest Types, then these will also be included in this union. */ - type UmbManifestTypes = UnionOfProperties; + type UmbExtensionManifest = UnionOfProperties; } diff --git a/src/packages/core/extension-registry/registry.ts b/src/packages/core/extension-registry/registry.ts index b29da72ae5..649d77294a 100644 --- a/src/packages/core/extension-registry/registry.ts +++ b/src/packages/core/extension-registry/registry.ts @@ -1,7 +1,7 @@ import type { ManifestKind } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionRegistry } from '@umbraco-cms/backoffice/extension-api'; -export type UmbBackofficeManifestKind = ManifestKind; -export type UmbBackofficeExtensionRegistry = UmbExtensionRegistry; +export type UmbBackofficeManifestKind = ManifestKind; +export type UmbBackofficeExtensionRegistry = UmbExtensionRegistry; -export const umbExtensionsRegistry = new UmbExtensionRegistry() as UmbBackofficeExtensionRegistry; +export const umbExtensionsRegistry = new UmbExtensionRegistry() as UmbBackofficeExtensionRegistry; diff --git a/src/packages/core/extension-registry/umbraco-package.ts b/src/packages/core/extension-registry/umbraco-package.ts index 19edb76a7f..7e11d17764 100644 --- a/src/packages/core/extension-registry/umbraco-package.ts +++ b/src/packages/core/extension-registry/umbraco-package.ts @@ -37,7 +37,7 @@ export interface UmbracoPackage { * @title An array of Umbraco package manifest types that will be installed * @required */ - extensions: UmbManifestTypes[]; + extensions: UmbExtensionManifest[]; /** * @title The importmap for the package From 7c62d8a3dafa6ffc964dd3f7f8050b4d3b3eafd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2024 11:36:30 +0200 Subject: [PATCH 224/322] rename map --- .../block-editor-custom-view.extension.ts | 2 +- .../core/extension-registry/models/index.ts | 24 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/packages/block/block-custom-view/block-editor-custom-view.extension.ts b/src/packages/block/block-custom-view/block-editor-custom-view.extension.ts index b82d46ec03..2212ae53c1 100644 --- a/src/packages/block/block-custom-view/block-editor-custom-view.extension.ts +++ b/src/packages/block/block-custom-view/block-editor-custom-view.extension.ts @@ -20,7 +20,7 @@ export interface ManifestBlockEditorCustomView extends ManifestElement; + type UmbExtensionManifest = UnionOfProperties; } From 028e82c7c085019450837fb94407489cddae5924 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 13 Sep 2024 12:15:30 +0200 Subject: [PATCH 225/322] add paths --- src/packages/members/member/paths.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/packages/members/member/paths.ts diff --git a/src/packages/members/member/paths.ts b/src/packages/members/member/paths.ts new file mode 100644 index 0000000000..0686227fe9 --- /dev/null +++ b/src/packages/members/member/paths.ts @@ -0,0 +1,13 @@ +import { UMB_MEMBER_MANAGEMENT_SECTION_PATHNAME } from '../section/paths.js'; +import { UMB_MEMBER_ENTITY_TYPE, UMB_MEMBER_ROOT_ENTITY_TYPE } from './entity.js'; +import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; + +export const UMB_MEMBER_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_MEMBER_MANAGEMENT_SECTION_PATHNAME, + entityType: UMB_MEMBER_ENTITY_TYPE, +}); + +export const UMB_MEMBER_ROOT_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_MEMBER_MANAGEMENT_SECTION_PATHNAME, + entityType: UMB_MEMBER_ROOT_ENTITY_TYPE, +}); From 2ceedcf925c0ae51b0a4adc7f87e6c0800858cc0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 13 Sep 2024 12:15:39 +0200 Subject: [PATCH 226/322] use path for back button --- .../workspace/member/member-workspace-split-view.element.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/packages/members/member/workspace/member/member-workspace-split-view.element.ts b/src/packages/members/member/workspace/member/member-workspace-split-view.element.ts index af378926ed..57a751eeac 100644 --- a/src/packages/members/member/workspace/member/member-workspace-split-view.element.ts +++ b/src/packages/members/member/workspace/member/member-workspace-split-view.element.ts @@ -3,6 +3,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, nothing, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import type { ActiveVariant } from '@umbraco-cms/backoffice/workspace'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UMB_MEMBER_ROOT_WORKSPACE_PATH } from '../../paths.js'; @customElement('umb-member-workspace-split-view') export class UmbMemberWorkspaceSplitViewElement extends UmbLitElement { @@ -12,8 +13,6 @@ export class UmbMemberWorkspaceSplitViewElement extends UmbLitElement { @state() _variants?: Array; - #BACK_PATH = '/section/member-management/view/members'; - constructor() { super(); @@ -45,7 +44,7 @@ export class UmbMemberWorkspaceSplitViewElement extends UmbLitElement { (view) => html` From 18b66a682df13b61e6c2012d5550db72f39157fc Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 13 Sep 2024 12:19:15 +0200 Subject: [PATCH 227/322] register member group menu item --- src/packages/members/member-group/manifests.ts | 3 +++ .../member-group/menu-item/manifests.ts | 18 ++++++++++++++++++ .../member-workspace-split-view.element.ts | 2 +- 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/packages/members/member-group/menu-item/manifests.ts diff --git a/src/packages/members/member-group/manifests.ts b/src/packages/members/member-group/manifests.ts index b0e74f6012..ffb627fc38 100644 --- a/src/packages/members/member-group/manifests.ts +++ b/src/packages/members/member-group/manifests.ts @@ -1,16 +1,19 @@ import { manifests as collectionManifests } from './collection/manifests.js'; import { manifests as entityActionManifests } from './entity-actions/manifests.js'; import { manifests as memberGroupPickerModalManifests } from './components/member-group-picker-modal/manifests.js'; +import { manifests as menuItemManifests } from './menu-item/manifests.js'; import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; + import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ ...collectionManifests, ...entityActionManifests, ...memberGroupPickerModalManifests, + ...menuItemManifests, ...propertyEditorManifests, ...repositoryManifests, ...sectionViewManifests, diff --git a/src/packages/members/member-group/menu-item/manifests.ts b/src/packages/members/member-group/menu-item/manifests.ts new file mode 100644 index 0000000000..a3d73b4191 --- /dev/null +++ b/src/packages/members/member-group/menu-item/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_MEMBER_MANAGEMENT_MENU_ALIAS } from '../../section/menu/constants.js'; +import { UMB_MEMBER_GROUP_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'menuItem', + alias: 'Umb.MenuItem.MemberGroups', + name: 'Member Groups Menu Item', + weight: 100, + meta: { + label: '#treeHeaders_memberGroups', + icon: 'icon-users', + entityType: UMB_MEMBER_GROUP_ROOT_ENTITY_TYPE, + menus: [UMB_MEMBER_MANAGEMENT_MENU_ALIAS], + }, + }, +]; diff --git a/src/packages/members/member/workspace/member/member-workspace-split-view.element.ts b/src/packages/members/member/workspace/member/member-workspace-split-view.element.ts index 57a751eeac..978d3f89c3 100644 --- a/src/packages/members/member/workspace/member/member-workspace-split-view.element.ts +++ b/src/packages/members/member/workspace/member/member-workspace-split-view.element.ts @@ -1,9 +1,9 @@ +import { UMB_MEMBER_ROOT_WORKSPACE_PATH } from '../../paths.js'; import { UMB_MEMBER_WORKSPACE_CONTEXT } from './member-workspace.context-token.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, nothing, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import type { ActiveVariant } from '@umbraco-cms/backoffice/workspace'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_MEMBER_ROOT_WORKSPACE_PATH } from '../../paths.js'; @customElement('umb-member-workspace-split-view') export class UmbMemberWorkspaceSplitViewElement extends UmbLitElement { From ba5f0059aca57d41b246b107c5f974f9ae5c817f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 13 Sep 2024 12:27:39 +0200 Subject: [PATCH 228/322] add root workspace --- .../members/member-group/manifests.ts | 6 +- .../member-group/section-view/manifests.ts | 24 ------- .../member-group-section-view.element.ts | 61 ---------------- .../member-group/workspace/manifests.ts | 69 ++----------------- .../workspace/member-group-root/manifests.ts | 14 ++++ .../member-group-root-workspace.element.ts | 21 ++++++ .../workspace/{ => member-group}/index.ts | 0 .../workspace/member-group/manifests.ts | 65 +++++++++++++++++ .../member-group-workspace-editor.element.ts | 0 .../member-group-workspace.context-token.ts | 0 .../member-group-workspace.context.ts | 4 +- ...member-type-workspace-view-info.element.ts | 0 12 files changed, 110 insertions(+), 154 deletions(-) delete mode 100644 src/packages/members/member-group/section-view/manifests.ts delete mode 100644 src/packages/members/member-group/section-view/member-group-section-view.element.ts create mode 100644 src/packages/members/member-group/workspace/member-group-root/manifests.ts create mode 100644 src/packages/members/member-group/workspace/member-group-root/member-group-root-workspace.element.ts rename src/packages/members/member-group/workspace/{ => member-group}/index.ts (100%) create mode 100644 src/packages/members/member-group/workspace/member-group/manifests.ts rename src/packages/members/member-group/workspace/{ => member-group}/member-group-workspace-editor.element.ts (100%) rename src/packages/members/member-group/workspace/{ => member-group}/member-group-workspace.context-token.ts (100%) rename src/packages/members/member-group/workspace/{ => member-group}/member-group-workspace.context.ts (96%) rename src/packages/members/member-group/workspace/{ => member-group}/views/info/member-type-workspace-view-info.element.ts (100%) diff --git a/src/packages/members/member-group/manifests.ts b/src/packages/members/member-group/manifests.ts index ffb627fc38..a5b05512b9 100644 --- a/src/packages/members/member-group/manifests.ts +++ b/src/packages/members/member-group/manifests.ts @@ -4,18 +4,16 @@ import { manifests as memberGroupPickerModalManifests } from './components/membe import { manifests as menuItemManifests } from './menu-item/manifests.js'; import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; -import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ +export const manifests: Array = [ ...collectionManifests, ...entityActionManifests, ...memberGroupPickerModalManifests, ...menuItemManifests, ...propertyEditorManifests, ...repositoryManifests, - ...sectionViewManifests, ...workspaceManifests, ]; diff --git a/src/packages/members/member-group/section-view/manifests.ts b/src/packages/members/member-group/section-view/manifests.ts deleted file mode 100644 index 823200d358..0000000000 --- a/src/packages/members/member-group/section-view/manifests.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; - -const sectionsViews: Array = [ - { - type: 'sectionView', - alias: 'Umb.SectionView.MemberGroup', - name: 'Member Group Section View', - js: () => import('./member-group-section-view.element.js'), - weight: 100, - meta: { - label: '#treeHeaders_memberGroups', - pathname: 'member-groups', - icon: 'icon-users', - }, - conditions: [ - { - alias: 'Umb.Condition.SectionAlias', - match: 'Umb.Section.Members', - }, - ], - }, -]; - -export const manifests: Array = [...sectionsViews]; diff --git a/src/packages/members/member-group/section-view/member-group-section-view.element.ts b/src/packages/members/member-group/section-view/member-group-section-view.element.ts deleted file mode 100644 index b4809053c8..0000000000 --- a/src/packages/members/member-group/section-view/member-group-section-view.element.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { UMB_MEMBER_GROUP_COLLECTION_ALIAS } from '../collection/manifests.js'; -import { UMB_MEMBER_GROUP_ENTITY_TYPE } from '../entity.js'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbRoute } from '@umbraco-cms/backoffice/router'; - -@customElement('umb-member-group-section-view') -export class UmbMemberGroupSectionViewElement extends UmbLitElement { - #routes: UmbRoute[] = [ - { - path: 'collection', - component: () => { - const element = document.createElement('umb-collection'); - element.setAttribute('alias', UMB_MEMBER_GROUP_COLLECTION_ALIAS); - return element; - }, - }, - { - path: 'member-group', - component: () => { - const element = document.createElement('umb-workspace'); - element.setAttribute('entityType', UMB_MEMBER_GROUP_ENTITY_TYPE); - return element; - }, - }, - { - path: '', - redirectTo: 'collection', - }, - { - path: `**`, - component: async () => (await import('@umbraco-cms/backoffice/router')).UmbRouteNotFoundElement, - }, - ]; - - override render() { - return html``; - } - - static override styles = [ - UmbTextStyles, - css` - :host { - height: 100%; - } - - #router-slot { - height: calc(100% - var(--umb-header-layout-height)); - } - `, - ]; -} - -export default UmbMemberGroupSectionViewElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-member-group-section-view': UmbMemberGroupSectionViewElement; - } -} diff --git a/src/packages/members/member-group/workspace/manifests.ts b/src/packages/members/member-group/workspace/manifests.ts index 41de3338ba..14b672a263 100644 --- a/src/packages/members/member-group/workspace/manifests.ts +++ b/src/packages/members/member-group/workspace/manifests.ts @@ -1,65 +1,8 @@ -import { UMB_MEMBER_GROUP_ENTITY_TYPE } from '../entity.js'; -import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; -import type { - ManifestWorkspaces, - ManifestWorkspaceActions, - ManifestWorkspaceView, - ManifestTypes, -} from '@umbraco-cms/backoffice/extension-registry'; +import { manifests as memberGroupManifests } from './member-group/manifests.js'; +import { manifests as memberGroupRootManifests } from './member-group-root/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const UMB_MEMBER_GROUP_WORKSPACE_ALIAS = 'Umb.Workspace.MemberGroup'; - -const workspace: ManifestWorkspaces = { - type: 'workspace', - kind: 'routable', - alias: UMB_MEMBER_GROUP_WORKSPACE_ALIAS, - name: 'MemberGroup Workspace', - api: () => import('./member-group-workspace.context.js'), - meta: { - entityType: UMB_MEMBER_GROUP_ENTITY_TYPE, - }, -}; - -const workspaceActions: Array = [ - { - type: 'workspaceAction', - kind: 'default', - alias: 'Umb.WorkspaceAction.MemberGroup.Save', - name: 'Save Member Group Workspace Action', - api: UmbSubmitWorkspaceAction, - meta: { - label: '#buttons_save', - look: 'primary', - color: 'positive', - }, - conditions: [ - { - alias: 'Umb.Condition.WorkspaceAlias', - match: UMB_MEMBER_GROUP_WORKSPACE_ALIAS, - }, - ], - }, +export const manifests: Array = [ + ...memberGroupManifests, + ...memberGroupRootManifests, ]; - -export const workspaceViews: Array = [ - { - type: 'workspaceView', - alias: 'Umb.WorkspaceView.Member.Info', - name: 'Member Workspace info View', - js: () => import('./views/info/member-type-workspace-view-info.element.js'), - weight: 300, - meta: { - label: '#general_info', - pathname: 'info', - icon: 'icon-document', - }, - conditions: [ - { - alias: 'Umb.Condition.WorkspaceAlias', - match: UMB_MEMBER_GROUP_WORKSPACE_ALIAS, - }, - ], - }, -]; - -export const manifests: Array = [workspace, ...workspaceActions, ...workspaceViews]; diff --git a/src/packages/members/member-group/workspace/member-group-root/manifests.ts b/src/packages/members/member-group/workspace/member-group-root/manifests.ts new file mode 100644 index 0000000000..bcc1843ad2 --- /dev/null +++ b/src/packages/members/member-group/workspace/member-group-root/manifests.ts @@ -0,0 +1,14 @@ +import { UMB_MEMBER_GROUP_ROOT_ENTITY_TYPE } from '../../entity.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'workspace', + alias: 'Umb.Workspace.MemberGroupRoot', + name: 'Member Group Root Workspace View', + element: () => import('./member-group-root-workspace.element.js'), + meta: { + entityType: UMB_MEMBER_GROUP_ROOT_ENTITY_TYPE, + }, + }, +]; diff --git a/src/packages/members/member-group/workspace/member-group-root/member-group-root-workspace.element.ts b/src/packages/members/member-group/workspace/member-group-root/member-group-root-workspace.element.ts new file mode 100644 index 0000000000..5a600d7fc9 --- /dev/null +++ b/src/packages/members/member-group/workspace/member-group-root/member-group-root-workspace.element.ts @@ -0,0 +1,21 @@ +import { UMB_MEMBER_GROUP_COLLECTION_ALIAS } from '../../collection/index.js'; +import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +const elementName = 'umb-member-group-root-workspace'; +@customElement(elementName) +export class UmbMemberGroupRootWorkspaceElement extends UmbLitElement { + override render() { + return html` + ; + `; + } +} + +export { UmbMemberGroupRootWorkspaceElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbMemberGroupRootWorkspaceElement; + } +} diff --git a/src/packages/members/member-group/workspace/index.ts b/src/packages/members/member-group/workspace/member-group/index.ts similarity index 100% rename from src/packages/members/member-group/workspace/index.ts rename to src/packages/members/member-group/workspace/member-group/index.ts diff --git a/src/packages/members/member-group/workspace/member-group/manifests.ts b/src/packages/members/member-group/workspace/member-group/manifests.ts new file mode 100644 index 0000000000..307f83c470 --- /dev/null +++ b/src/packages/members/member-group/workspace/member-group/manifests.ts @@ -0,0 +1,65 @@ +import { UMB_MEMBER_GROUP_ENTITY_TYPE } from '../../entity.js'; +import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import type { + ManifestWorkspaces, + ManifestWorkspaceActions, + ManifestWorkspaceView, + ManifestTypes, +} from '@umbraco-cms/backoffice/extension-registry'; + +export const UMB_MEMBER_GROUP_WORKSPACE_ALIAS = 'Umb.Workspace.MemberGroup'; + +const workspace: ManifestWorkspaces = { + type: 'workspace', + kind: 'routable', + alias: UMB_MEMBER_GROUP_WORKSPACE_ALIAS, + name: 'MemberGroup Workspace', + api: () => import('./member-group-workspace.context.js'), + meta: { + entityType: UMB_MEMBER_GROUP_ENTITY_TYPE, + }, +}; + +const workspaceActions: Array = [ + { + type: 'workspaceAction', + kind: 'default', + alias: 'Umb.WorkspaceAction.MemberGroup.Save', + name: 'Save Member Group Workspace Action', + api: UmbSubmitWorkspaceAction, + meta: { + label: '#buttons_save', + look: 'primary', + color: 'positive', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: UMB_MEMBER_GROUP_WORKSPACE_ALIAS, + }, + ], + }, +]; + +export const workspaceViews: Array = [ + { + type: 'workspaceView', + alias: 'Umb.WorkspaceView.Member.Info', + name: 'Member Workspace info View', + js: () => import('./views/info/member-type-workspace-view-info.element.js'), + weight: 300, + meta: { + label: '#general_info', + pathname: 'info', + icon: 'icon-document', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: UMB_MEMBER_GROUP_WORKSPACE_ALIAS, + }, + ], + }, +]; + +export const manifests: Array = [workspace, ...workspaceActions, ...workspaceViews]; diff --git a/src/packages/members/member-group/workspace/member-group-workspace-editor.element.ts b/src/packages/members/member-group/workspace/member-group/member-group-workspace-editor.element.ts similarity index 100% rename from src/packages/members/member-group/workspace/member-group-workspace-editor.element.ts rename to src/packages/members/member-group/workspace/member-group/member-group-workspace-editor.element.ts diff --git a/src/packages/members/member-group/workspace/member-group-workspace.context-token.ts b/src/packages/members/member-group/workspace/member-group/member-group-workspace.context-token.ts similarity index 100% rename from src/packages/members/member-group/workspace/member-group-workspace.context-token.ts rename to src/packages/members/member-group/workspace/member-group/member-group-workspace.context-token.ts diff --git a/src/packages/members/member-group/workspace/member-group-workspace.context.ts b/src/packages/members/member-group/workspace/member-group/member-group-workspace.context.ts similarity index 96% rename from src/packages/members/member-group/workspace/member-group-workspace.context.ts rename to src/packages/members/member-group/workspace/member-group/member-group-workspace.context.ts index 1258127044..3534ed8daf 100644 --- a/src/packages/members/member-group/workspace/member-group-workspace.context.ts +++ b/src/packages/members/member-group/workspace/member-group/member-group-workspace.context.ts @@ -1,5 +1,5 @@ -import { UmbMemberGroupDetailRepository } from '../repository/index.js'; -import type { UmbMemberGroupDetailModel } from '../types.js'; +import { UmbMemberGroupDetailRepository } from '../../repository/index.js'; +import type { UmbMemberGroupDetailModel } from '../../types.js'; import { UMB_MEMBER_GROUP_WORKSPACE_ALIAS } from './manifests.js'; import { UmbMemberGroupWorkspaceEditorElement } from './member-group-workspace-editor.element.js'; import { diff --git a/src/packages/members/member-group/workspace/views/info/member-type-workspace-view-info.element.ts b/src/packages/members/member-group/workspace/member-group/views/info/member-type-workspace-view-info.element.ts similarity index 100% rename from src/packages/members/member-group/workspace/views/info/member-type-workspace-view-info.element.ts rename to src/packages/members/member-group/workspace/member-group/views/info/member-type-workspace-view-info.element.ts From abf5cbcdf8ad13d43d14e4148e500f707f06779f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 13 Sep 2024 12:35:02 +0200 Subject: [PATCH 229/322] set up paths --- src/packages/members/member-group/paths.ts | 13 +++++++++++++ .../member-group-workspace-editor.element.ts | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/packages/members/member-group/paths.ts diff --git a/src/packages/members/member-group/paths.ts b/src/packages/members/member-group/paths.ts new file mode 100644 index 0000000000..4a2a2b21a3 --- /dev/null +++ b/src/packages/members/member-group/paths.ts @@ -0,0 +1,13 @@ +import { UMB_MEMBER_MANAGEMENT_SECTION_PATHNAME } from '../section/paths.js'; +import { UMB_MEMBER_GROUP_ENTITY_TYPE, UMB_MEMBER_GROUP_ROOT_ENTITY_TYPE } from './entity.js'; +import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; + +export const UMB_MEMBER_GROUP_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_MEMBER_MANAGEMENT_SECTION_PATHNAME, + entityType: UMB_MEMBER_GROUP_ENTITY_TYPE, +}); + +export const UMB_MEMBER_GROUP_ROOT_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_MEMBER_MANAGEMENT_SECTION_PATHNAME, + entityType: UMB_MEMBER_GROUP_ROOT_ENTITY_TYPE, +}); diff --git a/src/packages/members/member-group/workspace/member-group/member-group-workspace-editor.element.ts b/src/packages/members/member-group/workspace/member-group/member-group-workspace-editor.element.ts index 0f7ec568cc..2ff5c6f119 100644 --- a/src/packages/members/member-group/workspace/member-group/member-group-workspace-editor.element.ts +++ b/src/packages/members/member-group/workspace/member-group/member-group-workspace-editor.element.ts @@ -1,3 +1,4 @@ +import { UMB_MEMBER_GROUP_ROOT_WORKSPACE_PATH } from '../../paths.js'; import { UMB_MEMBER_GROUP_WORKSPACE_CONTEXT } from './member-group-workspace.context-token.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; @@ -50,7 +51,7 @@ export class UmbMemberGroupWorkspaceEditorElement extends UmbLitElement { override render() { return html` - + ${this.#renderActions()}