From 409795aabcb65ad0ac17469b523454c810b49dcb Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Wed, 8 Nov 2023 18:32:04 +0100 Subject: [PATCH 01/14] Use input type search for search/filter input fields --- .../modal/common/icon-picker/icon-picker-modal.element.ts | 5 +++-- .../views/section-view-examine-searchers.ts | 1 + .../data-type-picker-flow-modal.element.ts | 1 + .../property-editor-ui-picker-modal.element.ts | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/icon-picker/icon-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/icon-picker/icon-picker-modal.element.ts index de5bccd8e4..8050305abc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/icon-picker/icon-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/icon-picker/icon-picker-modal.element.ts @@ -106,10 +106,11 @@ export class UmbIconPickerModalElement extends UmbModalBaseElement + id="searchbar" + @keyup="${this.#filterIcons}"> `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-searchers.ts b/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-searchers.ts index 2e66e61cfc..f80ee143c8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-searchers.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-searchers.ts @@ -112,6 +112,7 @@ export class UmbDashboardExamineSearcherElement extends UmbLitElement {

Search the ${this.searcherName} and view the results

Date: Wed, 8 Nov 2023 18:36:27 +0100 Subject: [PATCH 02/14] Search input type --- .../dictionary/dashboard-localization-dictionary.element.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dashboards/dictionary/dashboard-localization-dictionary.element.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dashboards/dictionary/dashboard-localization-dictionary.element.ts index 9f9831a07d..acaaa39823 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dashboards/dictionary/dashboard-localization-dictionary.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dashboards/dictionary/dashboard-localization-dictionary.element.ts @@ -129,10 +129,11 @@ export class UmbDashboardTranslationDictionaryElement extends UmbLitElement { ${this.localize.term('dictionary_createNew')} + @keyup="${this.#filter}">
From a7fd6007ac15afc3975b4f0594c7df39ab80a1dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 23 Nov 2023 14:46:16 +0100 Subject: [PATCH 03/14] pick example devops --- .../devops/example-runner/index.js | 35 +++++++++++++++++++ src/Umbraco.Web.UI.Client/package.json | 3 +- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/devops/example-runner/index.js diff --git a/src/Umbraco.Web.UI.Client/devops/example-runner/index.js b/src/Umbraco.Web.UI.Client/devops/example-runner/index.js new file mode 100644 index 0000000000..017587bf5b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/devops/example-runner/index.js @@ -0,0 +1,35 @@ +import * as globModule from 'tiny-glob'; +import * as readline from 'readline'; +import { readdir } from 'fs/promises' + +const exampleDirectory = 'examples'; + +const getDirectories = async (source) => + (await readdir(source, { withFileTypes: true })) + .filter(dirent => dirent.isDirectory()) + .map(dirent => dirent.name) + +async function pickExampleUI(){ + + // Find sub folder: + const exampleFolderNames = await getDirectories(`${exampleDirectory}`); + + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); + + console.log('Please select a folder by entering the corresponding number:'); + exampleFolderNames.forEach((folder, index) => { + console.log(`${index + 1}. ${folder}`); + }); + + rl.question('Enter your selection: ', (answer) => { + const selectedFolder = exampleFolderNames[parseInt(answer) - 1]; + console.log(`You selected: ${selectedFolder}`); + rl.close(); + }); + +}; + +pickExampleUI(); diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index eeccddd9c6..704e54b42f 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -120,7 +120,8 @@ "new-extension": "plop --plopfile ./devops/plop/plop.js", "compile": "tsc", "check": "npm run lint:errors && npm run compile && npm run build-storybook && npm run generate:jsonschema:dist", - "prepublishOnly": "node ./devops/publish/cleanse-pkg.js" + "prepublishOnly": "node ./devops/publish/cleanse-pkg.js", + "example": "node ./devops/example-runner/index.js" }, "engines": { "node": ">=20.9 <21", From 0b314e3762d0cf93e3fcb11152e9ded86c803f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 23 Nov 2023 14:46:23 +0100 Subject: [PATCH 04/14] examples folder --- src/Umbraco.Web.UI.Client/examples/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/examples/README.md diff --git a/src/Umbraco.Web.UI.Client/examples/README.md b/src/Umbraco.Web.UI.Client/examples/README.md new file mode 100644 index 0000000000..8f6d34050e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/README.md @@ -0,0 +1,7 @@ +# Backoffice Examples + +This folder contains example packages showcasing the usage of extensions in Backoffice. + +The purpose of these projects includes serving as demonstration or example for +packages, as well as testing to make sure the extension points continue +to work in these situations and to assist in developing new integrations. From 6c736639e5bf62867142d29e787fcb8ed832b438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 23 Nov 2023 14:46:33 +0100 Subject: [PATCH 05/14] simple example --- .../examples/workspace-context-counter/manifests.ts | 10 ++++++++++ .../workspace-context-counter.ts | 12 ++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/examples/workspace-context-counter/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/examples/workspace-context-counter/workspace-context-counter.ts diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/manifests.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/manifests.ts new file mode 100644 index 0000000000..19d1700461 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/manifests.ts @@ -0,0 +1,10 @@ +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: ManifestTypes = [ + { + type: 'workspaceContext', + name: 'workspaceContextCounter', + alias: 'example.workspaceCounter.counter', + js: 'workspace-context-counter.js', + } +] diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/workspace-context-counter.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/workspace-context-counter.ts new file mode 100644 index 0000000000..975ffb87d9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/workspace-context-counter.ts @@ -0,0 +1,12 @@ +import { UmbBaseController, type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +export class WorkspaceContextCounter extends UmbBaseController { + + constructor(host: UmbControllerHost) { + super(); + + console.log("HELLOOOOO WORLLLDDD") + } +} + +export const api = WorkspaceContextCounter; From fe661c297adb4fd1c8f4e26b35632a648a9ed069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 23 Nov 2023 16:03:30 +0100 Subject: [PATCH 06/14] working example --- .../devops/example-runner/index.js | 19 +++++++++++----- .../{manifests.ts => index.ts} | 2 +- .../workspace-context-counter.ts | 2 +- src/Umbraco.Web.UI.Client/index.ts | 22 +++++++++++++++++++ src/Umbraco.Web.UI.Client/tsconfig.json | 2 +- 5 files changed, 39 insertions(+), 8 deletions(-) rename src/Umbraco.Web.UI.Client/examples/workspace-context-counter/{manifests.ts => index.ts} (81%) diff --git a/src/Umbraco.Web.UI.Client/devops/example-runner/index.js b/src/Umbraco.Web.UI.Client/devops/example-runner/index.js index 017587bf5b..9f3b5a1778 100644 --- a/src/Umbraco.Web.UI.Client/devops/example-runner/index.js +++ b/src/Umbraco.Web.UI.Client/devops/example-runner/index.js @@ -1,6 +1,6 @@ -import * as globModule from 'tiny-glob'; import * as readline from 'readline'; -import { readdir } from 'fs/promises' +import { execSync } from 'child_process'; +import { readdir } from 'fs/promises'; const exampleDirectory = 'examples'; @@ -14,20 +14,29 @@ async function pickExampleUI(){ // Find sub folder: const exampleFolderNames = await getDirectories(`${exampleDirectory}`); + // Create UI: const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); - console.log('Please select a folder by entering the corresponding number:'); + // List examples: + console.log('Please select an example by entering the corresponding number:'); exampleFolderNames.forEach((folder, index) => { - console.log(`${index + 1}. ${folder}`); + console.log(`[${index + 1}] ${folder}`); }); + // Ask user to select an example: rl.question('Enter your selection: ', (answer) => { + + // User picked an example: const selectedFolder = exampleFolderNames[parseInt(answer) - 1]; console.log(`You selected: ${selectedFolder}`); - rl.close(); + + process.env['VITE_EXAMPLE_PATH'] = `${exampleDirectory}/${selectedFolder}`; + + // Start vite server: + execSync('npm run dev', {stdio: 'inherit'}); }); }; diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/manifests.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts similarity index 81% rename from src/Umbraco.Web.UI.Client/examples/workspace-context-counter/manifests.ts rename to src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts index 19d1700461..60ced48a7d 100644 --- a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/manifests.ts +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts @@ -5,6 +5,6 @@ export const manifests: ManifestTypes = [ type: 'workspaceContext', name: 'workspaceContextCounter', alias: 'example.workspaceCounter.counter', - js: 'workspace-context-counter.js', + js: () => import('./workspace-context-counter.js'), } ] diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/workspace-context-counter.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/workspace-context-counter.ts index 975ffb87d9..39738d6105 100644 --- a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/workspace-context-counter.ts +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/workspace-context-counter.ts @@ -3,7 +3,7 @@ import { UmbBaseController, type UmbControllerHost } from '@umbraco-cms/backoffi export class WorkspaceContextCounter extends UmbBaseController { constructor(host: UmbControllerHost) { - super(); + super(host); console.log("HELLOOOOO WORLLLDDD") } diff --git a/src/Umbraco.Web.UI.Client/index.ts b/src/Umbraco.Web.UI.Client/index.ts index 2afb9dadf5..6aeddf2258 100644 --- a/src/Umbraco.Web.UI.Client/index.ts +++ b/src/Umbraco.Web.UI.Client/index.ts @@ -1,4 +1,5 @@ import { UmbAppElement } from './src/apps/app/app.element.js'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { startMockServiceWorker } from './src/mocks/index.js'; if (import.meta.env.VITE_UMBRACO_USE_MSW === 'on') { @@ -18,4 +19,25 @@ if (import.meta.env.DEV) { appElement.bypassAuth = isMocking; + document.body.appendChild(appElement); + +// Move this elsewhere: +if(import.meta.env.VITE_EXAMPLE_PATH) { + console.log(import.meta.env.VITE_EXAMPLE_PATH); + import(/* @vite-ignore */ './'+import.meta.env.VITE_EXAMPLE_PATH+'/index.ts').then((js) => { + console.log("js", js); + if (js) { + Object.keys(js).forEach((key) => { + const value = js[key]; + + if (Array.isArray(value)) { + umbExtensionsRegistry.registerMany(value); + } else if (typeof value === 'object') { + umbExtensionsRegistry.register(value); + } + }); + } + }); + +} diff --git a/src/Umbraco.Web.UI.Client/tsconfig.json b/src/Umbraco.Web.UI.Client/tsconfig.json index 289bf2ba2f..9aeafe340d 100644 --- a/src/Umbraco.Web.UI.Client/tsconfig.json +++ b/src/Umbraco.Web.UI.Client/tsconfig.json @@ -126,7 +126,7 @@ "@umbraco-cms/internal/test-utils": ["utils/test-utils.ts"] } }, - "include": ["src/**/*.ts", "apps/**/*.ts", "e2e/**/*.ts", "index.ts", "storybook/stories/**/*.ts"], + "include": ["src/**/*.ts", "apps/**/*.ts", "e2e/**/*.ts", "index.ts", "storybook/stories/**/*.ts", "examples/**/*.ts", ], "references": [ { "path": "./tsconfig.node.json" From 99e78d4ccdcd839b859fb56fd22d084f11073471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 23 Nov 2023 16:15:44 +0100 Subject: [PATCH 07/14] final --- src/Umbraco.Web.UI.Client/.eslintignore | 1 + .../examples/workspace-context-counter/index.ts | 2 +- src/Umbraco.Web.UI.Client/index.ts | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/.eslintignore b/src/Umbraco.Web.UI.Client/.eslintignore index 973eb4106a..0e94763217 100644 --- a/src/Umbraco.Web.UI.Client/.eslintignore +++ b/src/Umbraco.Web.UI.Client/.eslintignore @@ -6,3 +6,4 @@ schemas temp-schema-generator APP_PLUGINS /src/external/router-slot +/examples diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts index 60ced48a7d..b748153c24 100644 --- a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts @@ -1,6 +1,6 @@ import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: ManifestTypes = [ +export const manifests: Array = [ { type: 'workspaceContext', name: 'workspaceContextCounter', diff --git a/src/Umbraco.Web.UI.Client/index.ts b/src/Umbraco.Web.UI.Client/index.ts index 6aeddf2258..6c1dffecf4 100644 --- a/src/Umbraco.Web.UI.Client/index.ts +++ b/src/Umbraco.Web.UI.Client/index.ts @@ -1,6 +1,6 @@ import { UmbAppElement } from './src/apps/app/app.element.js'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { startMockServiceWorker } from './src/mocks/index.js'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; if (import.meta.env.VITE_UMBRACO_USE_MSW === 'on') { startMockServiceWorker(); @@ -22,9 +22,9 @@ appElement.bypassAuth = isMocking; document.body.appendChild(appElement); -// Move this elsewhere: + +// Example injector: if(import.meta.env.VITE_EXAMPLE_PATH) { - console.log(import.meta.env.VITE_EXAMPLE_PATH); import(/* @vite-ignore */ './'+import.meta.env.VITE_EXAMPLE_PATH+'/index.ts').then((js) => { console.log("js", js); if (js) { From 4a2b7e5138ea105aecd77e5e6543ff40bafc7c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 24 Nov 2023 10:17:09 +0100 Subject: [PATCH 08/14] no error on stop --- src/Umbraco.Web.UI.Client/devops/example-runner/index.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/devops/example-runner/index.js b/src/Umbraco.Web.UI.Client/devops/example-runner/index.js index 9f3b5a1778..2dd960c198 100644 --- a/src/Umbraco.Web.UI.Client/devops/example-runner/index.js +++ b/src/Umbraco.Web.UI.Client/devops/example-runner/index.js @@ -36,7 +36,12 @@ async function pickExampleUI(){ process.env['VITE_EXAMPLE_PATH'] = `${exampleDirectory}/${selectedFolder}`; // Start vite server: - execSync('npm run dev', {stdio: 'inherit'}); + try { + execSync('npm run dev', {stdio: 'inherit'}); + } catch (error) { + // Nothing, cause this is most likely just the server begin stopped. + //console.log(error); + } }); }; From 6877736501155b3035f0a5c4db6220ef2e4d6264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 24 Nov 2023 12:51:37 +0100 Subject: [PATCH 09/14] counter example --- .../workspace-context-counter/README.md | 8 +++ .../counter-workspace-context.ts | 30 ++++++++++ .../counter-workspace-view.ts | 60 +++++++++++++++++++ .../incrementor-workspace-action.ts | 17 ++++++ .../workspace-context-counter/index.ts | 48 ++++++++++++++- .../workspace-context-counter.ts | 12 ---- .../src/libs/class-api/class.mixin.ts | 2 +- .../workspace-action/workspace-action-base.ts | 17 +++--- .../workspace/document-workspace.element.ts | 1 + 9 files changed, 169 insertions(+), 26 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/examples/workspace-context-counter/README.md create mode 100644 src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.ts create mode 100644 src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-view.ts create mode 100644 src/Umbraco.Web.UI.Client/examples/workspace-context-counter/incrementor-workspace-action.ts delete mode 100644 src/Umbraco.Web.UI.Client/examples/workspace-context-counter/workspace-context-counter.ts diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/README.md b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/README.md new file mode 100644 index 0000000000..04336ea3dc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/README.md @@ -0,0 +1,8 @@ +# Workspace Context Counter Example + +This example demonstrates the essence of the Workspace Context. + +The Workspace Context is available for everything within the Workspace, giving any extension within the ability to communicate through this. +In this example, the Workspace Context houses a counter, which can be incremented by a Workspace Action and shown in the Workspace View. + +To demonstrate this, the example comes with: A Workspace Context, A Workspace Action and a Workspace View. diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.ts new file mode 100644 index 0000000000..941ba2304d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.ts @@ -0,0 +1,30 @@ +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import { UmbBaseController, type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbNumberState } from '@umbraco-cms/backoffice/observable-api'; + +// The Example Workspace Context Controller: +export class WorkspaceContextCounter extends UmbBaseController { + + // We always keep our states private, and expose the values as observables: + #counter = new UmbNumberState(0); + readonly counter = this.#counter.asObservable(); + + constructor(host: UmbControllerHost) { + super(host); + this.provideContext(EXAMPLE_COUNTER_CONTEXT, this); + console.log("Hey new context") + } + + // Lets expose methods to update the state: + increment() { + this.#counter.next(this.#counter.value + 1); + } + +} + +// Declare a api export, so Extension Registry can initialize this class: +export const api = WorkspaceContextCounter; + + +// Declare a Context Token that other elements can use to request the WorkspaceContextCounter: +export const EXAMPLE_COUNTER_CONTEXT = new UmbContextToken('example.workspaceContext.counter'); diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-view.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-view.ts new file mode 100644 index 0000000000..225a34bea8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-view.ts @@ -0,0 +1,60 @@ +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user'; +import { css, html, customElement, state, LitElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; +import { EXAMPLE_COUNTER_CONTEXT } from './counter-workspace-context'; + +@customElement('example-counter-workspace-view') +export class ExampleCounterWorkspaceView extends UmbElementMixin(LitElement) { + #counterContext?: typeof EXAMPLE_COUNTER_CONTEXT.TYPE; + + @state() + private count = ''; + + constructor() { + super(); + this.consumeContext(EXAMPLE_COUNTER_CONTEXT, (instance) => { + this.#counterContext = instance; + this.#observeCounter(); + }); + } + + #observeCounter(): void { + if (!this.#counterContext) return; + this.observe(this.#counterContext.counter, (count) => { + this.count = count; + }); + } + + render() { + return html` + +

