Merge branch 'main' into bugfix/block-grid-areas

This commit is contained in:
Jacob Overgaard
2024-04-15 13:15:26 +02:00
committed by GitHub
164 changed files with 1788 additions and 962 deletions

View File

@@ -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/',
},
},
};

View File

@@ -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": {

View File

@@ -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",

View File

@@ -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';

View File

@@ -368,3 +368,88 @@ describe('UmbExtensionRegistry with kinds', () => {
.unsubscribe();
});
});
describe('UmbExtensionRegistry with exclusions', () => {
let extensionRegistry: UmbExtensionRegistry<any>;
let manifests: Array<
ManifestElementWithElementName | TestManifestWithMeta | ManifestKind<ManifestElementWithElementName>
>;
beforeEach(() => {
extensionRegistry = new UmbExtensionRegistry<any>();
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;
});
});

View File

@@ -80,6 +80,7 @@ export class UmbExtensionRegistry<
private _kinds = new UmbBasicState<Array<ManifestKind<ManifestTypes>>>([]);
public readonly kinds = this._kinds.asObservable();
#exclusions: Array<string> = [];
defineKind(kind: ManifestKind<ManifestTypes>): 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<ManifestTypes>): 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);

View File

@@ -49,7 +49,7 @@ export class UmbMockEntityTreeManager<T extends { id: string; parent?: { id: str
const movedItems = items.map((item) => {
return {
...item,
parentId: destinationId,
parent: destinationId ? { id: destinationId } : null,
};
});

View File

@@ -9,7 +9,7 @@ export const handlers = [
...treeHandlers,
...itemHandlers,
...folderHandlers,
...detailHandlers,
...moveHandlers,
...copyHandlers,
...detailHandlers,
];

View File

@@ -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));

View File

@@ -102,6 +102,7 @@ export class UmbExtensionSlotElement extends UmbLitElement {
disconnectedCallback(): void {
this.#attached = false;
this.#extensionsController?.destroy();
this.#extensionsController = undefined;
super.disconnectedCallback();
}

View File

@@ -149,6 +149,7 @@ export class UmbExtensionWithApiSlotElement extends UmbLitElement {
disconnectedCallback(): void {
this.#attached = false;
this.#extensionsController?.destroy();
this.#extensionsController = undefined;
super.disconnectedCallback();
}

View File

@@ -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;

View File

@@ -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',
},
],
},
};

View File

@@ -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`<uui-input
id="datetime"
label="Pick a date or time"
.type="${this.type}"
@change="${this.#onChange}"
min="${ifDefined(this.min)}"
max="${ifDefined(this.max)}"
.step="${this.step}"
.value="${this.displayValue?.replace('Z', '')}">
.min=${this.min}
.max=${this.max}
.step=${this.step}
.type=${this.type}
.value="${this.displayValue?.replace('Z', '')}"
@change=${this.#onChange}>
</uui-input>`;
}
}

View File

@@ -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<any> | Map<PropertyKey, unknown>): 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()}>
<!-- TODO: validation for bad characters -->
</uui-input>
<uui-input

View File

@@ -1,4 +1,5 @@
export * from './duplicate/duplicate.action.js';
export * from './move/index.js';
export * from './delete/delete.action.js';
export * from './move/move.action.js';
export * from './move/move-to.action.js';
export * from './sort-children-of/sort-children-of.action.js';

View File

@@ -1,2 +1,3 @@
export type { UmbMoveDataSource } from './move-data-source.interface.js';
export type { UmbMoveRepository } from './move-repository.interface.js';
export type { UmbMoveToRequestArgs } from './types.js';

View File

@@ -1,3 +1,3 @@
import { manifest as moveKindManifest } from './move.action.kind.js';
import { manifest as moveToKindManifest } from './move-to.action.kind.js';
export const manifests = [moveKindManifest];
export const manifests = [moveToKindManifest];

View File

@@ -0,0 +1,6 @@
import type { UmbMoveToRequestArgs } from './types.js';
import type { UmbDataSourceErrorResponse } from '@umbraco-cms/backoffice/repository';
export interface UmbMoveDataSource {
moveTo(args: UmbMoveToRequestArgs): Promise<UmbDataSourceErrorResponse>;
}

View File

@@ -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<UmbRepositoryErrorResponse>;
}

View File

@@ -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: '',
},
},
};

View File

