diff --git a/src/Umbraco.Web.UI.Client/.storybook/main.ts b/src/Umbraco.Web.UI.Client/.storybook/main.ts index 22cadbe5ec..47e2a92d14 100644 --- a/src/Umbraco.Web.UI.Client/.storybook/main.ts +++ b/src/Umbraco.Web.UI.Client/.storybook/main.ts @@ -38,8 +38,8 @@ const config: StorybookConfig = { }, refs: { uui: { - title: 'Umbraco UI Library (1.6.0)', - url: 'https://04709c3--62189360eeb21b003ab2f4ad.chromatic.com/', + title: 'Umbraco UI Library', + url: 'https://62189360eeb21b003ab2f4ad-vfnpsanjps.chromatic.com/', }, }, }; diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 91b9a2eaea..ee3c1ade14 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -12,7 +12,7 @@ "@types/diff": "^5.0.9", "@types/dompurify": "^3.0.5", "@types/uuid": "^9.0.8", - "@umbraco-ui/uui": "1.8.0-rc.1", + "@umbraco-ui/uui": "1.8.0-rc.2", "@umbraco-ui/uui-css": "1.8.0-rc.0", "base64-js": "^1.5.1", "diff": "^5.2.0", @@ -6879,9 +6879,9 @@ } }, "node_modules/@umbraco-ui/uui": { - "version": "1.8.0-rc.1", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui/-/uui-1.8.0-rc.1.tgz", - "integrity": "sha512-YSM3HoUAAUiDNfbbI13X586BPucPvqLV8UGSj7hGQN+DgqiydQCxup8bYWIQwtoQzXtd7wgn8N8e7/5sv01PDw==", + "version": "1.8.0-rc.2", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui/-/uui-1.8.0-rc.2.tgz", + "integrity": "sha512-KYySEmXsl0Ga1lAqAiClsjCMquSAZpo/9HZUcnrkw1dgZN8XaHmt/0O+b1QOty7WHZihurcvPQh169+BfMwUFw==", "dependencies": { "@umbraco-ui/uui-action-bar": "1.8.0-rc.0", "@umbraco-ui/uui-avatar": "1.8.0-rc.0", @@ -6891,7 +6891,7 @@ "@umbraco-ui/uui-boolean-input": "1.8.0-rc.0", "@umbraco-ui/uui-box": "1.8.0-rc.1", "@umbraco-ui/uui-breadcrumbs": "1.8.0-rc.0", - "@umbraco-ui/uui-button": "1.8.0-rc.0", + "@umbraco-ui/uui-button": "1.8.0-rc.2", "@umbraco-ui/uui-button-group": "1.8.0-rc.0", "@umbraco-ui/uui-button-inline-create": "1.8.0-rc.0", "@umbraco-ui/uui-card": "1.8.0-rc.0", @@ -6906,7 +6906,7 @@ "@umbraco-ui/uui-color-slider": "1.8.0-rc.0", "@umbraco-ui/uui-color-swatch": "1.8.0-rc.0", "@umbraco-ui/uui-color-swatches": "1.8.0-rc.0", - "@umbraco-ui/uui-combobox": "1.8.0-rc.0", + "@umbraco-ui/uui-combobox": "1.8.0-rc.2", "@umbraco-ui/uui-combobox-list": "1.8.0-rc.0", "@umbraco-ui/uui-css": "1.8.0-rc.0", "@umbraco-ui/uui-dialog": "1.8.0-rc.0", @@ -6920,8 +6920,8 @@ "@umbraco-ui/uui-icon-registry": "1.8.0-rc.0", "@umbraco-ui/uui-icon-registry-essential": "1.8.0-rc.0", "@umbraco-ui/uui-input": "1.8.0-rc.0", - "@umbraco-ui/uui-input-file": "1.8.0-rc.0", - "@umbraco-ui/uui-input-lock": "1.8.0-rc.0", + "@umbraco-ui/uui-input-file": "1.8.0-rc.2", + "@umbraco-ui/uui-input-lock": "1.8.0-rc.2", "@umbraco-ui/uui-input-password": "1.8.0-rc.0", "@umbraco-ui/uui-keyboard-shortcut": "1.8.0-rc.0", "@umbraco-ui/uui-label": "1.8.0-rc.0", @@ -6929,8 +6929,8 @@ "@umbraco-ui/uui-loader-bar": "1.8.0-rc.0", "@umbraco-ui/uui-loader-circle": "1.8.0-rc.0", "@umbraco-ui/uui-menu-item": "1.8.0-rc.1", - "@umbraco-ui/uui-modal": "1.8.0-rc.0", - "@umbraco-ui/uui-pagination": "1.8.0-rc.0", + "@umbraco-ui/uui-modal": "1.8.0-rc.2", + "@umbraco-ui/uui-pagination": "1.8.0-rc.2", "@umbraco-ui/uui-popover": "1.8.0-rc.0", "@umbraco-ui/uui-popover-container": "1.8.0-rc.0", "@umbraco-ui/uui-progress-bar": "1.8.0-rc.0", @@ -6957,11 +6957,11 @@ "@umbraco-ui/uui-symbol-more": "1.8.0-rc.0", "@umbraco-ui/uui-symbol-sort": "1.8.0-rc.0", "@umbraco-ui/uui-table": "1.8.0-rc.0", - "@umbraco-ui/uui-tabs": "1.8.0-rc.0", + "@umbraco-ui/uui-tabs": "1.8.0-rc.2", "@umbraco-ui/uui-tag": "1.8.0-rc.0", "@umbraco-ui/uui-textarea": "1.8.0-rc.0", - "@umbraco-ui/uui-toast-notification": "1.8.0-rc.0", - "@umbraco-ui/uui-toast-notification-container": "1.8.0-rc.0", + "@umbraco-ui/uui-toast-notification": "1.8.0-rc.2", + "@umbraco-ui/uui-toast-notification-container": "1.8.0-rc.2", "@umbraco-ui/uui-toast-notification-layout": "1.8.0-rc.0", "@umbraco-ui/uui-toggle": "1.8.0-rc.0", "@umbraco-ui/uui-visually-hidden": "1.8.0-rc.0" @@ -7035,9 +7035,9 @@ } }, "node_modules/@umbraco-ui/uui-button": { - "version": "1.8.0-rc.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button/-/uui-button-1.8.0-rc.0.tgz", - "integrity": "sha512-V6Tl+uqBvy4ciKeoohylK8t4rPBl4aJNqVwxG13YCDOu95k+q+0neglAznkK+s5thhKThBHuW5XesRIEOW2Q3g==", + "version": "1.8.0-rc.2", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button/-/uui-button-1.8.0-rc.2.tgz", + "integrity": "sha512-5JAS247c0NdjsOdzdXOqjOEsfb1HxvPWvBc2KUMOi2hjh/TQbp765BXB0lvc5RqePwuJbwogeAhbesLuRvCCwQ==", "dependencies": { "@umbraco-ui/uui-base": "1.8.0-rc.0", "@umbraco-ui/uui-icon-registry-essential": "1.8.0-rc.0" @@ -7172,12 +7172,12 @@ } }, "node_modules/@umbraco-ui/uui-combobox": { - "version": "1.8.0-rc.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-combobox/-/uui-combobox-1.8.0-rc.0.tgz", - "integrity": "sha512-+7N0+LSCZ4SO1Y3XvG7zJU68dxKiqhkouuAWMibzTo7S5WeDQx6R3zATgM5iM+lCIVcnWzt8b34sHOug1rpatg==", + "version": "1.8.0-rc.2", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-combobox/-/uui-combobox-1.8.0-rc.2.tgz", + "integrity": "sha512-71AbVcHweB36g3jUCur/PKIKbpSHMvJq2iQou84NgVtO+hBM0PxH2JOsLRCMFG76D8fjIUd03tNp6szBHH1RMQ==", "dependencies": { "@umbraco-ui/uui-base": "1.8.0-rc.0", - "@umbraco-ui/uui-button": "1.8.0-rc.0", + "@umbraco-ui/uui-button": "1.8.0-rc.2", "@umbraco-ui/uui-combobox-list": "1.8.0-rc.0", "@umbraco-ui/uui-icon": "1.8.0-rc.0", "@umbraco-ui/uui-popover-container": "1.8.0-rc.0", @@ -7298,25 +7298,25 @@ } }, "node_modules/@umbraco-ui/uui-input-file": { - "version": "1.8.0-rc.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-file/-/uui-input-file-1.8.0-rc.0.tgz", - "integrity": "sha512-GHFlUIprhObBt6c+o5AWcScwVaFK2dN0GU4wfKXFcYvG9SZxuYJqC87z0ovX8qjXE8VgTTIlaF2T8GgNBmXjHg==", + "version": "1.8.0-rc.2", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-file/-/uui-input-file-1.8.0-rc.2.tgz", + "integrity": "sha512-WO4boW7+K4cFF+wo+qunBtiWyfn2XOdd3tl+8M/+lBwmCDIxuLbhrDosZEiUKvhyG4BjZxK1+C5JFqROZSQrkg==", "dependencies": { "@umbraco-ui/uui-action-bar": "1.8.0-rc.0", "@umbraco-ui/uui-base": "1.8.0-rc.0", - "@umbraco-ui/uui-button": "1.8.0-rc.0", + "@umbraco-ui/uui-button": "1.8.0-rc.2", "@umbraco-ui/uui-file-dropzone": "1.8.0-rc.0", "@umbraco-ui/uui-icon": "1.8.0-rc.0", "@umbraco-ui/uui-icon-registry-essential": "1.8.0-rc.0" } }, "node_modules/@umbraco-ui/uui-input-lock": { - "version": "1.8.0-rc.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-lock/-/uui-input-lock-1.8.0-rc.0.tgz", - "integrity": "sha512-GMKi/DFZPLIUG4IfAb9HFsuDwTmhnHgq/qHg+YbfZ2fPMjvuNQhFaWYbuYMIksLu13hQsiZdMjnHpBnM8leVpw==", + "version": "1.8.0-rc.2", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-lock/-/uui-input-lock-1.8.0-rc.2.tgz", + "integrity": "sha512-k8Dv83zUuEQvQBOFE+oD6tBNXB+UBd6pnQmoqLvohDobWVmjWo8o0vL2AszroLR9XFPGbPE+UpCNODM7OAEw9A==", "dependencies": { "@umbraco-ui/uui-base": "1.8.0-rc.0", - "@umbraco-ui/uui-button": "1.8.0-rc.0", + "@umbraco-ui/uui-button": "1.8.0-rc.2", "@umbraco-ui/uui-icon": "1.8.0-rc.0", "@umbraco-ui/uui-input": "1.8.0-rc.0" } @@ -7382,20 +7382,20 @@ } }, "node_modules/@umbraco-ui/uui-modal": { - "version": "1.8.0-rc.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-modal/-/uui-modal-1.8.0-rc.0.tgz", - "integrity": "sha512-hJBFF0siAeXYh6tYkAvA8zQlDsOxKhdrPTEMwqU46zHgnDOSXQ6xvt6RqY9nLmXF2x4VT4L0HUrrWmK5YAN8Ug==", + "version": "1.8.0-rc.2", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-modal/-/uui-modal-1.8.0-rc.2.tgz", + "integrity": "sha512-ISi2kRV729SHFXgpXnLlIjEJuOSBxo64gg8KMkXdFpUMXgfq6qlIWFrlY9D5L6m3c7mB3QfhDOejp0rwOeHO6A==", "dependencies": { "@umbraco-ui/uui-base": "1.8.0-rc.0" } }, "node_modules/@umbraco-ui/uui-pagination": { - "version": "1.8.0-rc.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-pagination/-/uui-pagination-1.8.0-rc.0.tgz", - "integrity": "sha512-j28PjKCJ08b9jtPz91d5gZptDUZs6a4t3WLp8GcVV+obGB7v2+Cr9jBlpRu14iwXVFYRl/TN2MdGqVuFKBC55w==", + "version": "1.8.0-rc.2", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-pagination/-/uui-pagination-1.8.0-rc.2.tgz", + "integrity": "sha512-T4vw2M5EJliqwy8YI03eA7pg+gcym9fyeO95eGQvriUV6/OB60CrzjEQ2tXREkVQq1oW3RIBEUEikUgRktMpwA==", "dependencies": { "@umbraco-ui/uui-base": "1.8.0-rc.0", - "@umbraco-ui/uui-button": "1.8.0-rc.0", + "@umbraco-ui/uui-button": "1.8.0-rc.2", "@umbraco-ui/uui-button-group": "1.8.0-rc.0" } }, @@ -7616,12 +7616,12 @@ } }, "node_modules/@umbraco-ui/uui-tabs": { - "version": "1.8.0-rc.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-tabs/-/uui-tabs-1.8.0-rc.0.tgz", - "integrity": "sha512-81bvMrb2KqrMpruV83wuWGcI/5Zx+2FeD7ibpQ0HmdGg2EKiMX+XZCsEPyc+LD4/JImkVPs90PQmhBj8IzLBrQ==", + "version": "1.8.0-rc.2", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-tabs/-/uui-tabs-1.8.0-rc.2.tgz", + "integrity": "sha512-MLtDabiXsOEqOxfgEuqU3ji1XTgY9ABbhqOHC23cFaaGBwlqAbUyi9hAMJhfso406vkQa/9t9A7yK8qpMqKdrA==", "dependencies": { "@umbraco-ui/uui-base": "1.8.0-rc.0", - "@umbraco-ui/uui-button": "1.8.0-rc.0", + "@umbraco-ui/uui-button": "1.8.0-rc.2", "@umbraco-ui/uui-popover-container": "1.8.0-rc.0", "@umbraco-ui/uui-symbol-more": "1.8.0-rc.0" } @@ -7643,24 +7643,24 @@ } }, "node_modules/@umbraco-ui/uui-toast-notification": { - "version": "1.8.0-rc.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification/-/uui-toast-notification-1.8.0-rc.0.tgz", - "integrity": "sha512-inBfJnrPtWgvUd4KBF168xB1EOI5B2HEK1GEaYYuKuFYZdeiJAZPP0GCgkiMC9K0YShIxh9H3q31iwvtWA1KhA==", + "version": "1.8.0-rc.2", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification/-/uui-toast-notification-1.8.0-rc.2.tgz", + "integrity": "sha512-ICvxWZVuDO1X/f1udYgtY1prHYbj26g3ZecKq2V2FVs9Ej5kYNIWU1nVGj6tWkdyKGnVPjoLfYmq/W8i9BJb9g==", "dependencies": { "@umbraco-ui/uui-base": "1.8.0-rc.0", - "@umbraco-ui/uui-button": "1.8.0-rc.0", + "@umbraco-ui/uui-button": "1.8.0-rc.2", "@umbraco-ui/uui-css": "1.8.0-rc.0", "@umbraco-ui/uui-icon": "1.8.0-rc.0", "@umbraco-ui/uui-icon-registry-essential": "1.8.0-rc.0" } }, "node_modules/@umbraco-ui/uui-toast-notification-container": { - "version": "1.8.0-rc.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification-container/-/uui-toast-notification-container-1.8.0-rc.0.tgz", - "integrity": "sha512-PA1IKPMJOSxYiOnSVyd2AhbovhSN/aU7d2Z/4/HFfvmnhedjsfRYzsgFDfoLUCenV7hN1dIxFNEEW6FxEpxEqQ==", + "version": "1.8.0-rc.2", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification-container/-/uui-toast-notification-container-1.8.0-rc.2.tgz", + "integrity": "sha512-iQ1xDQBgKrvTtCAUsT/3DJayCNVPWb+T9B5V+MyfuHnV9qOnmPtchs7l9r8cFwabOO5ZpxMke/tltsgMawwajQ==", "dependencies": { "@umbraco-ui/uui-base": "1.8.0-rc.0", - "@umbraco-ui/uui-toast-notification": "1.8.0-rc.0" + "@umbraco-ui/uui-toast-notification": "1.8.0-rc.2" } }, "node_modules/@umbraco-ui/uui-toast-notification-layout": { diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index f7f5c0103e..37a57026fc 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -169,7 +169,7 @@ "@types/diff": "^5.0.9", "@types/dompurify": "^3.0.5", "@types/uuid": "^9.0.8", - "@umbraco-ui/uui": "1.8.0-rc.1", + "@umbraco-ui/uui": "1.8.0-rc.2", "@umbraco-ui/uui-css": "1.8.0-rc.0", "base64-js": "^1.5.1", "diff": "^5.2.0", diff --git a/src/Umbraco.Web.UI.Client/src/external/lit/index.ts b/src/Umbraco.Web.UI.Client/src/external/lit/index.ts index 270a60fa6a..e7c9bc62c3 100644 --- a/src/Umbraco.Web.UI.Client/src/external/lit/index.ts +++ b/src/Umbraco.Web.UI.Client/src/external/lit/index.ts @@ -1,5 +1,6 @@ export * from 'lit'; export * from 'lit/decorators.js'; +export { directive, AsyncDirective } from 'lit/async-directive.js'; export * from 'lit/directives/class-map.js'; export * from 'lit/directives/if-defined.js'; export * from 'lit/directives/map.js'; diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.test.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.test.ts index 68e00ddbd7..2a801af75c 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.test.ts @@ -368,3 +368,88 @@ describe('UmbExtensionRegistry with kinds', () => { .unsubscribe(); }); }); + +describe('UmbExtensionRegistry with exclusions', () => { + let extensionRegistry: UmbExtensionRegistry; + let manifests: Array< + ManifestElementWithElementName | TestManifestWithMeta | ManifestKind + >; + + beforeEach(() => { + extensionRegistry = new UmbExtensionRegistry(); + manifests = [ + { + type: 'kind', + alias: 'Umb.Test.Kind', + matchType: 'section', + matchKind: 'test-kind', + manifest: { + type: 'section', + elementName: 'my-kind-element', + meta: { + label: 'my-kind-meta-label', + }, + }, + }, + { + type: 'section', + kind: 'test-kind' as unknown as undefined, // We do not know about this one, so it makes good sense that its not a valid option. + name: 'test-section-1', + alias: 'Umb.Test.Section.1', + weight: 1, + meta: { + pathname: 'test-section-1', + }, + }, + { + type: 'section', + name: 'test-section-2', + alias: 'Umb.Test.Section.2', + weight: 200, + meta: { + label: 'Test Section 2', + pathname: 'test-section-2', + }, + }, + ]; + + manifests.forEach((manifest) => extensionRegistry.register(manifest)); + }); + + it('should have the extensions registered', () => { + expect(extensionRegistry.isRegistered('Umb.Test.Kind')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + }); + + it('must not say that Umb.Test.Section.1d is registered, when its added to the exclusion list', () => { + extensionRegistry.exclude('Umb.Test.Section.1'); + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.false; + // But check that the other ones are still registered: + expect(extensionRegistry.isRegistered('Umb.Test.Kind')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + }); + + it('does not affect kinds when a kind-alias is put in the exclusion list', () => { + extensionRegistry.exclude('Umb.Test.Kind'); + // This had no effect, so all of them are still available. + expect(extensionRegistry.isRegistered('Umb.Test.Kind')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + }); + + it('prevents late comers from begin registered', () => { + extensionRegistry.exclude('Umb.Test.Section.Late'); + extensionRegistry.register({ + type: 'section', + name: 'test-section-late', + alias: 'Umb.Test.Section.Late', + weight: 200, + meta: { + label: 'Test Section Late', + pathname: 'test-section-Late', + }, + }); + expect(extensionRegistry.isRegistered('Umb.Test.Section.Late')).to.be.false; + }); +}); diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.ts index 245ddf6667..99449dbf88 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.ts @@ -80,6 +80,7 @@ export class UmbExtensionRegistry< private _kinds = new UmbBasicState>>([]); public readonly kinds = this._kinds.asObservable(); + #exclusions: Array = []; defineKind(kind: ManifestKind): void { const extensionsValues = this._extensions.getValue(); @@ -105,6 +106,15 @@ export class UmbExtensionRegistry< this._kinds.setValue(nextData); } + exclude(alias: string): void { + this.#exclusions.push(alias); + this._extensions.setValue(this._extensions.getValue().filter(this.#acceptExtension)); + } + + #acceptExtension = (ext: ManifestTypes): boolean => { + return !this.#exclusions.includes(ext.alias); + }; + register(manifest: ManifestTypes | ManifestKind): void { const isValid = this.#checkExtension(manifest); if (!isValid) { @@ -163,6 +173,10 @@ export class UmbExtensionRegistry< return false; } + if (!this.#acceptExtension(manifest as ManifestTypes)) { + return false; + } + const extensionsValues = this._extensions.getValue(); const extension = extensionsValues.find((extension) => extension.alias === (manifest as ManifestTypes).alias); diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/utils/entity/entity-tree.manager.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/utils/entity/entity-tree.manager.ts index a35f9b763a..8195af02df 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/utils/entity/entity-tree.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/utils/entity/entity-tree.manager.ts @@ -49,7 +49,7 @@ export class UmbMockEntityTreeManager { return { ...item, - parentId: destinationId, + parent: destinationId ? { id: destinationId } : null, }; }); diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/data-type/index.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/data-type/index.ts index c74b54913d..790a686bad 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/data-type/index.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/data-type/index.ts @@ -9,7 +9,7 @@ export const handlers = [ ...treeHandlers, ...itemHandlers, ...folderHandlers, + ...detailHandlers, ...moveHandlers, ...copyHandlers, - ...detailHandlers, ]; diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/data-type/move.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/data-type/move.handlers.ts index bca11683f4..9dc2b49cc1 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/data-type/move.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/data-type/move.handlers.ts @@ -5,7 +5,7 @@ import type { MoveDataTypeRequestModel } from '@umbraco-cms/backoffice/external/ import { umbracoPath } from '@umbraco-cms/backoffice/utils'; export const moveHandlers = [ - rest.post(umbracoPath(`${UMB_SLUG}/:id/move`), async (req, res, ctx) => { + rest.put(umbracoPath(`${UMB_SLUG}/:id/move`), async (req, res, ctx) => { const id = req.params.id as string; if (!id) return res(ctx.status(400)); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.element.ts index 2e3b3fd37f..f4e8f8679a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.element.ts @@ -102,6 +102,7 @@ export class UmbExtensionSlotElement extends UmbLitElement { disconnectedCallback(): void { this.#attached = false; this.#extensionsController?.destroy(); + this.#extensionsController = undefined; super.disconnectedCallback(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.element.ts index d1c35b7e9c..4a3ef2eccb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.element.ts @@ -149,6 +149,7 @@ export class UmbExtensionWithApiSlotElement extends UmbLitElement { disconnectedCallback(): void { this.#attached = false; this.#extensionsController?.destroy(); + this.#extensionsController = undefined; super.disconnectedCallback(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/field-dropdown-list/field-dropdown-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/field-dropdown-list/field-dropdown-list.element.ts index 837006de80..01aa08a420 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/field-dropdown-list/field-dropdown-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/field-dropdown-list/field-dropdown-list.element.ts @@ -14,12 +14,8 @@ import { } from '@umbraco-cms/backoffice/external/lit'; import type { UUIComboboxEvent, UUIComboboxElement } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbMediaTypeDetailRepository } from '@umbraco-cms/backoffice/media-type'; -import { - UMB_MEDIA_TYPE_PICKER_MODAL, - UMB_MODAL_MANAGER_CONTEXT, - type UmbModalManagerContext, -} from '@umbraco-cms/backoffice/modal'; +import { UmbMediaTypeDetailRepository, UMB_MEDIA_TYPE_PICKER_MODAL } from '@umbraco-cms/backoffice/media-type'; +import { UMB_MODAL_MANAGER_CONTEXT, type UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; interface FieldPickerValue { alias: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-content-type-property/input-content-type-property.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-content-type-property/input-content-type-property.element.ts index a4304c9162..34f82f10b4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-content-type-property/input-content-type-property.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-content-type-property/input-content-type-property.element.ts @@ -2,10 +2,10 @@ import { html, customElement, property, css } from '@umbraco-cms/backoffice/exte import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbChangeEvent, UmbSelectionChangeEvent } from '@umbraco-cms/backoffice/event'; -import { UmbMediaTypeDetailRepository } from '@umbraco-cms/backoffice/media-type'; +import { UmbMediaTypeDetailRepository, UMB_MEDIA_TYPE_PICKER_MODAL } from '@umbraco-cms/backoffice/media-type'; import { UMB_DOCUMENT_TYPE_PICKER_MODAL, UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; import { UMB_MEMBER_TYPE_PICKER_MODAL, UmbMemberTypeDetailRepository } from '@umbraco-cms/backoffice/member-type'; -import { UMB_ITEM_PICKER_MODAL, UMB_MEDIA_TYPE_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_ITEM_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; import type { UmbDetailRepositoryBase } from '@umbraco-cms/backoffice/repository'; import type { UmbItemPickerModel, UmbModalToken, UmbPickerModalValue } from '@umbraco-cms/backoffice/modal'; @@ -45,13 +45,43 @@ export class UmbInputContentTypePropertyElement extends UUIFormControlMixin(UmbL pickableFilter: (docType) => !docType.isElement, repository: () => new UmbDocumentTypeDetailRepository(this), systemProperties: [ - { label: this.localize.term('content_documentType'), description: 'contentTypeAlias', value: 'contentTypeAlias', icon: 'icon-settings' }, - { label: this.localize.term('content_createDate'), description: 'createDate', value: 'createDate', icon: 'icon-settings' }, + { + label: this.localize.term('content_documentType'), + description: 'contentTypeAlias', + value: 'contentTypeAlias', + icon: 'icon-settings', + }, + { + label: this.localize.term('content_createDate'), + description: 'createDate', + value: 'createDate', + icon: 'icon-settings', + }, { label: this.localize.term('content_createBy'), description: 'owner', value: 'owner', icon: 'icon-settings' }, - { label: this.localize.term('content_isPublished'), description: 'published', value: 'published', icon: 'icon-settings' }, - { label: this.localize.term('general_sort'), description: 'sortOrder', value: 'sortOrder', icon: 'icon-settings' }, - { label: this.localize.term('content_updateDate'), description: 'updateDate', value: 'updateDate', icon: 'icon-settings' }, - { label: this.localize.term('content_updatedBy'), description: 'updater', value: 'updater', icon: 'icon-settings' }, + { + label: this.localize.term('content_isPublished'), + description: 'published', + value: 'published', + icon: 'icon-settings', + }, + { + label: this.localize.term('general_sort'), + description: 'sortOrder', + value: 'sortOrder', + icon: 'icon-settings', + }, + { + label: this.localize.term('content_updateDate'), + description: 'updateDate', + value: 'updateDate', + icon: 'icon-settings', + }, + { + label: this.localize.term('content_updatedBy'), + description: 'updater', + value: 'updater', + icon: 'icon-settings', + }, ], }, elementTypes: { @@ -82,12 +112,37 @@ export class UmbInputContentTypePropertyElement extends UUIFormControlMixin(UmbL pickerModal: () => UMB_MEDIA_TYPE_PICKER_MODAL, repository: () => new UmbMediaTypeDetailRepository(this), systemProperties: [ - { label: this.localize.term('content_documentType'), description: 'contentTypeAlias', value: 'contentTypeAlias', icon: 'icon-settings' }, - { label: this.localize.term('content_createDate'), description: 'createDate', value: 'createDate', icon: 'icon-settings' }, + { + label: this.localize.term('content_documentType'), + description: 'contentTypeAlias', + value: 'contentTypeAlias', + icon: 'icon-settings', + }, + { + label: this.localize.term('content_createDate'), + description: 'createDate', + value: 'createDate', + icon: 'icon-settings', + }, { label: this.localize.term('content_createBy'), description: 'owner', value: 'owner', icon: 'icon-settings' }, - { label: this.localize.term('general_sort'), description: 'sortOrder', value: 'sortOrder', icon: 'icon-settings' }, - { label: this.localize.term('content_updateDate'), description: 'updateDate', value: 'updateDate', icon: 'icon-settings' }, - { label: this.localize.term('content_updatedBy'), description: 'updater', value: 'updater', icon: 'icon-settings' }, + { + label: this.localize.term('general_sort'), + description: 'sortOrder', + value: 'sortOrder', + icon: 'icon-settings', + }, + { + label: this.localize.term('content_updateDate'), + description: 'updateDate', + value: 'updateDate', + icon: 'icon-settings', + }, + { + label: this.localize.term('content_updatedBy'), + description: 'updater', + value: 'updater', + icon: 'icon-settings', + }, ], }, memberTypes: { @@ -100,11 +155,31 @@ export class UmbInputContentTypePropertyElement extends UUIFormControlMixin(UmbL pickerModal: () => UMB_MEMBER_TYPE_PICKER_MODAL, repository: () => new UmbMemberTypeDetailRepository(this), systemProperties: [ - { label: this.localize.term('content_documentType'), description: 'contentTypeAlias', value: 'contentTypeAlias', icon: 'icon-settings' }, - { label: this.localize.term('content_createDate'), description: 'createDate', value: 'createDate', icon: 'icon-settings' }, + { + label: this.localize.term('content_documentType'), + description: 'contentTypeAlias', + value: 'contentTypeAlias', + icon: 'icon-settings', + }, + { + label: this.localize.term('content_createDate'), + description: 'createDate', + value: 'createDate', + icon: 'icon-settings', + }, { label: this.localize.term('general_email'), description: 'email', value: 'email', icon: 'icon-settings' }, - { label: this.localize.term('content_updateDate'), description: 'updateDate', value: 'updateDate', icon: 'icon-settings' }, - { label: this.localize.term('general_username'), description: 'username', value: 'username', icon: 'icon-settings' }, + { + label: this.localize.term('content_updateDate'), + description: 'updateDate', + value: 'updateDate', + icon: 'icon-settings', + }, + { + label: this.localize.term('general_username'), + description: 'username', + value: 'username', + icon: 'icon-settings', + }, ], }, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-date/input-date.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-date/input-date.element.ts index d3f34925ef..0da0ec53c4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-date/input-date.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-date/input-date.element.ts @@ -1,8 +1,8 @@ -import { UmbConfigRepository } from '../../repository/config/config.repository.js'; -import { html, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; -import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; +import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; +import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-input-date') export class UmbInputDateElement extends UUIFormControlMixin(UmbLitElement, '') { @@ -22,12 +22,6 @@ export class UmbInputDateElement extends UUIFormControlMixin(UmbLitElement, '') @property({ type: String }) displayValue?: string; - @property({ type: Boolean }) - offsetTime = false; - - @state() - private _offsetValue = 0; - @property({ type: String }) min?: string; @@ -37,42 +31,25 @@ export class UmbInputDateElement extends UUIFormControlMixin(UmbLitElement, '') @property({ type: Number }) step?: number; - private _configRepository = new UmbConfigRepository(this); - - constructor() { - super(); - } - connectedCallback(): void { super.connectedCallback(); - this.offsetTime ? this.#getOffset() : (this.displayValue = this.#UTCToLocal(this.value as string)); - } - - async #getOffset() { - const data = await this._configRepository.getServertimeOffset(); - if (!data) return; - this._offsetValue = data.offset; if (!this.value) return; - this.displayValue = this.#valueToServerOffset(this.value as string, true); + this.displayValue = this.#UTCToLocal(this.value as string); } - #localToUTC(d: string) { + #localToUTC(date: string) { if (this.type === 'time') { - return new Date(`${new Date().toJSON().slice(0, 10)} ${d}`).toISOString().slice(11, 16); + return new Date(`${new Date().toJSON().slice(0, 10)} ${date}`).toISOString().slice(11, 16); } else { - const date = new Date(d); - const isoDate = date.toISOString(); - return `${isoDate.substring(0, 10)}T${isoDate.substring(11, 19)}Z`; + return new Date(date).toJSON(); } } #UTCToLocal(d: string) { if (this.type === 'time') { const local = new Date(`${new Date().toJSON().slice(0, 10)} ${d}Z`) - .toLocaleTimeString(undefined, { - hourCycle: 'h23', - }) + .toLocaleTimeString(undefined, { hourCycle: 'h23' }) .slice(0, 5); return local; } else { @@ -89,58 +66,25 @@ export class UmbInputDateElement extends UUIFormControlMixin(UmbLitElement, '') } } - #dateToString(date: Date) { - return `${date.getFullYear()}-${('0' + (date.getMonth() + 1)).slice(-2)}-${('0' + date.getDate()).slice(-2)}T${( - '0' + date.getHours() - ).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}:${('0' + date.getSeconds()).slice(-2)}`; - } + #onChange(event: UUIInputEvent) { + const newValue = event.target.value as string; + if (!newValue) return; - #valueToServerOffset(d: string, utc = false) { - if (this.type === 'time') { - const newDate = new Date(`${new Date().toJSON().slice(0, 10)} ${d}`); - const dateOffset = new Date( - newDate.setTime(newDate.getTime() + (utc ? this._offsetValue * -1 : this._offsetValue) * 60 * 1000), - ); - const time = dateOffset - .toLocaleTimeString(undefined, { - hourCycle: 'h23', - }) - .slice(0, 5); - return time; - } else { - const newDate = new Date(d.replace('Z', '')); - const dateOffset = new Date( - newDate.setTime(newDate.getTime() + (utc ? this._offsetValue * -1 : this._offsetValue) * 60 * 1000), - ); - return this.type === 'datetime-local' - ? this.#dateToString(dateOffset) - : this.#dateToString(dateOffset).slice(0, 10); - } - } - - #onChange(e: UUIInputEvent) { - e.stopPropagation(); - const picked = e.target.value as string; - if (!picked) { - this.value = ''; - this.displayValue = ''; - return; - } - this.value = this.offsetTime ? this.#valueToServerOffset(picked) : this.#localToUTC(picked); - this.displayValue = picked; - this.dispatchEvent(new CustomEvent('change')); + this.value = this.#localToUTC(newValue); + this.displayValue = newValue; + this.dispatchEvent(new UmbChangeEvent()); } render() { return html` + .min=${this.min} + .max=${this.max} + .step=${this.step} + .type=${this.type} + .value="${this.displayValue?.replace('Z', '')}" + @change=${this.#onChange}> `; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/property-type-settings/property-type-settings-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/property-type-settings/property-type-settings-modal.element.ts index c28a24bcd3..8c045ef7a7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/property-type-settings/property-type-settings-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/property-type-settings/property-type-settings-modal.element.ts @@ -8,9 +8,9 @@ import type { } from './property-type-settings-modal.token.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UUIBooleanInputEvent, UUIInputEvent, UUISelectEvent } from '@umbraco-cms/backoffice/external/uui'; -import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import { umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { generateAlias } from '@umbraco-cms/backoffice/utils'; import { UMB_CONTENT_TYPE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/content-type'; // TODO: Could base take a token to get its types? [NL] @@ -92,15 +92,6 @@ export class UmbPropertyTypeSettingsModalElement extends UmbModalBaseElement< } } - protected firstUpdated(_changedProperties: PropertyValueMap | Map): void { - super.firstUpdated(_changedProperties); - - // TODO: Make a general way to put focus on a input in a modal. (also make sure it only happens if its the top-most-modal.) [NL] - requestAnimationFrame(() => { - (this.shadowRoot!.querySelector('#name-input') as HTMLElement).focus(); - }); - } - #onSubmit(event: SubmitEvent) { event.preventDefault(); @@ -240,7 +231,8 @@ export class UmbPropertyTypeSettingsModalElement extends UmbModalBaseElement< label="property name (TODO: Localize)" @input=${this.#onNameChange} .value=${this.value.name} - placeholder="Enter a name..."> + placeholder="Enter a name..." + ${umbFocus()}> ; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move-repository.interface.ts new file mode 100644 index 0000000000..4eb344bcd9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move-repository.interface.ts @@ -0,0 +1,7 @@ +import type { UmbRepositoryErrorResponse } from '../../../repository/types.js'; +import type { UmbMoveToRequestArgs } from './types.js'; +import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; + +export interface UmbMoveRepository extends UmbApi { + requestMoveTo(args: UmbMoveToRequestArgs): Promise; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move-to.action.kind.ts similarity index 75% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move.action.kind.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move-to.action.kind.ts index 09b3fb9010..79a7cdeae0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move.action.kind.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move-to.action.kind.ts @@ -3,22 +3,22 @@ import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extensio export const manifest: UmbBackofficeManifestKind = { type: 'kind', - alias: 'Umb.Kind.EntityAction.Move', - matchKind: 'move', + alias: 'Umb.Kind.EntityAction.MoveTo', + matchKind: 'moveTo', matchType: 'entityAction', manifest: { ...UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST.manifest, type: 'entityAction', - kind: 'move', - api: () => import('./move.action.js'), + kind: 'moveTo', + api: () => import('./move-to.action.js'), weight: 700, forEntityTypes: [], meta: { icon: 'icon-enter', label: '#actions_move', - itemRepositoryAlias: '', + treeRepositoryAlias: '', moveRepositoryAlias: '', - pickerModal: '', + treeAlias: '', }, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move-to.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move-to.action.ts new file mode 100644 index 0000000000..a06f2d9bc8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move-to.action.ts @@ -0,0 +1,44 @@ +import { UmbEntityActionBase } from '../../entity-action-base.js'; +import { UmbRequestReloadStructureForEntityEvent } from '../../request-reload-structure-for-entity.event.js'; +import type { UmbMoveRepository } from './move-repository.interface.js'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import type { MetaEntityActionMoveToKind } from '@umbraco-cms/backoffice/extension-registry'; +import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import { UMB_TREE_PICKER_MODAL } from '@umbraco-cms/backoffice/tree'; + +export class UmbMoveToEntityAction extends UmbEntityActionBase { + async execute() { + if (!this.args.unique) throw new Error('Unique is not available'); + if (!this.args.entityType) throw new Error('Entity Type is not available'); + + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const modalContext = modalManager.open(this, UMB_TREE_PICKER_MODAL, { + data: { treeAlias: this.args.meta.treeAlias }, + }) as any; // TODO: make generic picker interface with selection + const value = await modalContext.onSubmit(); + const destinationUnique = value.selection[0]; + if (destinationUnique === undefined) throw new Error('Destination Unique is not available'); + + const moveRepository = await createExtensionApiByAlias(this, this.args.meta.moveRepositoryAlias); + if (!moveRepository) throw new Error('Move Repository is not available'); + + await moveRepository.requestMoveTo({ unique: this.args.unique, destination: { unique: destinationUnique } }); + + this.#reloadMenu(); + } + + async #reloadMenu() { + const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadStructureForEntityEvent({ + unique: this.args.unique, + entityType: this.args.entityType, + }); + + actionEventContext.dispatchEvent(event); + + // TODO: Reload destination + } +} + +export default UmbMoveToEntityAction; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move.action.ts deleted file mode 100644 index cefe1cc8f8..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move.action.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { UmbEntityActionBase } from '../../entity-action-base.js'; -import type { UmbEntityActionArgs } from '../../types.js'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; -import type { UmbItemRepository, UmbMoveRepository } from '@umbraco-cms/backoffice/repository'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { umbExtensionsRegistry, type MetaEntityActionMoveKind } from '@umbraco-cms/backoffice/extension-registry'; -import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; - -export class UmbMoveEntityAction extends UmbEntityActionBase { - // TODO: make base type for item and detail models - #itemRepository?: UmbItemRepository; - #moveRepository?: UmbMoveRepository; - #init: Promise; - - constructor(host: UmbControllerHost, args: UmbEntityActionArgs) { - super(host, args); - - // TODO: We should properly look into how we can simplify the one time usage of a extension api, as its a bit of overkill to take conditions/overwrites and observation of extensions into play here: [NL] - // But since this happens when we execute an action, it does most likely not hurt any users, but it is a bit of a overkill to do this for every action: [NL] - this.#init = Promise.all([ - new UmbExtensionApiInitializer( - this._host, - umbExtensionsRegistry, - this.args.meta.itemRepositoryAlias, - [this._host], - (permitted, ctrl) => { - this.#itemRepository = permitted ? (ctrl.api as UmbItemRepository) : undefined; - }, - ).asPromise(), - - new UmbExtensionApiInitializer( - this._host, - umbExtensionsRegistry, - this.args.meta.moveRepositoryAlias, - [this._host], - (permitted, ctrl) => { - this.#moveRepository = permitted ? (ctrl.api as UmbMoveRepository) : undefined; - }, - ).asPromise(), - ]); - } - - async execute() { - if (!this.args.unique) throw new Error('Unique is not available'); - await this.#init; - - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const modalContext = modalManager.open(this, this.args.meta.pickerModal) as any; // TODO: make generic picker interface with selection - const value = await modalContext.onSubmit(); - if (!value) return; - await this.#moveRepository!.move(this.args.unique, value.selection[0]); - } -} - -export default UmbMoveEntityAction; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/types.ts new file mode 100644 index 0000000000..ec38ab9db3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/types.ts @@ -0,0 +1,6 @@ +export interface UmbMoveToRequestArgs { + unique: string; + destination: { + unique: string | null; + }; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts index bbe018524f..d5b95c0fa0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts @@ -1,13 +1,13 @@ import { manifests as defaultEntityActionManifests } from './default/manifests.js'; import { manifests as deleteEntityActionManifests } from './common/delete/manifests.js'; import { manifests as duplicateEntityActionManifests } from './common/duplicate/manifests.js'; -import { manifests as moveEntityActionManifests } from './common/move/manifests.js'; +import { manifests as moveToEntityActionManifests } from './common/move/manifests.js'; import { manifests as sortChildrenOfEntityActionManifests } from './common/sort-children-of/manifests.js'; export const manifests = [ ...defaultEntityActionManifests, ...deleteEntityActionManifests, ...duplicateEntityActionManifests, - ...moveEntityActionManifests, + ...moveToEntityActionManifests, ...sortChildrenOfEntityActionManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts index 68ed28918a..33b6440960 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts @@ -125,16 +125,16 @@ export interface MetaEntityActionDuplicateKind extends MetaEntityActionDefaultKi pickerModal: UmbModalToken | string; } -// MOVE -export interface ManifestEntityActionMoveKind extends ManifestEntityAction { +// MOVE TO +export interface ManifestEntityActionMoveToKind extends ManifestEntityAction { type: 'entityAction'; - kind: 'move'; + kind: 'moveTo'; } -export interface MetaEntityActionMoveKind extends MetaEntityActionDefaultKind { +export interface MetaEntityActionMoveToKind extends MetaEntityActionDefaultKind { moveRepositoryAlias: string; - itemRepositoryAlias: string; - pickerModal: UmbModalToken | string; + treeRepositoryAlias: string; + treeAlias: string; } // FOLDER diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts index 5729a909c2..26da468431 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts @@ -11,7 +11,7 @@ import type { ManifestEntityActionRenameServerFileKind, ManifestEntityActionReloadTreeItemChildrenKind, ManifestEntityActionDuplicateKind, - ManifestEntityActionMoveKind, + ManifestEntityActionMoveToKind, ManifestEntityActionCreateFolderKind, ManifestEntityActionUpdateFolderKind, ManifestEntityActionDeleteFolderKind, @@ -118,7 +118,7 @@ export type ManifestEntityActions = | ManifestEntityActionDeleteKind | ManifestEntityActionDuplicateKind | ManifestEntityActionEmptyRecycleBinKind - | ManifestEntityActionMoveKind + | ManifestEntityActionMoveToKind | ManifestEntityActionReloadTreeItemChildrenKind | ManifestEntityActionRenameServerFileKind | ManifestEntityActionRestoreFromRecycleBinKind diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts new file mode 100644 index 0000000000..d339d4d3f4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts @@ -0,0 +1,44 @@ +import { AsyncDirective, directive, nothing, type ElementPart } from '@umbraco-cms/backoffice/external/lit'; + +/** + * The `focus` directive sets focus on the given element once its connected to the DOM. + */ +class UmbFocusDirective extends AsyncDirective { + private _el?: HTMLElement; + + render() { + return nothing; + } + + override update(part: ElementPart) { + if (this._el !== part.element) { + // This does feel wrong that we need to wait one render. [NL] + // Because even if our elements focus method is implemented so it can be called initially, my research shows that calling the focus method at this point is too early, thought the element is connected to the DOM and the focus method is available. [NL] + // This smells a bit like the DOMPart of which the directive is in is not connected to the main DOM yet, and therefor cant receive focus. [NL] + // Which is why we need to await one render: [NL] + requestAnimationFrame(() => { + (this._el = part.element as HTMLElement).focus(); + }); + } + return nothing; + } + + override disconnected() { + this._el = undefined; + } + + //override reconnected() {} +} + +/** + * @description + * A Lit directive, which sets focus on the element of scope once its connected to the DOM. + * + * @example: + * ```js + * html``; + * ``` + */ +export const umbFocus = directive(UmbFocusDirective); + +//export type { UmbFocusDirective }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/index.ts new file mode 100644 index 0000000000..0ccb1bc7eb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/index.ts @@ -0,0 +1 @@ +export * from './focus.lit-directive.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/index.ts index c0b5f9cb8e..23bedd188b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/index.ts @@ -1 +1,2 @@ export * from './lit-element.element.js'; +export * from './directives/index.js'; 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 91fbb6af8e..6d454f5156 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 @@ -7,6 +7,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbIconPickerModalData, UmbIconPickerModalValue } from '@umbraco-cms/backoffice/modal'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { extractUmbColorVariable, umbracoColors } from '@umbraco-cms/backoffice/resources'; +import { umbFocus } from '@umbraco-cms/backoffice/lit-element'; // TODO: Make use of UmbPickerLayoutBase // TODO: to prevent element extension we need to move the Picker logic into a separate class we can reuse across all pickers @@ -109,7 +110,8 @@ export class UmbIconPickerModalElement extends UmbModalBaseElement + @keyup="${this.#filterIcons}" + ${umbFocus()}> `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/item-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/item-picker-modal.element.ts index 579ec7bec7..2903c9be24 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/item-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/item-picker-modal.element.ts @@ -11,6 +11,7 @@ import { import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbItemPickerModalData, UmbItemPickerModel } from '@umbraco-cms/backoffice/modal'; +import { umbFocus } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-item-picker-modal') export class UmbItemPickerModalElement extends UmbModalBaseElement { @@ -52,7 +53,11 @@ export class UmbItemPickerModalElement extends UmbModalBaseElement
- +
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/index.ts index 311a146e78..b6c574f8f0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/index.ts @@ -8,8 +8,6 @@ export * from './examine-fields-settings-modal.token.js'; export * from './icon-picker-modal.token.js'; export * from './item-picker-modal.token.js'; export * from './link-picker-modal.token.js'; -export * from './media-tree-picker-modal.token.js'; -export * from './media-type-picker-modal.token.js'; export * from './modal-token.js'; export * from './property-editor-ui-picker-modal.token.js'; export * from './workspace-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/media-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/media-type-picker-modal.token.ts deleted file mode 100644 index 39b54a4817..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/media-type-picker-modal.token.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { UmbModalToken } from './modal-token.js'; -import type { UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal'; -import type { UmbUniqueTreeItemModel } from '@umbraco-cms/backoffice/tree'; - -export type UmbMediaTypePickerModalData = UmbTreePickerModalData; -export type UmbMediaTypePickerModalValue = UmbPickerModalValue; - -export const UMB_MEDIA_TYPE_PICKER_MODAL = new UmbModalToken( - 'Umb.Modal.TreePicker', - { - modal: { - type: 'sidebar', - size: 'small', - }, - data: { - treeAlias: 'Umb.Tree.MediaType', - }, - }, -); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts index 8f42e65ee0..ac1b193cb6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts @@ -7,9 +7,3 @@ export interface UmbPickerModalData { export interface UmbPickerModalValue { selection: Array; } - -export interface UmbTreePickerModalData extends UmbPickerModalData { - treeAlias?: string; -} - -export interface UmbTreePickerModalValue extends UmbPickerModalValue {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/schemas/Umbraco.DateTime.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/schemas/Umbraco.DateTime.ts index 4bf4469b90..48a98c08a1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/schemas/Umbraco.DateTime.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/schemas/Umbraco.DateTime.ts @@ -1,36 +1,10 @@ import type { ManifestPropertyEditorSchema } from '@umbraco-cms/backoffice/extension-registry'; -// TODO: We won't include momentjs anymore so we need to find a way to handle date formats export const manifest: ManifestPropertyEditorSchema = { type: 'propertyEditorSchema', name: 'Date/Time', alias: 'Umbraco.DateTime', meta: { defaultPropertyEditorUiAlias: 'Umb.PropertyEditorUi.DatePicker', - settings: { - properties: [ - { - alias: 'offsetTime', - label: 'Offset time', - description: - 'When enabled the time displayed will be offset with the servers timezone, this is useful for scenarios like scheduled publishing when an editor is in a different timezone than the hosted server', - propertyEditorUiAlias: 'Umb.PropertyEditorUi.Toggle', - config: [ - { - alias: 'labelOff', - value: 'Adjust to local time', - }, - { - alias: 'labelOn', - value: 'Adjust to local time', - }, - { - alias: 'showLabels', - value: true, - }, - ], - }, - ], - }, }, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/date-picker/property-editor-ui-date-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/date-picker/property-editor-ui-date-picker.element.ts index ebbbe7daa9..9912586cf8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/date-picker/property-editor-ui-date-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/date-picker/property-editor-ui-date-picker.element.ts @@ -1,43 +1,15 @@ -import type { UmbPropertyEditorConfigCollection } from '../../index.js'; import { UmbPropertyValueChangeEvent } from '../../index.js'; -import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorConfigCollection } from '../../index.js'; +import { html, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbInputDateElement } from '@umbraco-cms/backoffice/components'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; /** * @element umb-property-editor-ui-date-picker */ @customElement('umb-property-editor-ui-date-picker') export class UmbPropertyEditorUIDatePickerElement extends UmbLitElement implements UmbPropertyEditorUiElement { - private _value?: Date; - private _valueString?: string; - - @property() - set value(value: string | undefined) { - if (value) { - const d = new Date(value); - this._value = d; - this._valueString = `${d.getFullYear()}-${ - d.getMonth() + 1 - }-${d.getDate()}T${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`; - } else { - this._value = undefined; - this._valueString = undefined; - } - } - get value() { - return this._valueString; - } - - private _onInput(e: InputEvent) { - const dateField = e.target as HTMLInputElement; - this.value = dateField.value; - this.dispatchEvent(new UmbPropertyValueChangeEvent()); - } - - private _format?: string; - @state() private _inputType: UmbInputDateElement['type'] = 'datetime-local'; @@ -50,29 +22,34 @@ export class UmbPropertyEditorUIDatePickerElement extends UmbLitElement implemen @state() private _step?: number; - private _offsetTime?: boolean; + @property() + set value(value: string | undefined) { + if (value) { + // NOTE: If the `value` contains a space, then it doesn't contain the timezone, so may not be parsed as UTC. [LK] + const datetime = !value.includes(' ') ? value : value + ' +00'; + this.#value = new Date(datetime).toJSON(); + } + } + get value() { + return this.#value; + } + #value?: string; public set config(config: UmbPropertyEditorConfigCollection | undefined) { if (!config) return; const oldVal = this._inputType; // Format string prevalue/config - this._format = config.getValueByAlias('format'); - const pickTime = this._format?.includes('H') || this._format?.includes('m'); - if (pickTime) { - this._inputType = 'datetime-local'; - } else { - this._inputType = 'date'; - } + const format = config.getValueByAlias('format'); + const hasTime = format?.includes('H') || format?.includes('m'); + this._inputType = hasTime ? 'datetime-local' : 'date'; // Based on the type of format string change the UUI-input type const timeFormatPattern = /^h{1,2}:m{1,2}(:s{1,2})?\s?a?$/gim; - if (this._format?.toLowerCase().match(timeFormatPattern)) { + if (format?.toLowerCase().match(timeFormatPattern)) { this._inputType = 'time'; } - //TODO: - this._offsetTime = config.getValueByAlias('offsetTime'); this._min = config.getValueByAlias('min'); this._max = config.getValueByAlias('max'); this._step = config.getValueByAlias('step'); @@ -80,16 +57,22 @@ export class UmbPropertyEditorUIDatePickerElement extends UmbLitElement implemen this.requestUpdate('_inputType', oldVal); } + #onChange(event: CustomEvent & { target: HTMLInputElement }) { + this.value = event.target.value; + this.dispatchEvent(new UmbPropertyValueChangeEvent()); + } + render() { - return html``; + return html` + + + `; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts index 7557680428..3e12caefbd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts @@ -5,6 +5,5 @@ export * from './item/index.js'; export * from './detail/index.js'; export type { UmbDataSourceResponse, UmbDataSourceErrorResponse } from './data-source-response.interface.js'; -export type { UmbMoveDataSource, UmbMoveRepository } from './move/index.js'; export type { UmbDuplicateDataSource, UmbDuplicateRepository } from './duplicate/index.js'; export type { UmbPagedModel, UmbRepositoryResponse, UmbRepositoryErrorResponse } from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/move/move-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/move/move-data-source.interface.ts deleted file mode 100644 index e0ac7ce1d7..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/move/move-data-source.interface.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { UmbDataSourceErrorResponse } from '@umbraco-cms/backoffice/repository'; - -export interface UmbMoveDataSource { - move(unique: string, targetUnique: string | null): Promise; -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/move/move-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/move/move-repository.interface.ts deleted file mode 100644 index 9502e8d409..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/move/move-repository.interface.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { UmbRepositoryErrorResponse } from '../types.js'; - -export interface UmbMoveRepository { - move(unique: string, targetUnique: string): Promise; -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts index a4f1071496..f12bb43497 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts @@ -13,6 +13,9 @@ export { UmbRequestReloadTreeItemChildrenEvent, } from './reload-tree-item-children/index.js'; +export type { UmbTreePickerModalData, UmbTreePickerModalValue } from './tree-picker/index.js'; +export { UMB_TREE_PICKER_MODAL, UMB_TREE_PICKER_MODAL_ALIAS } from './tree-picker/index.js'; + export * from './types.js'; /* diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/constants.ts new file mode 100644 index 0000000000..63e0be0e66 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/constants.ts @@ -0,0 +1 @@ +export const UMB_TREE_PICKER_MODAL_ALIAS = 'Umb.Modal.TreePicker'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/index.ts new file mode 100644 index 0000000000..7cbd303dac --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/index.ts @@ -0,0 +1,3 @@ +export { UMB_TREE_PICKER_MODAL_ALIAS } from './constants.js'; +export type { UmbTreePickerModalData, UmbTreePickerModalValue } from './tree-picker-modal.token.js'; +export { UMB_TREE_PICKER_MODAL } from './tree-picker-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts index da3a4232e9..2134ac64a2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts @@ -1,6 +1,6 @@ import type { UmbTreeSelectionConfiguration } from '../types.js'; +import type { UmbTreePickerModalData, UmbTreePickerModalValue } from './tree-picker-modal.token.js'; import { html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbTreePickerModalData, UmbPickerModalValue } from '@umbraco-cms/backoffice/modal'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UmbDeselectedEvent, UmbSelectedEvent, UmbSelectionChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbTreeElement, UmbTreeItemModelBase } from '@umbraco-cms/backoffice/tree'; @@ -8,7 +8,7 @@ import type { UmbTreeElement, UmbTreeItemModelBase } from '@umbraco-cms/backoffi @customElement('umb-tree-picker-modal') export class UmbTreePickerModalElement extends UmbModalBaseElement< UmbTreePickerModalData, - UmbPickerModalValue + UmbTreePickerModalValue > { @state() _selectionConfiguration: UmbTreeSelectionConfiguration = { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts new file mode 100644 index 0000000000..c0b5daa592 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts @@ -0,0 +1,19 @@ +import { UMB_TREE_PICKER_MODAL_ALIAS } from './constants.js'; +import type { UmbPickerModalData, UmbPickerModalValue } from '@umbraco-cms/backoffice/modal'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbTreePickerModalData extends UmbPickerModalData { + treeAlias?: string; +} + +export interface UmbTreePickerModalValue extends UmbPickerModalValue {} + +export const UMB_TREE_PICKER_MODAL = new UmbModalToken( + UMB_TREE_PICKER_MODAL_ALIAS, + { + modal: { + type: 'sidebar', + size: 'small', + }, + }, +); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/variant-selector/variant-selector.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/variant-selector/variant-selector.element.ts index 6342015531..833b115891 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/variant-selector/variant-selector.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/variant-selector/variant-selector.element.ts @@ -7,7 +7,7 @@ import { } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state, query } from '@umbraco-cms/backoffice/external/lit'; import { UMB_WORKSPACE_SPLIT_VIEW_CONTEXT, type ActiveVariant } from '@umbraco-cms/backoffice/workspace'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbDocumentWorkspaceContext } from '@umbraco-cms/backoffice/document'; @@ -206,6 +206,7 @@ export class UmbVariantSelectorElement extends UmbLitElement { label="Document name (TODO: Localize)" .value=${this._name ?? ''} @input=${this.#handleInput} + ${umbFocus()} > ${ this._variants?.length diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/manifests.ts index e75c7625ff..4220e0dea3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/manifests.ts @@ -2,7 +2,7 @@ import { UMB_DATA_TYPE_ENTITY_TYPE } from '../entity.js'; import { UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../repository/detail/index.js'; import { UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS } from '../repository/item/manifests.js'; import { manifests as createManifests } from './create/manifests.js'; -import { manifests as moveManifests } from './move/manifests.js'; +import { manifests as moveManifests } from './move-to/manifests.js'; import { manifests as duplicateManifests } from './duplicate/manifests.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/index.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/index.ts new file mode 100644 index 0000000000..4d65421fc3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/index.ts @@ -0,0 +1 @@ +export { UmbMoveDataTypeRepository, UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/manifests.ts new file mode 100644 index 0000000000..84363a8f97 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/manifests.ts @@ -0,0 +1,23 @@ +import { UMB_DATA_TYPE_ENTITY_TYPE } from '../../entity.js'; +import { UMB_DATA_TYPE_TREE_REPOSITORY_ALIAS } from '../../tree/index.js'; +import { UMB_DATA_TYPE_TREE_ALIAS } from '../../tree/manifests.js'; +import { UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './repository/index.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +const entityActions: Array = [ + { + type: 'entityAction', + kind: 'moveTo', + alias: 'Umb.EntityAction.DataType.MoveTo', + name: 'Move Data Type Entity Action', + forEntityTypes: [UMB_DATA_TYPE_ENTITY_TYPE], + meta: { + treeRepositoryAlias: UMB_DATA_TYPE_TREE_REPOSITORY_ALIAS, + moveRepositoryAlias: UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS, + treeAlias: UMB_DATA_TYPE_TREE_ALIAS, + }, + }, +]; + +export const manifests = [...entityActions, ...repositoryManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/constants.ts new file mode 100644 index 0000000000..6b264a17ca --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/constants.ts @@ -0,0 +1 @@ +export const UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Move'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/data-type-move.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/data-type-move.repository.ts new file mode 100644 index 0000000000..265cef4ccb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/data-type-move.repository.ts @@ -0,0 +1,20 @@ +import { UmbMoveDataTypeServerDataSource } from './data-type-move.server.data-source.js'; +import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; +import type { UmbMoveRepository, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-action'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +export class UmbMoveDataTypeRepository extends UmbRepositoryBase implements UmbMoveRepository { + #moveSource = new UmbMoveDataTypeServerDataSource(this); + + async requestMoveTo(args: UmbMoveToRequestArgs) { + const { error } = await this.#moveSource.moveTo(args); + + if (!error) { + const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT); + const notification = { data: { message: `Moved` } }; + notificationContext.peek('positive', notification); + } + + return { error }; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/data-type-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/data-type-move.server.data-source.ts new file mode 100644 index 0000000000..4b96fcf784 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/data-type-move.server.data-source.ts @@ -0,0 +1,44 @@ +import { DataTypeService } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import type { UmbMoveDataSource, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-action'; + +/** + * Move Data Type Server Data Source + * @export + * @class UmbMoveDataTypeServerDataSource + */ +export class UmbMoveDataTypeServerDataSource implements UmbMoveDataSource { + #host: UmbControllerHost; + + /** + * Creates an instance of UmbMoveDataTypeServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbMoveDataTypeServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Move an item for the given id to the target unique + * @param {string} unique + * @param {(string | null)} targetUnique + * @return {*} + * @memberof UmbMoveDataTypeServerDataSource + */ + async moveTo(args: UmbMoveToRequestArgs) { + if (!args.unique) throw new Error('Unique is missing'); + if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); + + return tryExecuteAndNotify( + this.#host, + DataTypeService.putDataTypeByIdMove({ + id: args.unique, + requestBody: { + target: args.destination.unique ? { id: args.destination.unique } : null, + }, + }), + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/index.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/index.ts similarity index 56% rename from src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/index.ts index dfc6dcb884..6c2a31c2d8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/index.ts @@ -1,2 +1,2 @@ export { UmbMoveDataTypeRepository } from './data-type-move.repository.js'; -export { UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './manifests.js'; +export { UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/manifests.ts similarity index 82% rename from src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/manifests.ts index b43eca4387..911c6e83a0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/manifests.ts @@ -1,8 +1,7 @@ +import { UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './constants.js'; import { UmbMoveDataTypeRepository } from './data-type-move.repository.js'; import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; -export const UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Move'; - const moveRepository: ManifestRepository = { type: 'repository', alias: UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS, diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move/manifests.ts deleted file mode 100644 index 79ef41ec28..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move/manifests.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { UMB_DATA_TYPE_ENTITY_TYPE } from '../../entity.js'; -import { UMB_DATA_TYPE_PICKER_MODAL } from '../../modals/index.js'; -import { UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js'; -import { UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from '../../repository/move/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; - -const entityActions: Array = [ - { - type: 'entityAction', - kind: 'move', - alias: 'Umb.EntityAction.DataType.Move', - name: 'Move Data Type Entity Action', - forEntityTypes: [UMB_DATA_TYPE_ENTITY_TYPE], - meta: { - itemRepositoryAlias: UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS, - moveRepositoryAlias: UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS, - pickerModal: UMB_DATA_TYPE_PICKER_MODAL, - }, - }, -]; - -export const manifests = [...entityActions]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts index b7e28226cd..5c6ce9c6f7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts @@ -6,4 +6,6 @@ export * from './repository/index.js'; export * from './workspace/index.js'; export * from './modals/index.js'; +export { UmbMoveDataTypeRepository, UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './entity-actions/move-to/index.js'; + export type { UmbDataTypeDetailModel } from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts index d0d634e4e0..962abe0c73 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts @@ -14,6 +14,7 @@ import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension import type { UmbDataTypeItemModel } from '@umbraco-cms/backoffice/data-type'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/modal'; import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; +import { umbFocus } from '@umbraco-cms/backoffice/lit-element'; interface GroupedItems { [key: string]: Array; @@ -187,7 +188,8 @@ export class UmbDataTypePickerFlowModalElement extends UmbModalBaseElement< id="filter" @input="${this._handleFilterInput}" placeholder="Type to filter..." - label="Type to filter icons"> + label="Type to filter icons" + ${umbFocus()}>
`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-modal.token.ts index 1208d6e2c1..d3b0d87e26 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-modal.token.ts @@ -1,12 +1,16 @@ -import type { UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal'; +import { + type UmbTreePickerModalValue, + type UmbTreePickerModalData, + type UmbUniqueTreeItemModel, + UMB_TREE_PICKER_MODAL_ALIAS, +} from '@umbraco-cms/backoffice/tree'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; -import type { UmbUniqueTreeItemModel } from '@umbraco-cms/backoffice/tree'; export type UmbDataTypePickerModalData = UmbTreePickerModalData; -export type UmbDataTypePickerModalValue = UmbPickerModalValue; +export type UmbDataTypePickerModalValue = UmbTreePickerModalValue; export const UMB_DATA_TYPE_PICKER_MODAL = new UmbModalToken( - 'Umb.Modal.TreePicker', + UMB_TREE_PICKER_MODAL_ALIAS, { modal: { type: 'sidebar', diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts index 938329aea6..7a1894f23f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts @@ -8,6 +8,7 @@ import type { import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { umbFocus } from '@umbraco-cms/backoffice/lit-element'; interface GroupedPropertyEditorUIs { [key: string]: Array; @@ -71,7 +72,7 @@ export class UmbPropertyEditorUIPickerModalElement extends UmbModalBaseElement< return ( propertyEditorUI.name.toLowerCase().includes(query) || propertyEditorUI.alias.toLowerCase().includes(query) ); - }); + }); // TODO: groupBy is not known by TS yet // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -104,7 +105,8 @@ export class UmbPropertyEditorUIPickerModalElement extends UmbModalBaseElement< id="filter" @input="${this.#handleFilterInput}" placeholder="Type to filter..." - label="Type to filter icons"> + label="Type to filter icons" + ${umbFocus()}>
`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/index.ts index 56c390dd50..b20008a4af 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/index.ts @@ -5,6 +5,5 @@ export { UMB_DATA_TYPE_DETAIL_STORE_CONTEXT, } from './detail/index.js'; export { UmbDataTypeItemRepository, UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS } from './item/index.js'; -export { UmbMoveDataTypeRepository, UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './move/index.js'; export type { UmbDataTypeItemModel } from './item/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/manifests.ts index d2d7f2a1c0..a403530c4c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/manifests.ts @@ -1,6 +1,5 @@ import { manifests as duplicateManifests } from './duplicate/manifests.js'; import { manifests as detailManifests } from './detail/manifests.js'; import { manifests as itemManifests } from './item/manifests.js'; -import { manifests as moveManifests } from './move/manifests.js'; -export const manifests = [...duplicateManifests, ...detailManifests, ...itemManifests, ...moveManifests]; +export const manifests = [...duplicateManifests, ...detailManifests, ...itemManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/data-type-move.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/data-type-move.repository.ts deleted file mode 100644 index 78720534b1..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/data-type-move.repository.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { UmbDataTypeTreeStore } from '../../tree/data-type-tree.store.js'; -import { UMB_DATA_TYPE_TREE_STORE_CONTEXT } from '../../tree/data-type-tree.store.js'; -import { UmbDataTypeMoveServerDataSource } from './data-type-move.server.data-source.js'; -import type { UmbNotificationContext } from '@umbraco-cms/backoffice/notification'; -import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import type { UmbMoveDataSource, UmbMoveRepository} from '@umbraco-cms/backoffice/repository'; -import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; - -export class UmbMoveDataTypeRepository extends UmbRepositoryBase implements UmbMoveRepository { - #init: Promise; - #moveSource: UmbMoveDataSource; - #treeStore?: UmbDataTypeTreeStore; - #notificationContext?: UmbNotificationContext; - - constructor(host: UmbControllerHost) { - super(host); - this.#moveSource = new UmbDataTypeMoveServerDataSource(this); - - this.#init = Promise.all([ - this.consumeContext(UMB_DATA_TYPE_TREE_STORE_CONTEXT, (instance) => { - this.#treeStore = instance; - }).asPromise(), - - this.consumeContext(UMB_NOTIFICATION_CONTEXT, (instance) => { - this.#notificationContext = instance; - }).asPromise(), - ]); - } - - async move(unique: string, targetUnique: string | null) { - await this.#init; - const { error } = await this.#moveSource.move(unique, targetUnique); - - if (!error) { - // TODO: Be aware about this responsibility. - this.#treeStore!.updateItem(unique, { parentUnique: targetUnique }); - - const notification = { data: { message: `Data type moved` } }; - this.#notificationContext!.peek('positive', notification); - } - - return { error }; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/data-type-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/data-type-move.server.data-source.ts deleted file mode 100644 index 8152c3e0c5..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/move/data-type-move.server.data-source.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { DataTypeService } from '@umbraco-cms/backoffice/external/backend-api'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; -import type { UmbMoveDataSource } from '@umbraco-cms/backoffice/repository'; - -/** - * A data source for Data Type items that fetches data from the server - * @export - * @class UmbDataTypeMoveServerDataSource - */ -export class UmbDataTypeMoveServerDataSource implements UmbMoveDataSource { - #host: UmbControllerHost; - - /** - * Creates an instance of UmbDataTypeMoveServerDataSource. - * @param {UmbControllerHost} host - * @memberof UmbDataTypeMoveServerDataSource - */ - constructor(host: UmbControllerHost) { - this.#host = host; - } - - /** - * Move an item for the given id to the target unique - * @param {string} unique - * @param {(string | null)} targetUnique - * @return {*} - * @memberof UmbDataTypeMoveServerDataSource - */ - async move(unique: string, targetUnique: string | null) { - if (!unique) throw new Error('Unique is missing'); - if (targetUnique === undefined) throw new Error('Target unique is missing'); - - return tryExecuteAndNotify( - this.#host, - DataTypeService.putDataTypeByIdMove({ - id: unique, - requestBody: { - target: targetUnique ? { id: targetUnique } : null, - }, - }), - ); - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/tree/manifests.ts index e854377970..0d57f28704 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/tree/manifests.ts @@ -11,6 +11,7 @@ import type { export const UMB_DATA_TYPE_TREE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Tree'; export const UMB_DATA_TYPE_TREE_STORE_ALIAS = 'Umb.Store.DataType.Tree'; +export const UMB_DATA_TYPE_TREE_ALIAS = 'Umb.Tree.DataType'; const treeRepository: ManifestRepository = { type: 'repository', @@ -29,7 +30,7 @@ const treeStore: ManifestTreeStore = { const tree: ManifestTree = { type: 'tree', kind: 'default', - alias: 'Umb.Tree.DataType', + alias: UMB_DATA_TYPE_TREE_ALIAS, name: 'Data Types Tree', meta: { repositoryAlias: UMB_DATA_TYPE_TREE_REPOSITORY_ALIAS, diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace-editor.element.ts index 45467a2189..db4e305eaa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace-editor.element.ts @@ -2,7 +2,7 @@ import { UMB_DATA_TYPE_WORKSPACE_CONTEXT } from './data-type-workspace.context-t import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry'; /** * @element umb-data-type-workspace-editor @@ -24,29 +24,10 @@ export class UmbDataTypeWorkspaceEditorElement extends UmbLitElement { this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, (workspaceContext) => { this.#workspaceContext = workspaceContext; this.#workspaceContext.createPropertyDatasetContext(this); - this.#observeIsNew(); this.#observeName(); }); } - // TODO: invent some general way for all workspaces, with a name?, to put focus on the name when new. - #observeIsNew() { - if (!this.#workspaceContext) return; - this.observe( - this.#workspaceContext.isNew, - (isNew) => { - if (isNew) { - // TODO: Make a general way to put focus on a input in a modal. (also make sure it only happens if its the top-most-modal.) - requestAnimationFrame(() => { - (this.shadowRoot!.querySelector('#nameInput') as HTMLElement).focus(); - }); - } - this.removeUmbControllerByAlias('isNewRedirectController'); - }, - '_observeIsNew', - ); - } - #observeName() { if (!this.#workspaceContext) return; this.observe(this.#workspaceContext.name, (dataTypeName) => { @@ -70,7 +51,12 @@ export class UmbDataTypeWorkspaceEditorElement extends UmbLitElement { render() { return html` - + `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/manifests.ts index e331dd3d01..21697bf0ee 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/manifests.ts @@ -1,5 +1,6 @@ import { UMB_DICTIONARY_ENTITY_TYPE, UMB_DICTIONARY_ROOT_ENTITY_TYPE } from '../entity.js'; import { UMB_DICTIONARY_DETAIL_REPOSITORY_ALIAS, UMB_DICTIONARY_ITEM_REPOSITORY_ALIAS } from '../repository/index.js'; +import { manifests as moveManifests } from './move-to/manifests.js'; import type { ManifestModal, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; const entityActions: Array = [ @@ -16,16 +17,6 @@ const entityActions: Array = [ label: '#dictionary_createNew', }, }, - { - type: 'entityAction', - kind: 'move', - alias: 'Umb.EntityAction.Dictionary.Move', - name: 'Move Dictionary Entity Action', - forEntityTypes: [UMB_DICTIONARY_ENTITY_TYPE], - meta: { - moveRepositoryAlias: UMB_DICTIONARY_ITEM_REPOSITORY_ALIAS, - }, - }, { type: 'entityAction', kind: 'default', @@ -80,4 +71,4 @@ const modals: Array = [ }, ]; -export const manifests = [...entityActions, ...modals]; +export const manifests = [...entityActions, ...modals, ...moveManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/index.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/index.ts new file mode 100644 index 0000000000..031cf69f39 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/index.ts @@ -0,0 +1 @@ +export { UmbMoveDictionaryRepository, UMB_MOVE_DICTIONARY_REPOSITORY_ALIAS } from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/manifests.ts new file mode 100644 index 0000000000..5dd01d2e19 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/manifests.ts @@ -0,0 +1,22 @@ +import { UMB_DICTIONARY_ENTITY_TYPE } from '../../entity.js'; +import { UMB_DICTIONARY_TREE_ALIAS, UMB_DICTIONARY_TREE_REPOSITORY_ALIAS } from '../../tree/index.js'; +import { UMB_MOVE_DICTIONARY_REPOSITORY_ALIAS } from './repository/index.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +const entityActions: Array = [ + { + type: 'entityAction', + kind: 'moveTo', + alias: 'Umb.EntityAction.Dictionary.MoveTo', + name: 'Move Dictionary Entity Action', + forEntityTypes: [UMB_DICTIONARY_ENTITY_TYPE], + meta: { + treeRepositoryAlias: UMB_DICTIONARY_TREE_REPOSITORY_ALIAS, + moveRepositoryAlias: UMB_MOVE_DICTIONARY_REPOSITORY_ALIAS, + treeAlias: UMB_DICTIONARY_TREE_ALIAS, + }, + }, +]; + +export const manifests = [...entityActions, ...repositoryManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/constants.ts new file mode 100644 index 0000000000..2ddf48772c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/constants.ts @@ -0,0 +1 @@ +export const UMB_MOVE_DICTIONARY_REPOSITORY_ALIAS = 'Umb.Repository.Dictionary.Move'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/dictionary-move.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/dictionary-move.repository.ts new file mode 100644 index 0000000000..dbd5979a6e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/dictionary-move.repository.ts @@ -0,0 +1,20 @@ +import { UmbMoveDictionaryServerDataSource } from './dictionary-move.server.data-source.js'; +import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; +import type { UmbMoveRepository, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-action'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +export class UmbMoveDictionaryRepository extends UmbRepositoryBase implements UmbMoveRepository { + #moveSource = new UmbMoveDictionaryServerDataSource(this); + + async requestMoveTo(args: UmbMoveToRequestArgs) { + const { error } = await this.#moveSource.moveTo(args); + + if (!error) { + const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT); + const notification = { data: { message: `Moved` } }; + notificationContext.peek('positive', notification); + } + + return { error }; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/dictionary-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/dictionary-move.server.data-source.ts new file mode 100644 index 0000000000..c3713c0214 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/dictionary-move.server.data-source.ts @@ -0,0 +1,44 @@ +import { DictionaryService } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import type { UmbMoveDataSource, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-action'; + +/** + * Move Dictionary Server Data Source + * @export + * @class UmbMoveDictionaryServerDataSource + */ +export class UmbMoveDictionaryServerDataSource implements UmbMoveDataSource { + #host: UmbControllerHost; + + /** + * Creates an instance of UmbMoveDictionaryServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbMoveDictionaryServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Move an item for the given id to the target unique + * @param {string} unique + * @param {(string | null)} targetUnique + * @return {*} + * @memberof UmbMoveDictionaryServerDataSource + */ + async moveTo(args: UmbMoveToRequestArgs) { + if (!args.unique) throw new Error('Unique is missing'); + if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); + + return tryExecuteAndNotify( + this.#host, + DictionaryService.putDictionaryByIdMove({ + id: args.unique, + requestBody: { + target: args.destination.unique ? { id: args.destination.unique } : null, + }, + }), + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/index.ts new file mode 100644 index 0000000000..52fc988053 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/index.ts @@ -0,0 +1,2 @@ +export { UmbMoveDictionaryRepository } from './dictionary-move.repository.js'; +export { UMB_MOVE_DICTIONARY_REPOSITORY_ALIAS } from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/manifests.ts new file mode 100644 index 0000000000..003a41bed2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/manifests.ts @@ -0,0 +1,12 @@ +import { UMB_MOVE_DICTIONARY_REPOSITORY_ALIAS } from './constants.js'; +import { UmbMoveDictionaryRepository } from './dictionary-move.repository.js'; +import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +const moveRepository: ManifestRepository = { + type: 'repository', + alias: UMB_MOVE_DICTIONARY_REPOSITORY_ALIAS, + name: 'Move Dictionary Repository', + api: UmbMoveDictionaryRepository, +}; + +export const manifests = [moveRepository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/modals/dictionary-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/modals/dictionary-picker-modal.token.ts index 09dd4db6b5..e967c0a391 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/modals/dictionary-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/modals/dictionary-picker-modal.token.ts @@ -1,14 +1,18 @@ import type { UmbUniqueTreeItemModel } from '../../core/tree/types.js'; import { UmbModalToken } from '../../core/modal/token/modal-token.js'; -import type { UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal'; +import { + type UmbTreePickerModalValue, + type UmbTreePickerModalData, + UMB_TREE_PICKER_MODAL_ALIAS, +} from '@umbraco-cms/backoffice/tree'; export type UmbDictionaryPickerModalData = UmbTreePickerModalData; -export type UmbDictionaryPickerModalValue = UmbPickerModalValue; +export type UmbDictionaryPickerModalValue = UmbTreePickerModalValue; export const UMB_DICTIONARY_PICKER_MODAL = new UmbModalToken< UmbDictionaryPickerModalData, UmbDictionaryPickerModalValue ->('Umb.Modal.TreePicker', { +>(UMB_TREE_PICKER_MODAL_ALIAS, { modal: { type: 'sidebar', size: 'small', diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/dictionary-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/dictionary-workspace-editor.element.ts index b1a2e6eb04..96d7b1aa3d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/dictionary-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/dictionary-workspace-editor.element.ts @@ -2,7 +2,7 @@ import { UMB_DICTIONARY_WORKSPACE_CONTEXT } from './dictionary-workspace.context import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-dictionary-workspace-editor') export class UmbDictionaryWorkspaceEditorElement extends UmbLitElement { @@ -47,7 +47,8 @@ export class UmbDictionaryWorkspaceEditorElement extends UmbLitElement { placeholder=${this.localize.term('placeholders_entername')} .value=${this._name ?? ''} @input="${this.#handleInput}" - label="${this.localize.term('general_dictionary')} ${this.localize.term('general_name')}"> + label="${this.localize.term('general_dictionary')} ${this.localize.term('general_name')}" + ${umbFocus()}>
`; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/modal/document-blueprint-options-create-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/modal/document-blueprint-options-create-modal.element.ts index 4ef5397d3a..dda14004e9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/modal/document-blueprint-options-create-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/entity-actions/create/modal/document-blueprint-options-create-modal.element.ts @@ -1,3 +1,4 @@ +import { UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS } from '../../../tree/folder/manifests.js'; import type { UmbDocumentBlueprintOptionsCreateModalData, UmbDocumentBlueprintOptionsCreateModalValue, @@ -6,13 +7,42 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { html, customElement, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { type UmbSelectedEvent, UmbSelectionChangeEvent } from '@umbraco-cms/backoffice/event'; -import type { UmbTreeElement } from '@umbraco-cms/backoffice/tree'; +import { UmbCreateFolderEntityAction, type UmbTreeElement } from '@umbraco-cms/backoffice/tree'; @customElement('umb-document-blueprint-options-create-modal') export class UmbDocumentBlueprintOptionsCreateModalElement extends UmbModalBaseElement< UmbDocumentBlueprintOptionsCreateModalData, UmbDocumentBlueprintOptionsCreateModalValue > { + #createFolderAction?: UmbCreateFolderEntityAction; + + connectedCallback(): void { + super.connectedCallback(); + if (!this.data?.parent) throw new Error('A parent is required to create a folder'); + + // TODO: render the info from this instance in the list of actions + this.#createFolderAction = new UmbCreateFolderEntityAction(this, { + unique: this.data.parent.unique, + entityType: this.data.parent.entityType, + meta: { + icon: 'icon-folder', + label: 'New Folder...', + folderRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS, + }, + }); + } + + async #onCreateFolderClick(event: PointerEvent) { + event.stopPropagation(); + + try { + await this.#createFolderAction?.execute(); + this._submitModal(); + } catch (error) { + console.error(error); + } + } + #onSelected(event: UmbSelectedEvent) { event.stopPropagation(); const element = event.target as UmbTreeElement; @@ -24,8 +54,12 @@ export class UmbDocumentBlueprintOptionsCreateModalElement extends UmbModalBaseE render() { return html` - - Create an item under Content Templates + + + + + + Select the Document Type you want to make a content blueprint for @@ -45,8 +79,8 @@ export class UmbDocumentBlueprintOptionsCreateModalElement extends UmbModalBaseE static styles = [ UmbTextStyles, css` - strong { - display: block; + uui-box:first-child { + margin-bottom: var(--uui-size-6); } `, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts index c7d511a210..f0bd797c6a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/document-blueprint-tree.server.data-source.ts @@ -1,4 +1,4 @@ -import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE } from '../entity.js'; +import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE, UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../entity.js'; import type { UmbDocumentBlueprintTreeItemModel } from './types.js'; import { UmbTreeServerDataSourceBase } from '@umbraco-cms/backoffice/tree'; import { DocumentBlueprintService } from '@umbraco-cms/backoffice/external/backend-api'; @@ -43,27 +43,26 @@ const getChildrenOf = (args: UmbTreeChildrenOfRequestArgs) => { if (args.parentUnique === null) { return getRootItems(args); } else { - throw new Error('Not implemented'); - /* // eslint-disable-next-line local-rules/no-direct-api-import return DocumentBlueprintService.getTreeDocumentBlueprintChildren({ parentId: args.parentUnique, }); - */ } }; const getAncestorsOf = (args: UmbTreeAncestorsOfRequestArgs) => { throw new Error('Not implemented'); + /** TODO: Implement when endpoint becomes available... */ }; const mapper = (item: DocumentBlueprintTreeItemResponseModel): UmbDocumentBlueprintTreeItemModel => { return { unique: item.id, parentUnique: item.parent?.id || null, - name: (item as any).variants?.[0].name ?? item.name, - entityType: UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE, - isFolder: false, + name: (item as any).variants?.[0].name ?? item.name, + entityType: item.isFolder ? UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE : UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE, + isFolder: item.isFolder, hasChildren: item.hasChildren, + icon: item.isFolder ? 'icon-folder' : 'icon-blueprint', }; }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.repository.ts index 1031ebc6ed..4510666a59 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.repository.ts @@ -1,9 +1,9 @@ -// import { UmbDocumentBlueprintFolderServerDataSource } from './document-blueprint-folder.server.data-source.js'; -// import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -// import { UmbFolderRepositoryBase } from '@umbraco-cms/backoffice/tree'; +import { UmbDocumentBlueprintFolderServerDataSource } from './document-blueprint-folder.server.data-source.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbFolderRepositoryBase } from '@umbraco-cms/backoffice/tree'; -// export class UmbDocumentBlueprintFolderRepository extends UmbFolderRepositoryBase { -// constructor(host: UmbControllerHost) { -// super(host, UmbDocumentBlueprintFolderServerDataSource); -// } -// } +export class UmbDocumentBlueprintFolderRepository extends UmbFolderRepositoryBase { + constructor(host: UmbControllerHost) { + super(host, UmbDocumentBlueprintFolderServerDataSource); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.server.data-source.ts index e0dce44acd..ef7645c2ae 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/document-blueprint-folder.server.data-source.ts @@ -1,122 +1,122 @@ -// import type { UmbCreateFolderModel, UmbFolderDataSource, UmbUpdateFolderModel } from '@umbraco-cms/backoffice/tree'; -// import { DocumentBlueprintService } from '@umbraco-cms/backoffice/external/backend-api'; -// import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -// import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import type { UmbCreateFolderModel, UmbFolderDataSource, UmbUpdateFolderModel } from '@umbraco-cms/backoffice/tree'; +import { DocumentBlueprintService } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; -// /** -// * A data source for a Document Blueprint folder that fetches data from the server -// * @export -// * @class UmbDocumentBlueprintFolderServerDataSource -// * @implements {RepositoryDetailDataSource} -// */ -// export class UmbDocumentBlueprintFolderServerDataSource implements UmbFolderDataSource { -// #host: UmbControllerHost; +/** + * A data source for a Document Blueprint folder that fetches data from the server + * @export + * @class UmbDocumentBlueprintFolderServerDataSource + * @implements {RepositoryDetailDataSource} + */ +export class UmbDocumentBlueprintFolderServerDataSource implements UmbFolderDataSource { + #host: UmbControllerHost; -// /** -// * Creates an instance of UmbDocumentBlueprintFolderServerDataSource. -// * @param {UmbControllerHost} host -// * @memberof UmbDocumentBlueprintFolderServerDataSource -// */ -// constructor(host: UmbControllerHost) { -// this.#host = host; -// } + /** + * Creates an instance of UmbDocumentBlueprintFolderServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbDocumentBlueprintFolderServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } -// /** -// * Fetches a Document Blueprint folder from the server -// * @param {string} unique -// * @return {*} -// * @memberof UmbDocumentBlueprintFolderServerDataSource -// */ -// async read(unique: string) { -// if (!unique) throw new Error('Unique is missing'); + /** + * Fetches a Document Blueprint folder from the server + * @param {string} unique + * @return {*} + * @memberof UmbDocumentBlueprintFolderServerDataSource + */ + async read(unique: string) { + if (!unique) throw new Error('Unique is missing'); -// const { data, error } = await tryExecuteAndNotify( -// this.#host, -// DocumentBlueprintService.getDocumentBlueprintFolderById({ -// id: unique, -// }), -// ); + const { data, error } = await tryExecuteAndNotify( + this.#host, + DocumentBlueprintService.getDocumentBlueprintFolderById({ + id: unique, + }), + ); -// if (data) { -// const mappedData = { -// unique: data.id, -// name: data.name, -// }; + if (data) { + const mappedData = { + unique: data.id, + name: data.name, + }; -// return { data: mappedData }; -// } + return { data: mappedData }; + } -// return { error }; -// } + return { error }; + } -// /** -// * Creates a Document Blueprint folder on the server -// * @param {UmbCreateFolderModel} args -// * @return {*} -// * @memberof UmbDocumentBlueprintFolderServerDataSource -// */ -// async create(args: UmbCreateFolderModel) { -// if (args.parentUnique === undefined) throw new Error('Parent unique is missing'); -// if (!args.name) throw new Error('Name is missing'); + /** + * Creates a Document Blueprint folder on the server + * @param {UmbCreateFolderModel} args + * @return {*} + * @memberof UmbDocumentBlueprintFolderServerDataSource + */ + async create(args: UmbCreateFolderModel) { + if (args.parentUnique === undefined) throw new Error('Parent unique is missing'); + if (!args.name) throw new Error('Name is missing'); -// const requestBody = { -// id: args.unique, -// parent: args.parentUnique ? { id: args.parentUnique } : null, -// name: args.name, -// }; + const requestBody = { + id: args.unique, + parent: args.parentUnique ? { id: args.parentUnique } : null, + name: args.name, + }; -// const { error } = await tryExecuteAndNotify( -// this.#host, -// DocumentBlueprintService.postDocumentBlueprintFolder({ -// requestBody, -// }), -// ); + const { error } = await tryExecuteAndNotify( + this.#host, + DocumentBlueprintService.postDocumentBlueprintFolder({ + requestBody, + }), + ); -// if (!error) { -// return this.read(args.unique); -// } + if (!error) { + return this.read(args.unique); + } -// return { error }; -// } + return { error }; + } -// /** -// * Updates a Document Blueprint folder on the server -// * @param {UmbUpdateFolderModel} args -// * @return {*} -// * @memberof UmbDocumentBlueprintFolderServerDataSource -// */ -// async update(args: UmbUpdateFolderModel) { -// if (!args.unique) throw new Error('Unique is missing'); -// if (!args.name) throw new Error('Folder name is missing'); + /** + * Updates a Document Blueprint folder on the server + * @param {UmbUpdateFolderModel} args + * @return {*} + * @memberof UmbDocumentBlueprintFolderServerDataSource + */ + async update(args: UmbUpdateFolderModel) { + if (!args.unique) throw new Error('Unique is missing'); + if (!args.name) throw new Error('Folder name is missing'); -// const { error } = await tryExecuteAndNotify( -// this.#host, -// DocumentBlueprintService.putDocumentBlueprintFolderById({ -// id: args.unique, -// requestBody: { name: args.name }, -// }), -// ); + const { error } = await tryExecuteAndNotify( + this.#host, + DocumentBlueprintService.putDocumentBlueprintFolderById({ + id: args.unique, + requestBody: { name: args.name }, + }), + ); -// if (!error) { -// return this.read(args.unique); -// } + if (!error) { + return this.read(args.unique); + } -// return { error }; -// } + return { error }; + } -// /** -// * Deletes a Document Blueprint folder on the server -// * @param {string} unique -// * @return {*} -// * @memberof UmbDocumentBlueprintServerDataSource -// */ -// async delete(unique: string) { -// if (!unique) throw new Error('Unique is missing'); -// return tryExecuteAndNotify( -// this.#host, -// DocumentBlueprintService.deleteDocumentBlueprintFolderById({ -// id: unique, -// }), -// ); -// } -// } + /** + * Deletes a Document Blueprint folder on the server + * @param {string} unique + * @return {*} + * @memberof UmbDocumentBlueprintServerDataSource + */ + async delete(unique: string) { + if (!unique) throw new Error('Unique is missing'); + return tryExecuteAndNotify( + this.#host, + DocumentBlueprintService.deleteDocumentBlueprintFolderById({ + id: unique, + }), + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/index.ts index c0cde243d3..29904de469 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/index.ts @@ -1,2 +1,2 @@ -// export { UmbDocumentBlueprintFolderRepository } from './document-blueprint-folder.repository.js'; -// export { UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS } from './manifests.js'; +export { UmbDocumentBlueprintFolderRepository } from './document-blueprint-folder.repository.js'; +export { UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/manifests.ts index 90635572ee..9eef583220 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/manifests.ts @@ -1,37 +1,37 @@ -// import { UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../../entity.js'; -// import { UmbDocumentBlueprintFolderRepository } from './document-blueprint-folder.repository.js'; -// import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../../entity.js'; +import { UmbDocumentBlueprintFolderRepository } from './document-blueprint-folder.repository.js'; +import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -// export const UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS = 'Umb.Repository.DocumentBlueprint.Folder'; +export const UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS = 'Umb.Repository.DocumentBlueprint.Folder'; -// const folderRepository: ManifestRepository = { -// type: 'repository', -// alias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS, -// name: 'Document Blueprint Folder Repository', -// api: UmbDocumentBlueprintFolderRepository, -// }; +const folderRepository: ManifestRepository = { + type: 'repository', + alias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS, + name: 'Document Blueprint Folder Repository', + api: UmbDocumentBlueprintFolderRepository, +}; -// const entityActions: Array = [ -// { -// type: 'entityAction', -// kind: 'folderUpdate', -// alias: 'Umb.EntityAction.DocumentBlueprint.Folder.Rename', -// name: 'Rename Document Blueprint Folder Entity Action', -// forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE], -// meta: { -// folderRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS, -// }, -// }, -// { -// type: 'entityAction', -// kind: 'folderDelete', -// alias: 'Umb.EntityAction.DocumentBlueprint.Folder.Delete', -// name: 'Delete Document Blueprint Folder Entity Action', -// forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE], -// meta: { -// folderRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS, -// }, -// }, -// ]; +const entityActions: Array = [ + { + type: 'entityAction', + kind: 'folderUpdate', + alias: 'Umb.EntityAction.DocumentBlueprint.Folder.Rename', + name: 'Rename Document Blueprint Folder Entity Action', + forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE], + meta: { + folderRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS, + }, + }, + { + type: 'entityAction', + kind: 'folderDelete', + alias: 'Umb.EntityAction.DocumentBlueprint.Folder.Delete', + name: 'Delete Document Blueprint Folder Entity Action', + forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE], + meta: { + folderRepositoryAlias: UMB_DOCUMENT_BLUEPRINT_FOLDER_REPOSITORY_ALIAS, + }, + }, +]; -// export const manifests = [folderRepository, ...entityActions]; +export const manifests = [folderRepository, ...entityActions]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/types.ts index e29ea4ff3b..dd70703d94 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/types.ts @@ -1,6 +1,6 @@ -// import type { UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../../entity.js'; -// import type { UmbDocumentBlueprintTreeItemModel } from '../types.js'; +import type { UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../../entity.js'; +import type { UmbDocumentBlueprintTreeItemModel } from '../types.js'; -// export interface UmbDocumentBlueprintFolderTreeItemModel extends UmbDocumentBlueprintTreeItemModel { -// entityType: typeof UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE; -// } +export interface UmbDocumentBlueprintFolderTreeItemModel extends UmbDocumentBlueprintTreeItemModel { + entityType: typeof UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts index 9f2a67da2f..f098c0956c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/index.ts @@ -1,2 +1,2 @@ export { UMB_DOCUMENT_BLUEPRINT_TREE_STORE_CONTEXT } from './document-blueprint-tree.store.js'; -//export * from './folder/index.js'; +export * from './folder/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/manifests.ts index 1a085f7d96..f7c4a07d3e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/manifests.ts @@ -1,5 +1,5 @@ import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE, UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../entity.js'; -//import { manifests as folderManifests } from './folder/manifests.js'; +import { manifests as folderManifests } from './folder/manifests.js'; import { manifests as reloadManifests } from './reload-tree-item-children/manifests.js'; import { UmbDocumentBlueprintTreeRepository } from './document-blueprint-tree.repository.js'; import { UmbDocumentBlueprintTreeStore } from './document-blueprint-tree.store.js'; @@ -46,5 +46,4 @@ const treeItem: ManifestTreeItem = { forEntityTypes: [UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE, UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE], }; -export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadManifests]; -//...folderManifests, +export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadManifests, ...folderManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts index 9387350ca2..927a0bc4d7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts @@ -19,8 +19,6 @@ export class UmbDocumentBlueprintWorkspaceEditorElement extends UmbLitElement { constructor() { super(); - console.log('editor'); - this.consumeContext(UMB_DOCUMENT_BLUEPRINT_WORKSPACE_CONTEXT, (instance) => { this.#workspaceContext = instance; this.#observeVariants(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-split-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-split-view.element.ts index 5f8842615b..0744a49972 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-split-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-split-view.element.ts @@ -15,8 +15,6 @@ export class UmbDocumentBlueprintWorkspaceSplitViewElement extends UmbLitElement constructor() { super(); - console.log('split view'); - // TODO: Refactor: use a split view workspace context token: this.consumeContext(UMB_DOCUMENT_BLUEPRINT_WORKSPACE_CONTEXT, (context) => { this._workspaceContext = context; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/manifests.ts index ce0e502d8b..0c300d0386 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/manifests.ts @@ -1,40 +1,28 @@ +import { UMB_DOCUMENT_TYPE_ENTITY_TYPE } from '../entity.js'; import { DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS, DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS } from '../repository/index.js'; import { manifests as createManifests } from './create/manifests.js'; +import { manifests as moveManifests } from './move-to/manifests.js'; import { UMB_DOCUMENT_TYPE_PICKER_MODAL } from '@umbraco-cms/backoffice/document-type'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -const entityType = 'document-type'; - const entityActions: Array = [ { type: 'entityAction', kind: 'delete', alias: 'Umb.EntityAction.DocumentType.Delete', name: 'Delete Document-Type Entity Action', - forEntityTypes: [entityType], + forEntityTypes: [UMB_DOCUMENT_TYPE_ENTITY_TYPE], meta: { itemRepositoryAlias: DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS, detailRepositoryAlias: DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS, }, }, - { - type: 'entityAction', - kind: 'move', - alias: 'Umb.EntityAction.DocumentType.Move', - name: 'Move Document Type Entity Action', - forEntityTypes: [entityType], - meta: { - itemRepositoryAlias: DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS, - moveRepositoryAlias: DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS, - pickerModal: UMB_DOCUMENT_TYPE_PICKER_MODAL, - }, - }, { type: 'entityAction', kind: 'duplicate', alias: 'Umb.EntityAction.DocumentType.Duplicate', name: 'Duplicate Document Type Entity Action', - forEntityTypes: [entityType], + forEntityTypes: [UMB_DOCUMENT_TYPE_ENTITY_TYPE], meta: { itemRepositoryAlias: DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS, duplicateRepositoryAlias: DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS, @@ -43,4 +31,4 @@ const entityActions: Array = [ }, ]; -export const manifests = [...entityActions, ...createManifests]; +export const manifests = [...entityActions, ...createManifests, ...moveManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/index.ts new file mode 100644 index 0000000000..6452336803 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/index.ts @@ -0,0 +1 @@ +export { UmbMoveDocumentTypeRepository, UMB_MOVE_DOCUMENT_TYPE_REPOSITORY_ALIAS } from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/manifests.ts new file mode 100644 index 0000000000..0258c013f1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/manifests.ts @@ -0,0 +1,23 @@ +import { UMB_DOCUMENT_TYPE_ENTITY_TYPE } from '../../entity.js'; +import { UMB_DOCUMENT_TYPE_TREE_REPOSITORY_ALIAS } from '../../tree/index.js'; +import { UMB_DOCUMENT_TYPE_TREE_ALIAS } from '../../tree/manifests.js'; +import { UMB_MOVE_DOCUMENT_TYPE_REPOSITORY_ALIAS } from './repository/index.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +const entityActions: Array = [ + { + type: 'entityAction', + kind: 'moveTo', + alias: 'Umb.EntityAction.DocumentType.MoveTo', + name: 'Move Document Type Entity Action', + forEntityTypes: [UMB_DOCUMENT_TYPE_ENTITY_TYPE], + meta: { + treeRepositoryAlias: UMB_DOCUMENT_TYPE_TREE_REPOSITORY_ALIAS, + moveRepositoryAlias: UMB_MOVE_DOCUMENT_TYPE_REPOSITORY_ALIAS, + treeAlias: UMB_DOCUMENT_TYPE_TREE_ALIAS, + }, + }, +]; + +export const manifests = [...entityActions, ...repositoryManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/constants.ts new file mode 100644 index 0000000000..aedccd9db2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/constants.ts @@ -0,0 +1 @@ +export const UMB_MOVE_DOCUMENT_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DocumentType.Move'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/document-type-move.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/document-type-move.repository.ts new file mode 100644 index 0000000000..ed5b207812 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/document-type-move.repository.ts @@ -0,0 +1,20 @@ +import { UmbMoveDocumentTypeServerDataSource } from './document-type-move.server.data-source.js'; +import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; +import type { UmbMoveRepository, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-action'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +export class UmbMoveDocumentTypeRepository extends UmbRepositoryBase implements UmbMoveRepository { + #moveSource = new UmbMoveDocumentTypeServerDataSource(this); + + async requestMoveTo(args: UmbMoveToRequestArgs) { + const { error } = await this.#moveSource.moveTo(args); + + if (!error) { + const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT); + const notification = { data: { message: `Moved` } }; + notificationContext.peek('positive', notification); + } + + return { error }; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/document-type-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/document-type-move.server.data-source.ts new file mode 100644 index 0000000000..4b82d9e18d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/document-type-move.server.data-source.ts @@ -0,0 +1,44 @@ +import { DocumentTypeService } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import type { UmbMoveDataSource, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-action'; + +/** + * Move DocumentType Server Data Source + * @export + * @class UmbMoveDocumentTypeServerDataSource + */ +export class UmbMoveDocumentTypeServerDataSource implements UmbMoveDataSource { + #host: UmbControllerHost; + + /** + * Creates an instance of UmbMoveDocumentTypeServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbMoveDocumentTypeServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Move an item for the given id to the target unique + * @param {string} unique + * @param {(string | null)} targetUnique + * @return {*} + * @memberof UmbMoveDocumentTypeServerDataSource + */ + async moveTo(args: UmbMoveToRequestArgs) { + if (!args.unique) throw new Error('Unique is missing'); + if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); + + return tryExecuteAndNotify( + this.#host, + DocumentTypeService.putDocumentTypeByIdMove({ + id: args.unique, + requestBody: { + target: args.destination.unique ? { id: args.destination.unique } : null, + }, + }), + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/index.ts new file mode 100644 index 0000000000..d9cadf133f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/index.ts @@ -0,0 +1,2 @@ +export { UmbMoveDocumentTypeRepository } from './document-type-move.repository.js'; +export { UMB_MOVE_DOCUMENT_TYPE_REPOSITORY_ALIAS } from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/manifests.ts new file mode 100644 index 0000000000..e4e3226bb9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/manifests.ts @@ -0,0 +1,12 @@ +import { UMB_MOVE_DOCUMENT_TYPE_REPOSITORY_ALIAS } from './constants.js'; +import { UmbMoveDocumentTypeRepository } from './document-type-move.repository.js'; +import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +const moveRepository: ManifestRepository = { + type: 'repository', + alias: UMB_MOVE_DOCUMENT_TYPE_REPOSITORY_ALIAS, + name: 'Move Document Type Repository', + api: UmbMoveDocumentTypeRepository, +}; + +export const manifests = [moveRepository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts index b607f833ea..b9ff521986 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts @@ -1,14 +1,18 @@ -import { UmbModalToken } from '../../../core/modal/token/modal-token.js'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; import type { UmbDocumentTypeTreeItemModel } from '@umbraco-cms/backoffice/document-type'; -import type { UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal'; +import { + type UmbTreePickerModalValue, + type UmbTreePickerModalData, + UMB_TREE_PICKER_MODAL_ALIAS, +} from '@umbraco-cms/backoffice/tree'; export type UmbDocumentTypePickerModalData = UmbTreePickerModalData; -export type UmbDocumentTypePickerModalValue = UmbPickerModalValue; +export type UmbDocumentTypePickerModalValue = UmbTreePickerModalValue; export const UMB_DOCUMENT_TYPE_PICKER_MODAL = new UmbModalToken< UmbDocumentTypePickerModalData, UmbDocumentTypePickerModalValue ->('Umb.Modal.TreePicker', { +>(UMB_TREE_PICKER_MODAL_ALIAS, { modal: { type: 'sidebar', size: 'small', diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts index 1cbcd24750..6782b20ccd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts @@ -1,8 +1,8 @@ import { UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT } from './document-type-workspace.context-token.js'; +import { umbFocus, UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_MODAL_MANAGER_CONTEXT, UMB_ICON_PICKER_MODAL } from '@umbraco-cms/backoffice/modal'; import { generateAlias } from '@umbraco-cms/backoffice/utils'; @customElement('umb-document-type-workspace-editor') @@ -35,18 +35,6 @@ export class UmbDocumentTypeWorkspaceEditorElement extends UmbLitElement { this.observe(this.#workspaceContext.name, (name) => (this._name = name), '_observeName'); this.observe(this.#workspaceContext.alias, (alias) => (this._alias = alias), '_observeAlias'); this.observe(this.#workspaceContext.icon, (icon) => (this._icon = icon), '_observeIcon'); - - this.observe( - this.#workspaceContext.isNew, - (isNew) => { - if (isNew) { - // TODO: Would be good with a more general way to bring focus to the name input. - (this.shadowRoot?.querySelector('#name') as HTMLElement)?.focus(); - } - this.removeUmbControllerByAlias('isNewRedirectController'); - }, - '_observeIsNew', - ); } // TODO. find a way where we don't have to do this for all workspaces. @@ -113,7 +101,7 @@ export class UmbDocumentTypeWorkspaceEditorElement extends UmbLitElement { - + { - #repository = new UmbDocumentBlueprintDetailRepository(this); + #repository = new UmbDocumentCreateBlueprintRepository(this); constructor(host: UmbControllerHost, args: UmbEntityActionArgs) { super(host, args); } async execute() { + if (!this.args.unique) throw new Error('Unique is required'); + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); const modalContext = modalManager.open(this, UMB_CREATE_BLUEPRINT_MODAL, { data: { unique: this.args.unique }, }); await modalContext.onSubmit().catch(() => undefined); + + const { name, parent } = modalContext.getValue(); + if (!name) return; + + await this.#repository.create({ name, parent, document: { id: this.args.unique } }); } } export default UmbCreateDocumentBlueprintEntityAction; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/index.ts index 28d9f38fba..e130217e61 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/index.ts @@ -1 +1,2 @@ export * from './modal/index.js'; +export * from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/modal/create-blueprint-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/modal/create-blueprint-modal.element.ts index b099cb20af..8b7aa230a5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/modal/create-blueprint-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/modal/create-blueprint-modal.element.ts @@ -1,19 +1,16 @@ import { UmbDocumentDetailRepository } from '../../../repository/index.js'; -import type { UmbCreateBlueprintModalData } from './create-blueprint-modal.token.js'; +import type { UmbCreateBlueprintModalData, UmbCreateBlueprintModalValue } from './create-blueprint-modal.token.js'; import { html, customElement, css, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import type { UmbDocumentDetailModel } from '@umbraco-cms/backoffice/document'; -import { - type UmbDocumentBlueprintDetailModel, - UmbDocumentBlueprintDetailRepository, -} from '@umbraco-cms/backoffice/document-blueprint'; import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; -import { UmbId } from '@umbraco-cms/backoffice/id'; @customElement('umb-create-blueprint-modal') -export class UmbCreateBlueprintModalElement extends UmbModalBaseElement { - #blueprintRepository = new UmbDocumentBlueprintDetailRepository(this); +export class UmbCreateBlueprintModalElement extends UmbModalBaseElement< + UmbCreateBlueprintModalData, + UmbCreateBlueprintModalValue +> { #documentRepository = new UmbDocumentDetailRepository(this); #documentUnique = ''; @@ -39,24 +36,8 @@ export class UmbCreateBlueprintModalElement extends UmbModalBaseElement ({ ...variant, name: this._blueprintName })); - const model: UmbDocumentBlueprintDetailModel = { - ...this.#document, - entityType: 'document-blueprint', - variants, - unique: UmbId.new(), - }; - - return model; - } - async #handleSave() { - const model = this.#mapDocumentToBlueprintModel(); - if (!model) return; - const { error } = await this.#blueprintRepository.create(model, null); - console.log('error', error); + this.value = { name: this._blueprintName, parent: null }; this.modalContext?.submit(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/modal/create-blueprint-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/modal/create-blueprint-modal.token.ts index dbd009afca..2001558eb1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/modal/create-blueprint-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/modal/create-blueprint-modal.token.ts @@ -1,10 +1,16 @@ +import type { ReferenceByIdModel } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbCreateBlueprintModalData { unique: string | null; } -export const UMB_CREATE_BLUEPRINT_MODAL = new UmbModalToken( +export interface UmbCreateBlueprintModalValue { + name: string; + parent: ReferenceByIdModel | null; +} + +export const UMB_CREATE_BLUEPRINT_MODAL = new UmbModalToken( 'Umb.Modal.CreateBlueprint', { modal: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/document-create-blueprint.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/document-create-blueprint.repository.ts new file mode 100644 index 0000000000..99ca0352ff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/document-create-blueprint.repository.ts @@ -0,0 +1,32 @@ +import { UmbDocumentCreateBlueprintServerDataSource } from './document-create-blueprint.server.data-source.js'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; +import type { CreateDocumentBlueprintFromDocumentRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +export class UmbDocumentCreateBlueprintRepository extends UmbControllerBase implements UmbApi { + #dataSource = new UmbDocumentCreateBlueprintServerDataSource(this); + + #notificationContext?: typeof UMB_NOTIFICATION_CONTEXT.TYPE; + + constructor(host: UmbControllerHost) { + super(host); + + this.consumeContext(UMB_NOTIFICATION_CONTEXT, (instance) => { + this.#notificationContext = instance; + }); + } + + async create(requestBody: CreateDocumentBlueprintFromDocumentRequestModel) { + const { data, error } = await this.#dataSource.create(requestBody); + if (!error) { + const notification = { data: { message: `Document Blueprint created` } }; + this.#notificationContext!.peek('positive', notification); + + return { data }; + } + + return { error }; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/document-create-blueprint.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/document-create-blueprint.server.data-source.ts new file mode 100644 index 0000000000..e0551eb81b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/document-create-blueprint.server.data-source.ts @@ -0,0 +1,32 @@ +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { DocumentBlueprintService } from '@umbraco-cms/backoffice/external/backend-api'; +import type { CreateDocumentBlueprintFromDocumentRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +/** + * A data source for the Document Create Blueprint that fetches data from the server + * @export + * @class UmbDocumentCreateBlueprintServerDataSource + * @implements {RepositoryDetailDataSource} + */ +export class UmbDocumentCreateBlueprintServerDataSource { + #host: UmbControllerHost; + + /** + * Creates an instance of UmbDocumentCreateBlueprintServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbDocumentCreateBlueprintServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Fetches the Culture and Hostnames for the given Document unique + * @param {string} unique + * @memberof UmbDocumentCreateBlueprintServerDataSource + */ + async create(requestBody: CreateDocumentBlueprintFromDocumentRequestModel) { + return tryExecuteAndNotify(this.#host, DocumentBlueprintService.postDocumentBlueprintFromDocument({ requestBody })); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/index.ts new file mode 100644 index 0000000000..7e8dcb93a2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/index.ts @@ -0,0 +1,2 @@ +export { UmbDocumentCreateBlueprintRepository } from './document-create-blueprint.repository.js'; +export { UMB_DOCUMENT_CREATE_BLUEPRINT_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/manifests.ts new file mode 100644 index 0000000000..f5635547e6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/manifests.ts @@ -0,0 +1,13 @@ +import { UmbDocumentCreateBlueprintRepository } from './document-create-blueprint.repository.js'; +import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +export const UMB_DOCUMENT_CREATE_BLUEPRINT_REPOSITORY_ALIAS = 'Umb.Repository.Document.CreateBlueprint'; + +const repository: ManifestRepository = { + type: 'repository', + alias: UMB_DOCUMENT_CREATE_BLUEPRINT_REPOSITORY_ALIAS, + name: 'Document Create Blueprint Repository', + api: UmbDocumentCreateBlueprintRepository, +}; + +export const manifests = [repository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts index 6f0a2d5e7b..eb4361a1ec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts @@ -3,13 +3,17 @@ import type { UmbDocumentCreateOptionsModalData, UmbDocumentCreateOptionsModalValue, } from './document-create-options-modal.token.js'; -import { html, nothing, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { html, nothing, customElement, state, ifDefined, repeat, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UmbDocumentTypeStructureRepository, type UmbAllowedDocumentTypeModel, } from '@umbraco-cms/backoffice/document-type'; +import { + type UmbDocumentBlueprintItemModel, + UmbDocumentBlueprintItemRepository, +} from '@umbraco-cms/backoffice/document-blueprint'; @customElement('umb-document-create-options-modal') export class UmbDocumentCreateOptionsModalElement extends UmbModalBaseElement< @@ -18,12 +22,20 @@ export class UmbDocumentCreateOptionsModalElement extends UmbModalBaseElement< > { #documentTypeStructureRepository = new UmbDocumentTypeStructureRepository(this); #documentItemRepository = new UmbDocumentItemRepository(this); + #documentBlueprintItemRepository = new UmbDocumentBlueprintItemRepository(this); + + #documentTypeUnique = ''; + #documentTypeIcon = ''; @state() private _allowedDocumentTypes: UmbAllowedDocumentTypeModel[] = []; @state() - private _headline: string = 'Create'; + private _headline: string = + `${this.localize.term('create_createUnder')} ${this.localize.term('actionCategories_content')}`; + + @state() + private _availableBlueprints: Array = []; async firstUpdated() { const parentUnique = this.data?.parent.unique; @@ -50,40 +62,100 @@ export class UmbDocumentCreateOptionsModalElement extends UmbModalBaseElement< const { data } = await this.#documentItemRepository.requestItems([parentUnique]); if (data) { // TODO: we need to get the correct variant context here - this._headline = `Create at ${data[0].variants?.[0].name}`; + this._headline = `${this.localize.term('create_createUnder')} ${data[0].variants?.[0].name ?? this.localize.term('actionCategories_content')}`; } } // close the modal when navigating to data type - #onNavigate() { + #onNavigate(documentTypeUnique: string, blueprintUnique?: string) { + if (!blueprintUnique) { + history.pushState( + null, + '', + `section/content/workspace/document/create/parent/${this.data?.parent.entityType}/${this.data?.parent.unique ?? 'null'}/${documentTypeUnique}`, + ); + } else { + history.pushState( + null, + '', + `section/content/workspace/document/create/parent/${this.data?.parent.entityType}/${this.data?.parent.unique ?? 'null'}/${documentTypeUnique}/${blueprintUnique}`, + ); + } this._submitModal(); } + async #onSelectDocumentType(documentTypeUnique: string) { + this.#documentTypeUnique = documentTypeUnique; + this.#documentTypeIcon = this._allowedDocumentTypes.find((dt) => dt.unique === documentTypeUnique)?.icon ?? ''; + + /** TODO: Fix this to use the correct endpoint when it becomes available */ + const { data } = await this.#documentBlueprintItemRepository.requestItems([]); + if (!data?.length) return; + + this._availableBlueprints = data.filter((blueprint) => blueprint.documentType.unique === documentTypeUnique); + + if (!this._availableBlueprints.length) { + this.#onNavigate(documentTypeUnique); + return; + } + } + render() { return html` - - - ${this._allowedDocumentTypes.length === 0 ? html`

No allowed types

` : nothing} - ${this._allowedDocumentTypes.map( - (documentType) => html` - - > ${documentType.icon ? html`` : nothing} - - `, - )} -
+ + ${this._availableBlueprints.length && this.#documentTypeUnique + ? this.#renderBlueprints() + : this.#renderDocumentTypes()} `; } - static styles = [UmbTextStyles]; + #renderDocumentTypes() { + return html` + ${this._allowedDocumentTypes.length === 0 ? html`

No allowed types

` : nothing} + ${this._allowedDocumentTypes.map( + (documentType) => html` + this.#onSelectDocumentType(documentType.unique)}> + + + `, + )} +
`; + } + + #renderBlueprints() { + return html` + this.#onNavigate(this.#documentTypeUnique)}> + + + ${repeat( + this._availableBlueprints, + (blueprint) => blueprint.unique, + (blueprint) => + html` this.#onNavigate(this.#documentTypeUnique, blueprint.unique)}> + + `, + )} `; + } + + static styles = [ + UmbTextStyles, + css` + #blank { + border-bottom: 1px solid var(--uui-color-border); + } + `, + ]; } export default UmbDocumentCreateOptionsModalElement; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts index 8d0ab6f62c..7c40e92a1d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts @@ -4,7 +4,6 @@ import { UMB_DOCUMENT_PICKER_MODAL } from '../modals/index.js'; import { UMB_USER_PERMISSION_DOCUMENT_DELETE, UMB_USER_PERMISSION_DOCUMENT_DUPLICATE, - UMB_USER_PERMISSION_DOCUMENT_MOVE, UMB_USER_PERMISSION_DOCUMENT_NOTIFICATIONS, UMB_USER_PERMISSION_DOCUMENT_PERMISSIONS, UMB_USER_PERMISSION_DOCUMENT_PUBLISH, @@ -15,6 +14,7 @@ import { manifests as createBlueprintManifests } from './create-blueprint/manife import { manifests as publicAccessManifests } from './public-access/manifests.js'; import { manifests as cultureAndHostnamesManifests } from './culture-and-hostnames/manifests.js'; import { manifests as sortChildrenOfManifests } from './sort-children-of/manifests.js'; +import { manifests as moveManifests } from './move-to/manifests.js'; import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; const entityActions: Array = [ @@ -35,25 +35,6 @@ const entityActions: Array = [ }, ], }, - { - type: 'entityAction', - alias: 'Umb.EntityAction.Document.Move', - name: 'Move Document Entity Action ', - kind: 'move', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - weight: 900, - meta: { - moveRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, - itemRepositoryAlias: UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, - pickerModelAlias: UMB_DOCUMENT_PICKER_MODAL, - }, - conditions: [ - { - alias: 'Umb.Condition.UserPermission.Document', - allOf: [UMB_USER_PERMISSION_DOCUMENT_MOVE], - }, - ], - }, { type: 'entityAction', kind: 'duplicate', @@ -157,5 +138,6 @@ export const manifests = [ ...publicAccessManifests, ...cultureAndHostnamesManifests, ...sortChildrenOfManifests, + ...moveManifests, ...entityActions, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/index.ts new file mode 100644 index 0000000000..6a8cb43962 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/index.ts @@ -0,0 +1 @@ +export { UmbMoveDocumentRepository, UMB_MOVE_DOCUMENT_REPOSITORY_ALIAS } from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/manifests.ts new file mode 100644 index 0000000000..fd970dc6ed --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/manifests.ts @@ -0,0 +1,29 @@ +import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; +import { UMB_DOCUMENT_TREE_ALIAS, UMB_DOCUMENT_TREE_REPOSITORY_ALIAS } from '../../tree/index.js'; +import { UMB_USER_PERMISSION_DOCUMENT_MOVE } from '../../user-permissions/constants.js'; +import { UMB_MOVE_DOCUMENT_REPOSITORY_ALIAS } from './repository/index.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +const entityActions: Array = [ + { + type: 'entityAction', + kind: 'moveTo', + alias: 'Umb.EntityAction.Document.MoveTo', + name: 'Move Document Entity Action', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + treeRepositoryAlias: UMB_DOCUMENT_TREE_REPOSITORY_ALIAS, + moveRepositoryAlias: UMB_MOVE_DOCUMENT_REPOSITORY_ALIAS, + treeAlias: UMB_DOCUMENT_TREE_ALIAS, + }, + conditions: [ + { + alias: 'Umb.Condition.UserPermission.Document', + allOf: [UMB_USER_PERMISSION_DOCUMENT_MOVE], + }, + ], + }, +]; + +export const manifests = [...entityActions, ...repositoryManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/constants.ts new file mode 100644 index 0000000000..a3f4f36752 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/constants.ts @@ -0,0 +1 @@ +export const UMB_MOVE_DOCUMENT_REPOSITORY_ALIAS = 'Umb.Repository.Document.Move'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/document-move.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/document-move.repository.ts new file mode 100644 index 0000000000..4248878930 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/document-move.repository.ts @@ -0,0 +1,20 @@ +import { UmbMoveDocumentServerDataSource } from './document-move.server.data-source.js'; +import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; +import type { UmbMoveRepository, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-action'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +export class UmbMoveDocumentRepository extends UmbRepositoryBase implements UmbMoveRepository { + #moveSource = new UmbMoveDocumentServerDataSource(this); + + async requestMoveTo(args: UmbMoveToRequestArgs) { + const { error } = await this.#moveSource.moveTo(args); + + if (!error) { + const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT); + const notification = { data: { message: `Moved` } }; + notificationContext.peek('positive', notification); + } + + return { error }; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/document-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/document-move.server.data-source.ts new file mode 100644 index 0000000000..e59c817d23 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/document-move.server.data-source.ts @@ -0,0 +1,44 @@ +import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import type { UmbMoveDataSource, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-action'; + +/** + * Move Document Server Data Source + * @export + * @class UmbMoveDocumentServerDataSource + */ +export class UmbMoveDocumentServerDataSource implements UmbMoveDataSource { + #host: UmbControllerHost; + + /** + * Creates an instance of UmbMoveDocumentServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbMoveDocumentServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Move an item for the given id to the target unique + * @param {string} unique + * @param {(string | null)} targetUnique + * @return {*} + * @memberof UmbMoveDocumentServerDataSource + */ + async moveTo(args: UmbMoveToRequestArgs) { + if (!args.unique) throw new Error('Unique is missing'); + if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); + + return tryExecuteAndNotify( + this.#host, + DocumentService.putDocumentByIdMove({ + id: args.unique, + requestBody: { + target: args.destination.unique ? { id: args.destination.unique } : null, + }, + }), + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/index.ts new file mode 100644 index 0000000000..3b95bc5269 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/index.ts @@ -0,0 +1,2 @@ +export { UmbMoveDocumentRepository } from './document-move.repository.js'; +export { UMB_MOVE_DOCUMENT_REPOSITORY_ALIAS } from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/manifests.ts new file mode 100644 index 0000000000..3258fe31a1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/manifests.ts @@ -0,0 +1,12 @@ +import { UMB_MOVE_DOCUMENT_REPOSITORY_ALIAS } from './constants.js'; +import { UmbMoveDocumentRepository } from './document-move.repository.js'; +import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +const moveRepository: ManifestRepository = { + type: 'repository', + alias: UMB_MOVE_DOCUMENT_REPOSITORY_ALIAS, + name: 'Move Document Repository', + api: UmbMoveDocumentRepository, +}; + +export const manifests = [moveRepository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-bulk-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-bulk-actions/manifests.ts index a509f88957..0c6940f22b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-bulk-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-bulk-actions/manifests.ts @@ -82,7 +82,7 @@ export const manifests: Array = [ { type: 'entityBulkAction', kind: 'default', - alias: 'Umb.EntityBulkAction.Document.Move', + alias: 'Umb.EntityBulkAction.Document.MoveTo', name: 'Move Document Entity Bulk Action', weight: 20, api: UmbMoveDocumentEntityBulkAction, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/document-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/document-picker-modal.token.ts index 9e04756f58..b244d4093a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/document-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/document-picker-modal.token.ts @@ -1,12 +1,16 @@ import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; -import type { UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal'; +import { + type UmbTreePickerModalValue, + type UmbTreePickerModalData, + UMB_TREE_PICKER_MODAL_ALIAS, +} from '@umbraco-cms/backoffice/tree'; import type { UmbDocumentItemModel } from '@umbraco-cms/backoffice/document'; export type UmbDocumentPickerModalData = UmbTreePickerModalData; -export type UmbDocumentPickerModalValue = UmbPickerModalValue; +export type UmbDocumentPickerModalValue = UmbTreePickerModalValue; export const UMB_DOCUMENT_PICKER_MODAL = new UmbModalToken( - 'Umb.Modal.TreePicker', + UMB_TREE_PICKER_MODAL_ALIAS, { modal: { type: 'sidebar', diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index 1ab4c387a1..25d4dc6469 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -48,6 +48,7 @@ import { UmbRequestReloadTreeItemChildrenEvent } from '@umbraco-cms/backoffice/t import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/entity-action'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { UmbDocumentTypeDetailModel } from '@umbraco-cms/backoffice/document-type'; +import { UmbDocumentBlueprintDetailRepository } from '@umbraco-cms/backoffice/document-blueprint'; type EntityType = UmbDocumentDetailModel; export class UmbDocumentWorkspaceContext @@ -75,6 +76,10 @@ export class UmbDocumentWorkspaceContext #languages = new UmbArrayState([], (x) => x.unique); public readonly languages = this.#languages.asObservable(); + #blueprintRepository = new UmbDocumentBlueprintDetailRepository(this); + /*#blueprint = new UmbObjectState(undefined); + public readonly blueprint = this.#blueprint.asObservable();*/ + public isLoaded() { return this.#getDataPromise; } @@ -145,6 +150,24 @@ export class UmbDocumentWorkspaceContext this.loadLanguages(); this.routes.setRoutes([ + { + path: 'create/parent/:entityType/:parentUnique/:documentTypeUnique/:blueprintUnique', + component: () => import('./document-workspace-editor.element.js'), + setup: async (_component, info) => { + const parentEntityType = info.match.params.entityType; + const parentUnique: string | null = + info.match.params.parentUnique === 'null' ? null : info.match.params.parentUnique; + const documentTypeUnique = info.match.params.documentTypeUnique; + const blueprintUnique = info.match.params.blueprintUnique; + + this.create({ entityType: parentEntityType, unique: parentUnique }, documentTypeUnique, blueprintUnique); + new UmbWorkspaceIsNewRedirectController( + this, + this, + this.getHostElement().shadowRoot!.querySelector('umb-router-slot')!, + ); + }, + }, { path: 'create/parent/:entityType/:parentUnique/:documentTypeUnique', component: () => import('./document-workspace-editor.element.js'), @@ -208,15 +231,32 @@ export class UmbDocumentWorkspaceContext } } - async create(parent: { entityType: string; unique: string | null }, documentTypeUnique: string) { + async create( + parent: { entityType: string; unique: string | null }, + documentTypeUnique: string, + blueprintUnique?: string, + ) { this.resetState(); this.#parent.setValue(parent); - this.#getDataPromise = this.repository.createScaffold({ - documentType: { - unique: documentTypeUnique, - collection: null, - }, - }); + + /**TODO Explore bug: A way to make blueprintUnique undefined/null when no unique is given, rather than setting it to invariant */ + if (blueprintUnique && blueprintUnique.toLowerCase() !== 'invariant') { + const { data } = await this.#blueprintRepository.requestByUnique(blueprintUnique); + console.log(data); + this.#getDataPromise = this.repository.createScaffold({ + documentType: data?.documentType, + values: data?.values, + variants: data?.variants as Array, + }); + } else { + this.#getDataPromise = this.repository.createScaffold({ + documentType: { + unique: documentTypeUnique, + collection: null, + }, + }); + } + const { data } = await this.#getDataPromise; if (!data) return undefined; diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace-editor.element.ts index 2648fd0d73..fa5bc5f053 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace-editor.element.ts @@ -3,7 +3,7 @@ import { UMB_LANGUAGE_WORKSPACE_CONTEXT } from './language-workspace.context-tok import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @customElement('umb-language-workspace-editor') export class UmbLanguageWorkspaceEditorElement extends UmbLitElement { @@ -55,7 +55,8 @@ export class UmbLanguageWorkspaceEditorElement extends UmbLitElement { : html``} + @input="${this.#handleInput}" + ${umbFocus()}>
`} `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.element.ts b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.element.ts index e8b1c14f3d..e525c752b5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.element.ts @@ -8,13 +8,10 @@ import { UUIFormControlMixin, type UUIModalSidebarSize } from '@umbraco-cms/back import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; -import { - UMB_LINK_PICKER_MODAL, - UMB_MEDIA_TREE_PICKER_MODAL, - UMB_MODAL_MANAGER_CONTEXT, -} from '@umbraco-cms/backoffice/modal'; +import { UMB_LINK_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { UMB_APP_CONTEXT } from '@umbraco-cms/backoffice/app'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UMB_MEDIA_TREE_PICKER_MODAL } from '@umbraco-cms/backoffice/media'; /** * @element umb-input-markdown diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/input-media-type/input-media-type.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/input-media-type/input-media-type.context.ts index 403e692a92..dfe3fea1f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/input-media-type/input-media-type.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/input-media-type/input-media-type.context.ts @@ -1,8 +1,8 @@ import type { UmbMediaTypeItemModel } from '../../repository/index.js'; import { UMB_MEDIA_TYPE_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js'; +import { UMB_MEDIA_TYPE_PICKER_MODAL } from '../../tree/media-type-picker-modal.token.js'; import { UmbPickerInputContext } from '@umbraco-cms/backoffice/picker-input'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UMB_MEDIA_TYPE_PICKER_MODAL } from '@umbraco-cms/backoffice/modal'; export class UmbMediaTypePickerContext extends UmbPickerInputContext { constructor(host: UmbControllerHost) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/manifests.ts index c80d3fead0..f6eda92df5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/manifests.ts @@ -1,22 +1,11 @@ import { UMB_MEDIA_TYPE_ENTITY_TYPE } from '../entity.js'; import { UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS, UMB_MEDIA_TYPE_ITEM_REPOSITORY_ALIAS } from '../repository/index.js'; +import { UMB_MEDIA_TYPE_PICKER_MODAL } from '../tree/index.js'; import { manifests as createManifests } from './create/manifests.js'; -import { UMB_MEDIA_TREE_PICKER_MODAL } from '@umbraco-cms/backoffice/modal'; +import { manifests as moveManifests } from './move-to/manifests.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; const entityActions: Array = [ - { - type: 'entityAction', - kind: 'move', - alias: 'Umb.EntityAction.MediaType.Move', - name: 'Move Media Type Entity Action', - forEntityTypes: [UMB_MEDIA_TYPE_ENTITY_TYPE], - meta: { - moveRepositoryAlias: UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS, - itemRepositoryAlias: UMB_MEDIA_TYPE_ITEM_REPOSITORY_ALIAS, - pickerModal: UMB_MEDIA_TREE_PICKER_MODAL, - }, - }, { type: 'entityAction', kind: 'duplicate', @@ -26,7 +15,7 @@ const entityActions: Array = [ meta: { duplicateRepositoryAlias: UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS, itemRepositoryAlias: UMB_MEDIA_TYPE_ITEM_REPOSITORY_ALIAS, - pickerModal: UMB_MEDIA_TREE_PICKER_MODAL, + pickerModal: UMB_MEDIA_TYPE_PICKER_MODAL, }, }, { @@ -42,4 +31,4 @@ const entityActions: Array = [ }, ]; -export const manifests = [...entityActions, ...createManifests]; +export const manifests = [...entityActions, ...createManifests, ...moveManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/index.ts new file mode 100644 index 0000000000..e16847c20f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/index.ts @@ -0,0 +1 @@ +export { UmbMoveMediaTypeRepository, UMB_MOVE_MEDIA_TYPE_REPOSITORY_ALIAS } from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/manifests.ts new file mode 100644 index 0000000000..7446965839 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/manifests.ts @@ -0,0 +1,22 @@ +import { UMB_MEDIA_TYPE_ENTITY_TYPE } from '../../entity.js'; +import { UMB_MEDIA_TYPE_TREE_REPOSITORY_ALIAS, UMB_MEDIA_TYPE_TREE_ALIAS } from '../../tree/index.js'; +import { UMB_MOVE_MEDIA_TYPE_REPOSITORY_ALIAS } from './repository/index.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +const entityActions: Array = [ + { + type: 'entityAction', + kind: 'moveTo', + alias: 'Umb.EntityAction.MediaType.MoveTo', + name: 'Move Media Type Entity Action', + forEntityTypes: [UMB_MEDIA_TYPE_ENTITY_TYPE], + meta: { + treeRepositoryAlias: UMB_MEDIA_TYPE_TREE_REPOSITORY_ALIAS, + moveRepositoryAlias: UMB_MOVE_MEDIA_TYPE_REPOSITORY_ALIAS, + treeAlias: UMB_MEDIA_TYPE_TREE_ALIAS, + }, + }, +]; + +export const manifests = [...entityActions, ...repositoryManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/constants.ts new file mode 100644 index 0000000000..0b1e0108cc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/constants.ts @@ -0,0 +1 @@ +export const UMB_MOVE_MEDIA_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.MediaType.Move'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/index.ts new file mode 100644 index 0000000000..d073d1bc98 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/index.ts @@ -0,0 +1,2 @@ +export { UmbMoveMediaTypeRepository } from './media-type-move.repository.js'; +export { UMB_MOVE_MEDIA_TYPE_REPOSITORY_ALIAS } from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/manifests.ts new file mode 100644 index 0000000000..6c9199a10e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/manifests.ts @@ -0,0 +1,12 @@ +import { UMB_MOVE_MEDIA_TYPE_REPOSITORY_ALIAS } from './constants.js'; +import { UmbMoveMediaTypeRepository } from './media-type-move.repository.js'; +import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +const moveRepository: ManifestRepository = { + type: 'repository', + alias: UMB_MOVE_MEDIA_TYPE_REPOSITORY_ALIAS, + name: 'Move Media Type Repository', + api: UmbMoveMediaTypeRepository, +}; + +export const manifests = [moveRepository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/media-type-move.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/media-type-move.repository.ts new file mode 100644 index 0000000000..62d92043f2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/media-type-move.repository.ts @@ -0,0 +1,20 @@ +import { UmbMoveMediaTypeServerDataSource } from './media-type-move.server.data-source.js'; +import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; +import type { UmbMoveRepository, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-action'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +export class UmbMoveMediaTypeRepository extends UmbRepositoryBase implements UmbMoveRepository { + #moveSource = new UmbMoveMediaTypeServerDataSource(this); + + async requestMoveTo(args: UmbMoveToRequestArgs) { + const { error } = await this.#moveSource.moveTo(args); + + if (!error) { + const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT); + const notification = { data: { message: `Moved` } }; + notificationContext.peek('positive', notification); + } + + return { error }; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/media-type-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/media-type-move.server.data-source.ts new file mode 100644 index 0000000000..5177c9bde2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/media-type-move.server.data-source.ts @@ -0,0 +1,44 @@ +import { MediaTypeService } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import type { UmbMoveDataSource, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-action'; + +/** + * Move Media Type Server Data Source + * @export + * @class UmbMoveMediaTypeServerDataSource + */ +export class UmbMoveMediaTypeServerDataSource implements UmbMoveDataSource { + #host: UmbControllerHost; + + /** + * Creates an instance of UmbMoveMediaTypeServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbMoveMediaTypeServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Move an item for the given id to the target unique + * @param {string} unique + * @param {(string | null)} targetUnique + * @return {*} + * @memberof UmbMoveMediaTypeServerDataSource + */ + async moveTo(args: UmbMoveToRequestArgs) { + if (!args.unique) throw new Error('Unique is missing'); + if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); + + return tryExecuteAndNotify( + this.#host, + MediaTypeService.putMediaTypeByIdMove({ + id: args.unique, + requestBody: { + target: args.destination.unique ? { id: args.destination.unique } : null, + }, + }), + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts index 60142d5186..e746aa874e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts @@ -8,3 +8,5 @@ export * from './tree/types.js'; export * from './types.js'; export * from './utils/index.js'; + +export { UMB_MEDIA_TYPE_PICKER_MODAL } from './tree/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/index.ts index 8f6cd31496..c3e4fe6987 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/index.ts @@ -4,8 +4,8 @@ export { UMB_MEDIA_TYPE_TREE_REPOSITORY_ALIAS, } from './manifests.js'; export * from './folder/index.js'; - export { UmbMediaTypeTreeRepository } from './media-type-tree.repository.js'; export { UMB_MEDIA_TYPE_TREE_STORE_CONTEXT } from './media-type-tree.store.js'; +export { UMB_MEDIA_TYPE_PICKER_MODAL } from './media-type-picker-modal.token.js'; export type { UmbMediaTypeTreeItemModel, UmbMediaTypeTreeRootModel } from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-picker-modal.token.ts new file mode 100644 index 0000000000..c6ecbe0509 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-picker-modal.token.ts @@ -0,0 +1,23 @@ +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; +import { + type UmbTreePickerModalValue, + type UmbTreePickerModalData, + type UmbUniqueTreeItemModel, + UMB_TREE_PICKER_MODAL_ALIAS, +} from '@umbraco-cms/backoffice/tree'; + +export type UmbMediaTypePickerModalData = UmbTreePickerModalData; +export type UmbMediaTypePickerModalValue = UmbTreePickerModalValue; + +export const UMB_MEDIA_TYPE_PICKER_MODAL = new UmbModalToken( + UMB_TREE_PICKER_MODAL_ALIAS, + { + modal: { + type: 'sidebar', + size: 'small', + }, + data: { + treeAlias: 'Umb.Tree.MediaType', + }, + }, +); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace-editor.element.ts index 4fee493db8..66c3009968 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace-editor.element.ts @@ -3,7 +3,7 @@ import { UMB_MEDIA_TYPE_WORKSPACE_CONTEXT } from './media-type-workspace.context import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { UMB_ICON_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { generateAlias } from '@umbraco-cms/backoffice/utils'; @@ -37,18 +37,6 @@ export class UmbMediaTypeWorkspaceEditorElement extends UmbLitElement { this.observe(this.#workspaceContext.name, (name) => (this._name = name), '_observeName'); this.observe(this.#workspaceContext.alias, (alias) => (this._alias = alias), '_observeAlias'); this.observe(this.#workspaceContext.icon, (icon) => (this._icon = icon), '_observeIcon'); - - this.observe( - this.#workspaceContext.isNew, - (isNew) => { - if (isNew) { - // TODO: Would be good with a more general way to bring focus to the name input. - (this.shadowRoot?.querySelector('#name') as HTMLElement)?.focus(); - } - this.removeUmbControllerByAlias('isNewRedirectController'); - }, - '_observeIsNew', - ); } // TODO: find a way where we don't have to do this for all workspaces. @@ -115,7 +103,7 @@ export class UmbMediaTypeWorkspaceEditorElement extends UmbLitElement { - + { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/manifests.ts index 3e355e7e9f..5964af777b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/manifests.ts @@ -1,5 +1,7 @@ import { UMB_MEDIA_DETAIL_REPOSITORY_ALIAS, UMB_MEDIA_ITEM_REPOSITORY_ALIAS } from '../repository/index.js'; +import { UMB_MEDIA_ENTITY_TYPE } from '../entity.js'; import { manifests as createManifests } from './create/manifests.js'; +import { manifests as moveManifests } from './move-to/manifests.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; const entityActions: Array = [ @@ -9,7 +11,7 @@ const entityActions: Array = [ alias: 'Umb.EntityAction.Media.Delete', name: 'Delete Media Entity Action ', kind: 'delete', - forEntityTypes: ['media'], + forEntityTypes: [UMB_MEDIA_ENTITY_TYPE], meta: { itemRepositoryAlias: UMB_MEDIA_ITEM_REPOSITORY_ALIAS, detailRepositoryAlias: UMB_MEDIA_DETAIL_REPOSITORY_ALIAS, @@ -17,4 +19,4 @@ const entityActions: Array = [ }, ]; -export const manifests = [...entityActions]; +export const manifests = [...entityActions, ...moveManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/index.ts new file mode 100644 index 0000000000..13b4fb73ad --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/index.ts @@ -0,0 +1 @@ +export { UmbMoveMediaRepository, UMB_MOVE_MEDIA_REPOSITORY_ALIAS } from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/manifests.ts new file mode 100644 index 0000000000..b97ac60e72 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/manifests.ts @@ -0,0 +1,22 @@ +import { UMB_MEDIA_ENTITY_TYPE } from '../../entity.js'; +import { UMB_MEDIA_TREE_REPOSITORY_ALIAS, UMB_MEDIA_TREE_ALIAS } from '../../tree/index.js'; +import { UMB_MOVE_MEDIA_REPOSITORY_ALIAS } from './repository/index.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +const entityActions: Array = [ + { + type: 'entityAction', + kind: 'moveTo', + alias: 'Umb.EntityAction.Media.MoveTo', + name: 'Move Media Entity Action', + forEntityTypes: [UMB_MEDIA_ENTITY_TYPE], + meta: { + treeRepositoryAlias: UMB_MEDIA_TREE_REPOSITORY_ALIAS, + moveRepositoryAlias: UMB_MOVE_MEDIA_REPOSITORY_ALIAS, + treeAlias: UMB_MEDIA_TREE_ALIAS, + }, + }, +]; + +export const manifests = [...entityActions, ...repositoryManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/constants.ts new file mode 100644 index 0000000000..8aab22c289 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/constants.ts @@ -0,0 +1 @@ +export const UMB_MOVE_MEDIA_REPOSITORY_ALIAS = 'Umb.Repository.Media.Move'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/index.ts new file mode 100644 index 0000000000..c37fac09be --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/index.ts @@ -0,0 +1,2 @@ +export { UmbMoveMediaRepository } from './media-move.repository.js'; +export { UMB_MOVE_MEDIA_REPOSITORY_ALIAS } from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/manifests.ts new file mode 100644 index 0000000000..699791550f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/manifests.ts @@ -0,0 +1,12 @@ +import { UMB_MOVE_MEDIA_REPOSITORY_ALIAS } from './constants.js'; +import { UmbMoveMediaRepository } from './media-move.repository.js'; +import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +const moveRepository: ManifestRepository = { + type: 'repository', + alias: UMB_MOVE_MEDIA_REPOSITORY_ALIAS, + name: 'Move Media Repository', + api: UmbMoveMediaRepository, +}; + +export const manifests = [moveRepository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/media-move.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/media-move.repository.ts new file mode 100644 index 0000000000..16fbdec5f0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/media-move.repository.ts @@ -0,0 +1,20 @@ +import { UmbMoveMediaServerDataSource } from './media-move.server.data-source.js'; +import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; +import type { UmbMoveRepository, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-action'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +export class UmbMoveMediaRepository extends UmbRepositoryBase implements UmbMoveRepository { + #moveSource = new UmbMoveMediaServerDataSource(this); + + async requestMoveTo(args: UmbMoveToRequestArgs) { + const { error } = await this.#moveSource.moveTo(args); + + if (!error) { + const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT); + const notification = { data: { message: `Moved` } }; + notificationContext.peek('positive', notification); + } + + return { error }; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/media-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/media-move.server.data-source.ts new file mode 100644 index 0000000000..faf84e11c5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/media-move.server.data-source.ts @@ -0,0 +1,44 @@ +import { MediaService } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import type { UmbMoveDataSource, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/entity-action'; + +/** + * Move Media Server Data Source + * @export + * @class UmbMoveMediaServerDataSource + */ +export class UmbMoveMediaServerDataSource implements UmbMoveDataSource { + #host: UmbControllerHost; + + /** + * Creates an instance of UmbMoveMediaServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbMoveMediaServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Move an item for the given id to the target unique + * @param {string} unique + * @param {(string | null)} targetUnique + * @return {*} + * @memberof UmbMoveMediaServerDataSource + */ + async moveTo(args: UmbMoveToRequestArgs) { + if (!args.unique) throw new Error('Unique is missing'); + if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); + + return tryExecuteAndNotify( + this.#host, + MediaService.putMediaByIdMove({ + id: args.unique, + requestBody: { + target: args.destination.unique ? { id: args.destination.unique } : null, + }, + }), + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/manifests.ts index dc643b3063..d7ea05ed49 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/manifests.ts @@ -32,7 +32,7 @@ export const manifests: Array = [ }, { type: 'entityBulkAction', - alias: 'Umb.EntityBulkAction.Media.Move', + alias: 'Umb.EntityBulkAction.Media.MoveTo', name: 'Move Media Entity Bulk Action', weight: 20, api: UmbMediaMoveEntityBulkAction, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move/move.action.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move/move.action.ts index 69dfbb5926..d22ef9c539 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move/move.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-bulk-actions/move/move.action.ts @@ -1,5 +1,6 @@ +import { UMB_MEDIA_TREE_PICKER_MODAL } from '../../tree/index.js'; import { UmbEntityBulkActionBase } from '@umbraco-cms/backoffice/entity-bulk-action'; -import { UMB_MODAL_MANAGER_CONTEXT, UMB_MEDIA_TREE_PICKER_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; export class UmbMediaMoveEntityBulkAction extends UmbEntityBulkActionBase { async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/index.ts index a475f13f31..774113923c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/index.ts @@ -7,7 +7,7 @@ export * from './components/index.js'; export * from './entity.js'; export * from './utils/index.js'; -export { UMB_MEDIA_TREE_ALIAS } from './tree/index.js'; +export { UMB_MEDIA_TREE_ALIAS, UMB_MEDIA_TREE_PICKER_MODAL } from './tree/index.js'; export { UMB_MEDIA_COLLECTION_ALIAS } from './collection/index.js'; export { UMB_MEDIA_MENU_ALIAS } from './menu/manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/entity-action/manifests.ts index d3631a29c6..f587d2449d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/entity-action/manifests.ts @@ -2,7 +2,7 @@ import { UMB_MEDIA_RECYCLE_BIN_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_MEDIA_ENTITY_TYPE } from '../../entity.js'; import { UMB_MEDIA_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js'; import { UMB_MEDIA_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../entity.js'; -import { UMB_MEDIA_TREE_PICKER_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UMB_MEDIA_TREE_PICKER_MODAL } from '../../tree/index.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/index.ts index 2b2581f649..9e0f66f683 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/index.ts @@ -1,5 +1,6 @@ export { UmbMediaTreeRepository } from './media-tree.repository.js'; export { UMB_MEDIA_TREE_REPOSITORY_ALIAS, UMB_MEDIA_TREE_STORE_ALIAS, UMB_MEDIA_TREE_ALIAS } from './manifests.js'; export { UMB_MEDIA_TREE_STORE_CONTEXT } from './media-tree.store.js'; +export { UMB_MEDIA_TREE_PICKER_MODAL } from './media-tree-picker-modal.token.js'; export { type UmbMediaTreeStore } from './media-tree.store.js'; export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/media-tree-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/media-tree-picker-modal.token.ts similarity index 57% rename from src/Umbraco.Web.UI.Client/src/packages/core/modal/token/media-tree-picker-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/media/media/tree/media-tree-picker-modal.token.ts index e7be987ac8..2ba9bba5cd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/media-tree-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/media-tree-picker-modal.token.ts @@ -1,12 +1,16 @@ -import { UmbModalToken } from './modal-token.js'; -import type { UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; +import { + type UmbTreePickerModalValue, + type UmbTreePickerModalData, + UMB_TREE_PICKER_MODAL_ALIAS, +} from '@umbraco-cms/backoffice/tree'; import type { UmbMediaTreeItemModel } from '@umbraco-cms/backoffice/media'; export type UmbMediaTreePickerModalData = UmbTreePickerModalData; -export type UmbMediaTreePickerModalValue = UmbPickerModalValue; +export type UmbMediaTreePickerModalValue = UmbTreePickerModalValue; export const UMB_MEDIA_TREE_PICKER_MODAL = new UmbModalToken( - 'Umb.Modal.TreePicker', + UMB_TREE_PICKER_MODAL_ALIAS, { modal: { type: 'sidebar', diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group-workspace-editor.element.ts index 65180d682c..a2f5f27ac4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group-workspace-editor.element.ts @@ -1,7 +1,7 @@ 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'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry'; import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; @@ -62,7 +62,7 @@ export class UmbMemberGroupWorkspaceEditorElement extends UmbLitElement { ${this.#renderActions()} `; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/modal/member-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/modal/member-type-picker-modal.token.ts index 22546423bb..dd858eadab 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/modal/member-type-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/modal/member-type-picker-modal.token.ts @@ -1,14 +1,18 @@ import { UmbModalToken } from '../../../core/modal/token/modal-token.js'; -import type { UmbUniqueTreeItemModel } from '@umbraco-cms/backoffice/tree'; -import type { UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal'; +import { UMB_TREE_PICKER_MODAL_ALIAS } from '@umbraco-cms/backoffice/tree'; +import type { + UmbTreePickerModalValue, + UmbTreePickerModalData, + UmbUniqueTreeItemModel, +} from '@umbraco-cms/backoffice/tree'; export type UmbMemberTypePickerModalData = UmbTreePickerModalData; -export type UmbMemberTypePickerModalValue = UmbPickerModalValue; +export type UmbMemberTypePickerModalValue = UmbTreePickerModalValue; export const UMB_MEMBER_TYPE_PICKER_MODAL = new UmbModalToken< UmbMemberTypePickerModalData, UmbMemberTypePickerModalValue ->('Umb.Modal.TreePicker', { +>(UMB_TREE_PICKER_MODAL_ALIAS, { modal: { type: 'sidebar', size: 'small', diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/member-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/member-type-workspace-editor.element.ts index 10cac1e6a0..37f3e59b7b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/member-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/member-type-workspace-editor.element.ts @@ -1,6 +1,6 @@ import { UMB_MEMBER_TYPE_WORKSPACE_CONTEXT } from './member-type-workspace.context-token.js'; import { css, html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { UMB_ICON_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; @@ -118,7 +118,7 @@ export class UmbMemberTypeWorkspaceEditorElement extends UmbLitElement { - + this._packageNameInput?.focus()); } async #getPackageCreated() { @@ -147,6 +146,7 @@ export class UmbWorkspacePackageBuilderElement extends UmbLitElement { required label="Name of the package" placeholder=${this.localize.term('placeholders_entername')} + ${umbFocus()} .value=${this._package?.name ?? ''} @input=${(e: UUIInputEvent) => (this._package!.name = e.target.value as string)}> 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 05d8649b00..a37110ec08 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 @@ -3,7 +3,7 @@ import { css, html, nothing, customElement, state, query, property } from '@umbr import { UMB_MODAL_MANAGER_CONTEXT, UMB_EXAMINE_FIELDS_SETTINGS_MODAL } from '@umbraco-cms/backoffice/modal'; import type { SearchResultResponseModel, FieldPresentationModel } from '@umbraco-cms/backoffice/external/backend-api'; import { SearcherService } from '@umbraco-cms/backoffice/external/backend-api'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; import './modal-views/fields-viewer.element.js'; @@ -112,7 +112,8 @@ export class UmbDashboardExamineSearcherElement extends UmbLitElement { id="search-input" placeholder="Type to filter..." label="Type to filter" - @keypress=${this._onKeyPress}> + @keypress=${this._onKeyPress} + ${umbFocus()}> Search diff --git a/src/Umbraco.Web.UI.Client/src/packages/static-file/modals/static-file-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/static-file/modals/static-file-picker-modal.token.ts index 2209fd678f..4b891f639f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/static-file/modals/static-file-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/static-file/modals/static-file-picker-modal.token.ts @@ -1,15 +1,19 @@ import { UMB_STATIC_FILE_TREE_ALIAS } from '../tree/manifests.js'; import type { StaticFileItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; -import type { UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal'; +import { + type UmbTreePickerModalValue, + type UmbTreePickerModalData, + UMB_TREE_PICKER_MODAL_ALIAS, +} from '@umbraco-cms/backoffice/tree'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export type UmbStaticFilePickerModalData = UmbTreePickerModalData; -export type UmbStaticFilePickerModalValue = UmbPickerModalValue; +export type UmbStaticFilePickerModalValue = UmbTreePickerModalValue; export const UMB_STATIC_FILE_PICKER_MODAL = new UmbModalToken< UmbStaticFilePickerModalData, UmbStaticFilePickerModalValue ->('Umb.Modal.TreePicker', { +>(UMB_TREE_PICKER_MODAL_ALIAS, { modal: { type: 'sidebar', size: 'small', diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/partial-view-picker/partial-view-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/partial-view-picker/partial-view-picker-modal.token.ts index cf2f080421..99e245951c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/partial-view-picker/partial-view-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/partial-view-picker/partial-view-picker-modal.token.ts @@ -1,15 +1,16 @@ import { UMB_PARTIAL_VIEW_TREE_ALIAS } from '../../partial-views/tree/manifests.js'; import type { UmbPartialViewTreeItemModel } from '../../partial-views/tree/index.js'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; -import type { UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal'; +import type { UmbTreePickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/tree'; +import { UMB_TREE_PICKER_MODAL_ALIAS } from '@umbraco-cms/backoffice/tree'; export type UmbPartialViewPickerModalData = UmbTreePickerModalData; -export type UmbPartialViewPickerModalValue = UmbPickerModalValue; +export type UmbPartialViewPickerModalValue = UmbTreePickerModalValue; export const UMB_PARTIAL_VIEW_PICKER_MODAL = new UmbModalToken< UmbPartialViewPickerModalData, UmbPartialViewPickerModalValue ->('Umb.Modal.TreePicker', { +>(UMB_TREE_PICKER_MODAL_ALIAS, { modal: { type: 'sidebar', size: 'small', diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace-editor.element.ts index 1b1ca191e7..980775ae3e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace-editor.element.ts @@ -4,8 +4,8 @@ import { UMB_PARTIAL_VIEW_WORKSPACE_CONTEXT } from './partial-view-workspace.con import { UMB_TEMPLATE_QUERY_BUILDER_MODAL } from '@umbraco-cms/backoffice/template'; import type { UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor'; import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; -import { css, html, customElement, query, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { css, html, customElement, query, state, nothing } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; @customElement('umb-partial-view-workspace-editor') @@ -20,7 +20,7 @@ export class UmbPartialViewWorkspaceEditorElement extends UmbLitElement { private _ready: boolean = false; @state() - private _isNew?: boolean = false; + private _isNew?: boolean; @query('umb-code-editor') private _codeEditor?: UmbCodeEditorElement; @@ -89,29 +89,36 @@ export class UmbPartialViewWorkspaceEditorElement extends UmbLitElement { } render() { - return html` -
- -
- -
- - - Query builder - -
- ${this._ready - ? this.#renderCodeEditor() - : html`
- -
`} -
-
`; + return this._isNew !== undefined + ? html` +
+ +
+ +
+ + + Query builder + +
+ ${this._ready + ? this.#renderCodeEditor() + : html`
+ +
`} +
+
` + : nothing; } static styles = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/modals/script-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/modals/script-picker-modal.token.ts index bd27809539..fff219026b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/modals/script-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/modals/script-picker-modal.token.ts @@ -1,12 +1,16 @@ import type { UmbScriptTreeItemModel } from '../tree/index.js'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; -import type { UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal'; +import { + type UmbTreePickerModalValue, + type UmbTreePickerModalData, + UMB_TREE_PICKER_MODAL_ALIAS, +} from '@umbraco-cms/backoffice/tree'; export type UmbScriptPickerModalData = UmbTreePickerModalData; -export type UmbScriptPickerModalValue = UmbPickerModalValue; +export type UmbScriptPickerModalValue = UmbTreePickerModalValue; export const UMB_SCRIPT_PICKER_MODAL = new UmbModalToken( - 'Umb.Modal.TreePicker', + UMB_TREE_PICKER_MODAL_ALIAS, { modal: { type: 'sidebar', diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/script-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/script-workspace-editor.element.ts index a8ba2ef651..54b9155946 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/script-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/script-workspace-editor.element.ts @@ -1,8 +1,8 @@ import { UMB_SCRIPT_WORKSPACE_CONTEXT } from './script-workspace.context-token.js'; import type { UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor'; -import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @customElement('umb-script-workspace-editor') @@ -17,7 +17,7 @@ export class UmbScriptWorkspaceEditorElement extends UmbLitElement { private _ready?: boolean = false; @state() - private _isNew?: boolean = false; + private _isNew?: boolean; #context?: typeof UMB_SCRIPT_WORKSPACE_CONTEXT.TYPE; @@ -66,25 +66,28 @@ export class UmbScriptWorkspaceEditorElement extends UmbLitElement { } render() { - return html` -
- -
- - -
- ${this._ready - ? this.#renderCodeEditor() - : html`
- -
`} -
-
`; + return this._isNew !== undefined + ? html` +
+ +
+ + +
+ ${this._ready + ? this.#renderCodeEditor() + : html`
+ +
`} +
+
` + : nothing; } static styles = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/components/stylesheet-input/stylesheet-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/components/stylesheet-input/stylesheet-picker-modal.token.ts index 619999fd74..ccc7cac44c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/components/stylesheet-input/stylesheet-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/components/stylesheet-input/stylesheet-picker-modal.token.ts @@ -1,14 +1,18 @@ import type { UmbStylesheetTreeItemModel } from '../../tree/types.js'; -import type { UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal'; +import { + type UmbTreePickerModalValue, + type UmbTreePickerModalData, + UMB_TREE_PICKER_MODAL_ALIAS, +} from '@umbraco-cms/backoffice/tree'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export type UmbStylesheetPickerModalData = UmbTreePickerModalData; -export type UmbStylesheetPickerModalValue = UmbPickerModalValue; +export type UmbStylesheetPickerModalValue = UmbTreePickerModalValue; export const UMB_STYLESHEET_PICKER_MODAL = new UmbModalToken< UmbStylesheetPickerModalData, UmbStylesheetPickerModalValue ->('Umb.Modal.TreePicker', { +>(UMB_TREE_PICKER_MODAL_ALIAS, { modal: { type: 'sidebar', size: 'small', diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts index 3adf3431dd..3535ee5154 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts @@ -1,13 +1,13 @@ import { UMB_STYLESHEET_WORKSPACE_CONTEXT } from './stylesheet-workspace.context-token.js'; import type { UUIInputElement, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; -import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { css, html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @customElement('umb-stylesheet-workspace-editor') export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { @state() - private _isNew?: boolean = false; + private _isNew?: boolean; @state() private _name?: string; @@ -35,20 +35,23 @@ export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { } render() { - return html` - - - - `; + return this._isNew !== undefined + ? html` + + + + ` + : nothing; } static styles = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder-modal.element.ts index da0bdc9672..6e1973c023 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder-modal.element.ts @@ -234,7 +234,7 @@ export default class UmbTemplateQueryBuilderModalElement extends UmbModalBaseEle ${sort.direction ?? this._defaultSortDirection} - ` + ` : ''}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/template-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/template-picker-modal.token.ts index 7778661df7..a832fdbd2a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/template-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/template-picker-modal.token.ts @@ -1,12 +1,13 @@ import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; -import type { UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal'; +import { UMB_TREE_PICKER_MODAL_ALIAS } from '@umbraco-cms/backoffice/tree'; +import type { UmbTreePickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/tree'; import type { UmbTemplateTreeItemModel } from '@umbraco-cms/backoffice/template'; export type UmbTemplatePickerModalData = UmbTreePickerModalData; -export type UmbTemplatePickerModalValue = UmbPickerModalValue; +export type UmbTemplatePickerModalValue = UmbTreePickerModalValue; export const UMB_TEMPLATE_PICKER_MODAL = new UmbModalToken( - 'Umb.Modal.TreePicker', + UMB_TREE_PICKER_MODAL_ALIAS, { modal: { type: 'sidebar', diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace-editor.element.ts index 7b886c2723..94887ad0fc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace-editor.element.ts @@ -10,7 +10,7 @@ import { css, html, customElement, query, state, nothing, ifDefined } from '@umb import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { UMB_TEMPLATE_PICKER_MODAL } from '@umbraco-cms/backoffice/template'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { Subject, debounceTime } from '@umbraco-cms/backoffice/external/rxjs'; @customElement('umb-template-workspace-editor') @@ -195,7 +195,8 @@ export class UmbTemplateWorkspaceEditorElement extends UmbLitElement { slot="header" .value=${this._name} @input=${this.#onNameInput} - label=${this.localize.term('template_template')}> + label=${this.localize.term('template_template')} + ${umbFocus()}> diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-mediapicker.plugin.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-mediapicker.plugin.ts index 8bae4b1abc..3451e0a5bf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-mediapicker.plugin.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-mediapicker.plugin.ts @@ -1,11 +1,11 @@ import { UMB_MEDIA_CAPTION_ALT_TEXT_MODAL } from '../modals/media-caption-alt-text/media-caption-alt-text-modal.token.js'; import { type TinyMcePluginArguments, UmbTinyMcePluginBase } from '../components/input-tiny-mce/tiny-mce-plugin.js'; -import { UMB_MEDIA_TREE_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { UMB_CURRENT_USER_CONTEXT, UmbCurrentUserModel } from '@umbraco-cms/backoffice/current-user'; import type { RawEditorOptions } from '@umbraco-cms/backoffice/external/tinymce'; import { UmbTemporaryFileRepository } from '@umbraco-cms/backoffice/temporary-file'; import { UmbId } from '@umbraco-cms/backoffice/id'; -import { sizeImageInEditor, uploadBlobImages } from '@umbraco-cms/backoffice/media'; +import { sizeImageInEditor, uploadBlobImages, UMB_MEDIA_TREE_PICKER_MODAL } from '@umbraco-cms/backoffice/media'; interface MediaPickerTargetData { altText?: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts index a7b1b2e669..f9a1da1ee5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts @@ -4,7 +4,7 @@ import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from './user-group-workspace.context 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'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbInputDocumentElement } from '@umbraco-cms/backoffice/document'; import type { UmbInputSectionElement } from '@umbraco-cms/backoffice/section'; @@ -82,7 +82,8 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { id="name" label=${this.localize.term('general_name')} .value=${this._userGroup?.name ?? ''} - @input="${this.#onNameChange}"> + @input="${this.#onNameChange}" + ${umbFocus()}>
`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts index c2f8e30725..0740cef2dd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -5,7 +5,7 @@ import { UMB_USER_WORKSPACE_CONTEXT } from './user-workspace.context-token.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'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; // import local components. Theses are not meant to be used outside of this component. @@ -66,7 +66,7 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { - + `; }