Counter Example

+

+ Current count value: ${this.count} +

+

+ This is a Workspace View, that consumes the Counter Context, and displays the current count. +

+
+ `; + } + + static styles = [ + UmbTextStyles, + css` + :host { + display: block; + padding: var(--uui-size-layout-1); + } + `, + ]; +} + +export default ExampleCounterWorkspaceView; + +declare global { + interface HTMLElementTagNameMap { + 'example-counter-workspace-view': ExampleCounterWorkspaceView; + } +} diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/incrementor-workspace-action.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/incrementor-workspace-action.ts new file mode 100644 index 0000000000..f53371786d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/incrementor-workspace-action.ts @@ -0,0 +1,17 @@ +import { UmbBaseController } from '@umbraco-cms/backoffice/controller-api'; +import type { UmbWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import { EXAMPLE_COUNTER_CONTEXT } from './counter-workspace-context'; + +// The Example Incrementor Workspace Action Controller: +export class ExampleIncrementorWorkspaceAction extends UmbBaseController implements UmbWorkspaceAction { + + // This method is executed + async execute() { + await this.consumeContext(EXAMPLE_COUNTER_CONTEXT, (context) => { + context.increment(); + }).asPromise(); + } +} + +// Declare a api export, so Extension Registry can initialize this class: +export const api = ExampleIncrementorWorkspaceAction; diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts index b748153c24..e22c3603ec 100644 --- a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts @@ -3,8 +3,50 @@ import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ { type: 'workspaceContext', - name: 'workspaceContextCounter', + name: 'Example Counter Workspace Context', alias: 'example.workspaceCounter.counter', - js: () => import('./workspace-context-counter.js'), - } + js: () => import('./counter-workspace-context.js'), + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + }, + ], + }, + { + type: 'workspaceAction', + name: 'Example Count Incerementor Workspace Action', + alias: 'example.workspaceAction.incrementor', + weight: 1000, + api: () => import('./incrementor-workspace-action.js'), + meta: { + label: 'Increment', + look: 'primary', + color: 'danger', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + }, + ], + }, + { + type: 'workspaceEditorView', + name: 'Example Counter Workspace View', + alias: 'example.workspaceView.counter', + element: () => import('./counter-workspace-view.js'), + weight: 900, + meta: { + label: 'Counter', + pathname: 'counter', + icon: 'icon-lab', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + }, + ], + }, ] diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/workspace-context-counter.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/workspace-context-counter.ts deleted file mode 100644 index 39738d6105..0000000000 --- a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/workspace-context-counter.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { UmbBaseController, type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; - -export class WorkspaceContextCounter extends UmbBaseController { - - constructor(host: UmbControllerHost) { - super(host); - - console.log("HELLOOOOO WORLLLDDD") - } -} - -export const api = WorkspaceContextCounter; diff --git a/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts b/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts index ac2d5f957f..bee3e7ea0f 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts @@ -21,7 +21,7 @@ type UmbClassMixinConstructor = new ( ) => UmbClassMixinDeclaration; declare class UmbClassMixinDeclaration implements UmbClassMixinInterface { - _host: UmbControllerHost; + protected _host: UmbControllerHost; observe( source: Observable, callback: (_value: T) => void, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action/workspace-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action/workspace-action-base.ts index 1251b1c334..a8fb5daf1c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action/workspace-action-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action/workspace-action-base.ts @@ -1,23 +1,20 @@ import { UmbWorkspaceContextInterface, UMB_WORKSPACE_CONTEXT } from '../workspace-context/index.js'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; +import { UmbBaseController, type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; -export interface UmbWorkspaceAction extends UmbApi { - host: UmbControllerHost; - workspaceContext?: WorkspaceType; +export interface UmbWorkspaceAction extends UmbApi { execute(): Promise; } -export abstract class UmbWorkspaceActionBase - implements UmbWorkspaceAction +export abstract class UmbWorkspaceActionBase extends UmbBaseController + implements UmbWorkspaceAction { - host: UmbControllerHost; workspaceContext?: WorkspaceContextType; constructor(host: UmbControllerHost) { - this.host = host; + super(host); - new UmbContextConsumerController(this.host, UMB_WORKSPACE_CONTEXT, (instance) => { + // TODO, we most likely should require a context token here in this type, and mane it specifically for workspace actions with context workspace request. + this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => { // TODO: Be aware we are casting here. We should consider a better solution for typing the contexts. (But notice we still want to capture the first workspace...) this.workspaceContext = instance as unknown as WorkspaceContextType; }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.element.ts index 3c6d303203..95b7d77d5e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.element.ts @@ -54,6 +54,7 @@ export class UmbDocumentWorkspaceElement extends UmbLitElement { }, ]; + // TODO: We need to recreate when ID changed? new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'workspaceContext', [this, this.#workspaceContext]); } From 123e4841b3261832716fe7856bcf54be0eddbb4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 24 Nov 2023 12:55:04 +0100 Subject: [PATCH 10/14] allow examples to be part of files of the package --- src/Umbraco.Web.UI.Client/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 704e54b42f..fc2bcdaf3b 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -75,6 +75,7 @@ }, "files": [ "dist-cms", + "examples", "README.md" ], "repository": { From 36da64ad519923c22b2ed1630312729ca9ca9ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 24 Nov 2023 12:58:26 +0100 Subject: [PATCH 11/14] remove log --- .../workspace-context-counter/counter-workspace-context.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.ts index 941ba2304d..3b31fd648a 100644 --- a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.ts @@ -12,7 +12,6 @@ export class WorkspaceContextCounter extends UmbBaseController { constructor(host: UmbControllerHost) { super(host); this.provideContext(EXAMPLE_COUNTER_CONTEXT, this); - console.log("Hey new context") } // Lets expose methods to update the state: From 258f9f95e0ec5486c4d751971a850099a13d2922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 24 Nov 2023 12:58:43 +0100 Subject: [PATCH 12/14] remove devops log --- src/Umbraco.Web.UI.Client/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/index.ts b/src/Umbraco.Web.UI.Client/index.ts index 6c1dffecf4..ecb0f617cf 100644 --- a/src/Umbraco.Web.UI.Client/index.ts +++ b/src/Umbraco.Web.UI.Client/index.ts @@ -26,7 +26,6 @@ document.body.appendChild(appElement); // Example injector: if(import.meta.env.VITE_EXAMPLE_PATH) { import(/* @vite-ignore */ './'+import.meta.env.VITE_EXAMPLE_PATH+'/index.ts').then((js) => { - console.log("js", js); if (js) { Object.keys(js).forEach((key) => { const value = js[key]; From aeb143366007b2d951099a1e35d4d04e31096ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 24 Nov 2023 21:04:04 +0100 Subject: [PATCH 13/14] needed an export for umbraco CLI for create-package to pick up the examples --- src/Umbraco.Web.UI.Client/examples/index.js | 0 src/Umbraco.Web.UI.Client/package.json | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/examples/index.js diff --git a/src/Umbraco.Web.UI.Client/examples/index.js b/src/Umbraco.Web.UI.Client/examples/index.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index fc2bcdaf3b..5a07ebb6ed 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -71,7 +71,9 @@ "./user": "./dist-cms/packages/user/user/index.js", "./user-permission": "./dist-cms/packages/user/user-permission/index.js", "./code-editor": "./dist-cms/packages/templating/code-editor/index.js", - "./external/*": "./dist-cms/external/*/index.js" + "./external/*": "./dist-cms/external/*/index.js", + "./examples/*": "./examples/*/index.js", + "./examples": "./examples/index.js" }, "files": [ "dist-cms", From 4bb2f9a7d0afa087dd5b6e1293eee5449f172977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 27 Nov 2023 09:07:43 +0100 Subject: [PATCH 14/14] revert protected prop --- .../src/libs/class-api/class.mixin.ts | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts b/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts index bee3e7ea0f..ea13fbc663 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts @@ -17,24 +17,27 @@ import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; type UmbClassMixinConstructor = new ( host: UmbControllerHost, - controllerAlias: UmbControllerAlias + controllerAlias: UmbControllerAlias, ) => UmbClassMixinDeclaration; declare class UmbClassMixinDeclaration implements UmbClassMixinInterface { - protected _host: UmbControllerHost; + _host: UmbControllerHost; observe( source: Observable, callback: (_value: T) => void, - controllerAlias?: UmbControllerAlias + controllerAlias?: UmbControllerAlias, ): UmbObserverController; provideContext< BaseType = unknown, ResultType extends BaseType = BaseType, - InstanceType extends ResultType = ResultType - >(alias: string | UmbContextToken, instance: InstanceType): UmbContextProviderController; + InstanceType extends ResultType = ResultType, + >( + alias: string | UmbContextToken, + instance: InstanceType, + ): UmbContextProviderController; consumeContext( alias: string | UmbContextToken, - callback: UmbContextCallback + callback: UmbContextCallback, ): UmbContextConsumerController; hasController(controller: UmbController): boolean; getControllers(filterMethod: (ctrl: UmbController) => boolean): UmbController[]; @@ -86,15 +89,13 @@ export const UmbClassMixin = (superClass: T) => { * @return {UmbContextProviderController} Reference to a Context Provider Controller instance * @memberof UmbElementMixin */ - provideContext - < + provideContext< BaseType = unknown, ResultType extends BaseType = BaseType, - InstanceType extends ResultType = ResultType - > - ( + InstanceType extends ResultType = ResultType, + >( contextAlias: string | UmbContextToken, - instance: InstanceType + instance: InstanceType, ): UmbContextProviderController { return new UmbContextProviderController(this, contextAlias, instance); } @@ -108,8 +109,8 @@ export const UmbClassMixin = (superClass: T) => { */ consumeContext( contextAlias: string | UmbContextToken, - callback: UmbContextCallback - ): UmbContextConsumerController { + callback: UmbContextCallback, + ): UmbContextConsumerController { return new UmbContextConsumerController(this, contextAlias, callback); } }