@@ -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<MetaEntityActionMoveToKind> {
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<UmbMoveRepository>(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;

View File

@@ -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<any> {
// TODO: make base type for item and detail models
#itemRepository?: UmbItemRepository<any>;
#moveRepository?: UmbMoveRepository;
#init: Promise<unknown>;
constructor(host: UmbControllerHost, args: UmbEntityActionArgs<MetaEntityActionMoveKind>) {
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<any>) : 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;

View File

@@ -0,0 +1,6 @@
export interface UmbMoveToRequestArgs {
unique: string;
destination: {
unique: string | null;
};
}

View File

@@ -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,
];

View File

@@ -125,16 +125,16 @@ export interface MetaEntityActionDuplicateKind extends MetaEntityActionDefaultKi
pickerModal: UmbModalToken | string;
}
// MOVE
export interface ManifestEntityActionMoveKind extends ManifestEntityAction<MetaEntityActionMoveKind> {
// MOVE TO
export interface ManifestEntityActionMoveToKind extends ManifestEntityAction<MetaEntityActionMoveToKind> {
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

View File

@@ -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

View File

@@ -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`<input ${umbFocus()}>`;
* ```
*/
export const umbFocus = directive(UmbFocusDirective);
//export type { UmbFocusDirective };

View File

@@ -0,0 +1 @@
export * from './focus.lit-directive.js';

View File

@@ -1 +1,2 @@
export * from './lit-element.element.js';
export * from './directives/index.js';

View File

@@ -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<UmbIconPicker
placeholder=${this.localize.term('placeholders_filter')}
label=${this.localize.term('placeholders_filter')}
id="searchbar"
@keyup="${this.#filterIcons}">
@keyup="${this.#filterIcons}"
${umbFocus()}>
<uui-icon name="search" slot="prepend" id="searchbar_icon"></uui-icon>
</uui-input>`;
}

View File

@@ -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<UmbItemPickerModalData, UmbItemPickerModel> {
@@ -52,7 +53,11 @@ export class UmbItemPickerModalElement extends UmbModalBaseElement<UmbItemPicker
return html`
<umb-body-layout headline=${this.data.headline}>
<div id="main">
<uui-input type="search" placeholder=${this.localize.term('placeholders_filter')} @input=${this.#filter}>
<uui-input
type="search"
placeholder=${this.localize.term('placeholders_filter')}
@input=${this.#filter}
${umbFocus()}>
<div slot="prepend">
<uui-icon name="search"></uui-icon>
</div>

View File

@@ -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';

View File

@@ -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<UmbUniqueTreeItemModel>;
export type UmbMediaTypePickerModalValue = UmbPickerModalValue;
export const UMB_MEDIA_TYPE_PICKER_MODAL = new UmbModalToken<UmbMediaTypePickerModalData, UmbMediaTypePickerModalValue>(
'Umb.Modal.TreePicker',
{
modal: {
type: 'sidebar',
size: 'small',
},
data: {
treeAlias: 'Umb.Tree.MediaType',
},
},
);

View File

@@ -7,9 +7,3 @@ export interface UmbPickerModalData<ItemType> {
export interface UmbPickerModalValue {
selection: Array<string | null>;
}
export interface UmbTreePickerModalData<TreeItemType> extends UmbPickerModalData<TreeItemType> {
treeAlias?: string;
}
export interface UmbTreePickerModalValue extends UmbPickerModalValue {}

View File

@@ -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,
},
],
},
],
},
},
};

View File

@@ -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<string>('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`<umb-input-date
.type=${this._inputType}
@input=${this._onInput}
.datetime=${this._valueString}
.min=${this._min}
.max=${this._max}
.step=${this._step}
.offsetTime=${this._offsetTime || false}
label="Pick a date or time"></umb-input-date>`;
return html`
<umb-input-date
value="${ifDefined(this.value)}"
.min=${this._min}
.max=${this._max}
.step=${this._step}
.type=${this._inputType}
@change=${this.#onChange}>
</umb-input-date>
`;
}
}

View File

@@ -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';

View File

@@ -1,5 +0,0 @@
import type { UmbDataSourceErrorResponse } from '@umbraco-cms/backoffice/repository';
export interface UmbMoveDataSource {
move(unique: string, targetUnique: string | null): Promise<UmbDataSourceErrorResponse>;
}

View File

@@ -1,5 +0,0 @@
import type { UmbRepositoryErrorResponse } from '../types.js';
export interface UmbMoveRepository {
move(unique: string, targetUnique: string): Promise<UmbRepositoryErrorResponse>;
}

View File

@@ -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';
/*

View File

@@ -0,0 +1 @@
export const UMB_TREE_PICKER_MODAL_ALIAS = 'Umb.Modal.TreePicker';

View File

@@ -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';

View File

@@ -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<TreeItemType extends UmbTreeItemModelBase> extends UmbModalBaseElement<
UmbTreePickerModalData<TreeItemType>,
UmbPickerModalValue
UmbTreePickerModalValue
> {
@state()
_selectionConfiguration: UmbTreeSelectionConfiguration = {

View File

@@ -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<TreeItemType = any> extends UmbPickerModalData<TreeItemType> {
treeAlias?: string;
}
export interface UmbTreePickerModalValue extends UmbPickerModalValue {}
export const UMB_TREE_PICKER_MODAL = new UmbModalToken<UmbTreePickerModalData, UmbTreePickerModalValue>(
UMB_TREE_PICKER_MODAL_ALIAS,
{
modal: {
type: 'sidebar',
size: 'small',
},
},
);

View File

@@ -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

View File

@@ -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';

View File

@@ -0,0 +1 @@
export { UmbMoveDataTypeRepository, UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './repository/index.js';

View File

@@ -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<ManifestTypes> = [
{
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];

View File

@@ -0,0 +1 @@
export const UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Move';

View File

@@ -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 };
}
}

View File

@@ -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,
},
}),
);
}
}

View File

@@ -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';

View File

@@ -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,

View File

@@ -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<ManifestTypes> = [
{
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];

View File

@@ -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';

View File

@@ -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<T> {
[key: string]: Array<T>;
@@ -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()}>
<uui-icon name="search" slot="prepend" id="filter-icon"></uui-icon>
</uui-input>`;
}

View File

@@ -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<UmbUniqueTreeItemModel>;
export type UmbDataTypePickerModalValue = UmbPickerModalValue;
export type UmbDataTypePickerModalValue = UmbTreePickerModalValue;
export const UMB_DATA_TYPE_PICKER_MODAL = new UmbModalToken<UmbDataTypePickerModalData, UmbDataTypePickerModalValue>(
'Umb.Modal.TreePicker',
UMB_TREE_PICKER_MODAL_ALIAS,
{
modal: {
type: 'sidebar',

View File

@@ -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<ManifestPropertyEditorUi>;
@@ -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()}>
<uui-icon name="search" slot="prepend" id="filter-icon"></uui-icon>
</uui-input>`;
}

View File

@@ -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';

View File

@@ -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];

View File

@@ -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<unknown>;
#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 };
}
}

View File

@@ -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,
},
}),
);
}
}

View File

@@ -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,

View File

@@ -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`
<umb-workspace-editor alias="Umb.Workspace.DataType">
<uui-input slot="header" id="nameInput" .value=${this._dataTypeName} @input="${this.#handleInput}"></uui-input>
<uui-input
slot="header"
id="nameInput"
.value=${this._dataTypeName}
@input="${this.#handleInput}"
${umbFocus()}></uui-input>
</umb-workspace-editor>
`;
}

View File

@@ -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<ManifestTypes> = [
@@ -16,16 +17,6 @@ const entityActions: Array<ManifestTypes> = [
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<ManifestModal> = [
},
];
export const manifests = [...entityActions, ...modals];
export const manifests = [...entityActions, ...modals, ...moveManifests];

View File

@@ -0,0 +1 @@
export { UmbMoveDictionaryRepository, UMB_MOVE_DICTIONARY_REPOSITORY_ALIAS } from './repository/index.js';

View File

@@ -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<ManifestTypes> = [
{
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];

View File

@@ -0,0 +1 @@
export const UMB_MOVE_DICTIONARY_REPOSITORY_ALIAS = 'Umb.Repository.Dictionary.Move';

View File

@@ -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 };
}
}

View File

@@ -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,
},
}),
);
}
}

View File

@@ -0,0 +1,2 @@
export { UmbMoveDictionaryRepository } from './dictionary-move.repository.js';
export { UMB_MOVE_DICTIONARY_REPOSITORY_ALIAS } from './constants.js';

View File

@@ -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];

View File

@@ -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<UmbUniqueTreeItemModel>;
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',

View File

@@ -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')}"></uui-input>
label="${this.localize.term('general_dictionary')} ${this.localize.term('general_name')}"
${umbFocus()}></uui-input>
</div>
</umb-workspace-editor>
`;

View File

@@ -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`
<umb-body-layout headline=${this.localize.term('actions_createblueprint')}>
<uui-box>
<strong>Create an item under Content Templates</strong>
<uui-box headline="Create a folder under Content Templates">
<uui-menu-item @click=${this.#onCreateFolderClick} label="New Folder...">
<uui-icon slot="icon" name="icon-folder"></uui-icon>
</uui-menu-item>
</uui-box>
<uui-box headline="Create an item under Content Templates">
<umb-localize key="create_createContentBlueprint">
Select the Document Type you want to make a content blueprint for
</umb-localize>
@@ -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);
}
`,
];

View File

@@ -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',
};
};

View File

@@ -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);
}
}

View File

@@ -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,
}),
);
}
}

View File

@@ -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';

View File

@@ -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<ManifestTypes> = [
// {
// 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<ManifestTypes> = [
{
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];

View File

@@ -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;
}

View File

@@ -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';

View File

@@ -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];

View File

@@ -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();

View File

@@ -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;

View File

@@ -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<ManifestTypes> = [
{
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<ManifestTypes> = [
},
];
export const manifests = [...entityActions, ...createManifests];
export const manifests = [...entityActions, ...createManifests, ...moveManifests];

View File

@@ -0,0 +1 @@
export { UmbMoveDocumentTypeRepository, UMB_MOVE_DOCUMENT_TYPE_REPOSITORY_ALIAS } from './repository/index.js';

View File

@@ -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<ManifestTypes> = [
{
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];

View File

@@ -0,0 +1 @@
export const UMB_MOVE_DOCUMENT_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DocumentType.Move';

View File

@@ -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 };
}
}

View File

@@ -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,
},
}),
);
}
}

View File

@@ -0,0 +1,2 @@
export { UmbMoveDocumentTypeRepository } from './document-type-move.repository.js';
export { UMB_MOVE_DOCUMENT_TYPE_REPOSITORY_ALIAS } from './constants.js';

View File

@@ -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];

View File

@@ -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<UmbDocumentTypeTreeItemModel>;
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',

View File

@@ -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 {
<umb-icon name=${ifDefined(this._icon)}></umb-icon>
</uui-button>
<uui-input id="name" .value=${this._name} @input="${this.#onNameChange}" label="name">
<uui-input id="name" label="name" .value=${this._name} @input="${this.#onNameChange}" ${umbFocus()}>
<!-- TODO: should use UUI-LOCK-INPUT, but that does not fire an event when its locked/unlocked -->
<uui-input
name="alias"

View File

@@ -1,23 +1,30 @@
import { UmbDocumentCreateBlueprintRepository } from './repository/document-create-blueprint.repository.js';
import { UMB_CREATE_BLUEPRINT_MODAL } from './modal/create-blueprint-modal.token.js';
import type { UmbEntityActionArgs } from '@umbraco-cms/backoffice/entity-action';
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import { UmbDocumentBlueprintDetailRepository } from '@umbraco-cms/backoffice/document-blueprint';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { UmbEntityActionArgs } from '@umbraco-cms/backoffice/entity-action';
export class UmbCreateDocumentBlueprintEntityAction extends UmbEntityActionBase<never> {
#repository = new UmbDocumentBlueprintDetailRepository(this);
#repository = new UmbDocumentCreateBlueprintRepository(this);
constructor(host: UmbControllerHost, args: UmbEntityActionArgs<never>) {
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;

View File

@@ -1 +1,2 @@
export * from './modal/index.js';
export * from './repository/index.js';

View File

@@ -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<UmbCreateBlueprintModalData, never> {
#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<UmbCreat
this._blueprintName = data.variants[0].name;
}
#mapDocumentToBlueprintModel() {
if (!this.#document) return;
const variants = this.#document?.variants.map((variant) => ({ ...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();
}

View File

@@ -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<UmbCreateBlueprintModalData, never>(
export interface UmbCreateBlueprintModalValue {
name: string;
parent: ReferenceByIdModel | null;
}
export const UMB_CREATE_BLUEPRINT_MODAL = new UmbModalToken<UmbCreateBlueprintModalData, UmbCreateBlueprintModalValue>(
'Umb.Modal.CreateBlueprint',
{
modal: {

Some files were not shown because too many files have changed in this diff Show More