Merge remote-tracking branch 'origin/main' into feature/file-upload-temp
This commit is contained in:
@@ -51,6 +51,11 @@
|
||||
"exceptions": ["@umbraco-cms", "@open-wc/testing", "@storybook", "msw", "."]
|
||||
}
|
||||
],
|
||||
"local-rules/exported-string-constant-naming": ["error",
|
||||
{
|
||||
"excludedFileNames": ["umbraco-package", "input-tiny-mce.defaults"] // TODO: what to do about the tiny mce defaults?
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
"@typescript-eslint/no-unused-vars": "warn"
|
||||
|
||||
@@ -13,7 +13,7 @@ import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext } from '../src/
|
||||
import { UmbDataTypeTreeStore } from '../src/packages/core/data-type/tree/data-type.tree.store';
|
||||
import { UmbDocumentStore } from '../src/packages/documents/documents/repository/document.store';
|
||||
import { UmbDocumentTreeStore } from '../src/packages/documents/documents/repository/document.tree.store';
|
||||
import { UmbDocumentTypeStore } from '../src/packages/documents/document-types/repository/document-type.store';
|
||||
import { UmbDocumentTypeDetailStore } from '../src/packages/documents/document-types/repository/detail/document-type-detail.store';
|
||||
import { umbExtensionsRegistry } from '../src/packages/core/extension-registry';
|
||||
import { UmbIconRegistry } from '../src/shared/icon-registry/icon.registry';
|
||||
import { UmbLitElement } from '../src/shared/lit-element';
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description:
|
||||
'Ensure all exported string constants should be in uppercase with words separated by underscores and prefixed with UMB_',
|
||||
},
|
||||
},
|
||||
create: function (context) {
|
||||
const excludedFileNames = context.options[0]?.excludedFileNames || [];
|
||||
return {
|
||||
ExportNamedDeclaration(node) {
|
||||
const fileName = context.getFilename();
|
||||
|
||||
if (excludedFileNames.some((excludedFileName) => fileName.includes(excludedFileName))) {
|
||||
// Skip the rule check for files in the excluded list
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.declaration && node.declaration.type === 'VariableDeclaration') {
|
||||
const declaration = node.declaration.declarations[0];
|
||||
const { id, init } = declaration;
|
||||
|
||||
if (id && id.type === 'Identifier' && init && init.type === 'Literal' && typeof init.value === 'string') {
|
||||
const isValidName = /^[A-Z]+(_[A-Z]+)*$/.test(id.name);
|
||||
|
||||
if (!isValidName || !id.name.startsWith('UMB_')) {
|
||||
context.report({
|
||||
node: id,
|
||||
message:
|
||||
'Exported string constant should be in uppercase with words separated by underscores and prefixed with UMB_',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -18,4 +18,5 @@ module.exports = {
|
||||
'prefer-import-aliases': preferImportAliasesRule,
|
||||
'prefer-static-styles-last': preferStaticStylesLastRule,
|
||||
'umb-class-prefix': umbClassPrefixRule,
|
||||
'exported-string-constant-naming': require('./devops/eslint/rules/exported-string-constant-naming.cjs'),
|
||||
};
|
||||
|
||||
8
src/Umbraco.Web.UI.Client/package-lock.json
generated
8
src/Umbraco.Web.UI.Client/package-lock.json
generated
@@ -21,7 +21,7 @@
|
||||
"marked": "^9.1.0",
|
||||
"monaco-editor": "^0.41.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"tinymce": "^6.7.1",
|
||||
"tinymce": "^6.7.3",
|
||||
"tinymce-i18n": "^23.8.7",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
@@ -20560,9 +20560,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tinymce": {
|
||||
"version": "6.7.1",
|
||||
"resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.7.1.tgz",
|
||||
"integrity": "sha512-SIGJgWk2d/X59VbO+i81QfNx2EP1P5t+sza2/1So3OLGtmMBhEJMag7sN/Mo8sq4s0niwb65Z51yLju32jP11g=="
|
||||
"version": "6.7.3",
|
||||
"resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.7.3.tgz",
|
||||
"integrity": "sha512-J7WmYIi/gt1RvZ6Ap2oQiUjzAoiS9pfV+d4GnKuZuPu8agmlAEAInNmMvMjfCNBzHv4JnZXY7qlHUAI0IuYQVA=="
|
||||
},
|
||||
"node_modules/tinymce-i18n": {
|
||||
"version": "23.8.7",
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
"marked": "^9.1.0",
|
||||
"monaco-editor": "^0.41.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"tinymce": "^6.7.1",
|
||||
"tinymce": "^6.7.3",
|
||||
"tinymce-i18n": "^23.8.7",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
|
||||
@@ -2,23 +2,25 @@ import { expect, oneEvent } from '@open-wc/testing';
|
||||
import { UmbContextProvider } from '../provide/context-provider.js';
|
||||
import { UmbContextToken } from '../token/context-token.js';
|
||||
import { UmbContextConsumer } from './context-consumer.js';
|
||||
import { UmbContextRequestEventImplementation, umbContextRequestEventType } from './context-request.event.js';
|
||||
import { UmbContextRequestEventImplementation, UMB_CONTENT_REQUEST_EVENT_TYPE } from './context-request.event.js';
|
||||
|
||||
const testContextAlias = 'my-test-context';
|
||||
const testContextAliasAndApiAlias = 'my-test-context#testApi';
|
||||
const testContextAliasAndNotExstingApiAlias = 'my-test-context#notExistingTestApi';
|
||||
|
||||
class UmbTestContextConsumerClass {
|
||||
public prop: string = 'value from provider';
|
||||
}
|
||||
|
||||
describe('UmbContextConsumer', () => {
|
||||
let consumer: UmbContextConsumer;
|
||||
|
||||
beforeEach(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
consumer = new UmbContextConsumer(document.body, testContextAlias, () => {});
|
||||
});
|
||||
|
||||
describe('Public API', () => {
|
||||
let consumer: UmbContextConsumer;
|
||||
|
||||
beforeEach(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
consumer = new UmbContextConsumer(document.body, testContextAlias, () => {});
|
||||
});
|
||||
|
||||
describe('properties', () => {
|
||||
it('has a instance property', () => {
|
||||
expect(consumer).to.have.property('instance').that.is.undefined;
|
||||
@@ -32,143 +34,191 @@ describe('UmbContextConsumer', () => {
|
||||
|
||||
describe('events', () => {
|
||||
it('dispatches context request event when constructed', async () => {
|
||||
const listener = oneEvent(window, umbContextRequestEventType);
|
||||
const listener = oneEvent(window, UMB_CONTENT_REQUEST_EVENT_TYPE);
|
||||
|
||||
consumer.hostConnected();
|
||||
|
||||
const event = (await listener) as unknown as UmbContextRequestEventImplementation;
|
||||
expect(event).to.exist;
|
||||
expect(event.type).to.eq(umbContextRequestEventType);
|
||||
expect(event.type).to.eq(UMB_CONTENT_REQUEST_EVENT_TYPE);
|
||||
expect(event.contextAlias).to.eq(testContextAlias);
|
||||
consumer.hostDisconnected();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('works with UmbContextProvider', (done) => {
|
||||
const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
|
||||
provider.hostConnected();
|
||||
describe('Simple implementation', () => {
|
||||
it('works with UmbContextProvider', (done) => {
|
||||
const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
|
||||
provider.hostConnected();
|
||||
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
testContextAlias,
|
||||
(_instance: UmbTestContextConsumerClass | undefined) => {
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
testContextAlias,
|
||||
(_instance: UmbTestContextConsumerClass | undefined) => {
|
||||
if (_instance) {
|
||||
expect(_instance.prop).to.eq('value from provider');
|
||||
done();
|
||||
localConsumer.hostDisconnected();
|
||||
provider.hostDisconnected();
|
||||
}
|
||||
},
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
|
||||
/*
|
||||
Unprovided feature is out commented currently. I'm not sure there is a use case. So lets leave the code around until we know for sure.
|
||||
it('acts to Context API disconnected', (done) => {
|
||||
const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
|
||||
provider.hostConnected();
|
||||
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
let callbackNum = 0;
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
testContextAlias,
|
||||
(_instance: UmbTestContextConsumerClass | undefined) => {
|
||||
callbackNum++;
|
||||
if (callbackNum === 1) {
|
||||
expect(_instance?.prop).to.eq('value from provider');
|
||||
// unregister.
|
||||
provider.hostDisconnected();
|
||||
} else if (callbackNum === 2) {
|
||||
expect(_instance?.prop).to.be.undefined;
|
||||
done();
|
||||
}
|
||||
}
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
describe('Implementation with Api Alias', () => {
|
||||
it('responds when api alias matches', (done) => {
|
||||
const provider = new UmbContextProvider(
|
||||
document.body,
|
||||
testContextAliasAndApiAlias,
|
||||
new UmbTestContextConsumerClass(),
|
||||
);
|
||||
provider.hostConnected();
|
||||
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(element, testContextAliasAndApiAlias, (_instance) => {
|
||||
if (_instance) {
|
||||
expect((_instance as UmbTestContextConsumerClass).prop).to.eq('value from provider');
|
||||
localConsumer.hostDisconnected();
|
||||
provider.hostDisconnected();
|
||||
done();
|
||||
}
|
||||
});
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
|
||||
it('does not respond to a non existing api alias', (done) => {
|
||||
const provider = new UmbContextProvider(
|
||||
document.body,
|
||||
testContextAliasAndApiAlias,
|
||||
new UmbTestContextConsumerClass(),
|
||||
);
|
||||
provider.hostConnected();
|
||||
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(element, testContextAliasAndNotExstingApiAlias, () => {
|
||||
expect(false).to.be.true;
|
||||
});
|
||||
localConsumer.hostConnected();
|
||||
|
||||
// Delayed check to make sure the callback is not called.
|
||||
Promise.resolve().then(() => {
|
||||
localConsumer.hostDisconnected();
|
||||
provider.hostDisconnected();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Implementation with discriminator method', () => {
|
||||
type A = { prop: string };
|
||||
|
||||
function discriminator(instance: unknown): instance is A {
|
||||
return typeof (instance as any).prop === 'string';
|
||||
}
|
||||
|
||||
function badDiscriminator(instance: unknown): instance is A {
|
||||
return typeof (instance as any).notExistingProp === 'string';
|
||||
}
|
||||
|
||||
it('discriminator determines the instance type', async () => {
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
document.body,
|
||||
new UmbContextToken(testContextAlias, undefined, discriminator),
|
||||
(instance: A) => {
|
||||
console.log(instance);
|
||||
},
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
|
||||
// This bit of code is not really a test but it serves as a TypeScript type test, making sure the given type is matches the one given from the Discriminator method.
|
||||
type TestType = Exclude<typeof localConsumer.instance, undefined> extends A ? true : never;
|
||||
const test: TestType = true;
|
||||
expect(test).to.be.true;
|
||||
|
||||
localConsumer.destroy();
|
||||
});
|
||||
|
||||
it('approving discriminator still fires callback', (done) => {
|
||||
const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
|
||||
provider.hostConnected();
|
||||
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
new UmbContextToken(testContextAlias, undefined, discriminator),
|
||||
(_instance) => {
|
||||
expect(_instance.prop).to.eq('value from provider');
|
||||
done();
|
||||
localConsumer.hostDisconnected();
|
||||
provider.hostDisconnected();
|
||||
}
|
||||
}
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
},
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
|
||||
/*
|
||||
Unprovided feature is out commented currently. I'm not sure there is a use case. So lets leave the code around until we know for sure.
|
||||
it('acts to Context API disconnected', (done) => {
|
||||
const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
|
||||
provider.hostConnected();
|
||||
it('disapproving discriminator does not fire callback', (done) => {
|
||||
const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
|
||||
provider.hostConnected();
|
||||
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
let callbackNum = 0;
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
new UmbContextToken(testContextAlias, undefined, badDiscriminator),
|
||||
(_instance) => {
|
||||
expect(_instance.prop).to.eq('this must not happen!');
|
||||
},
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
testContextAlias,
|
||||
(_instance: UmbTestContextConsumerClass | undefined) => {
|
||||
callbackNum++;
|
||||
if (callbackNum === 1) {
|
||||
expect(_instance?.prop).to.eq('value from provider');
|
||||
// unregister.
|
||||
provider.hostDisconnected();
|
||||
} else if (callbackNum === 2) {
|
||||
expect(_instance?.prop).to.be.undefined;
|
||||
done();
|
||||
}
|
||||
}
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
describe('UmbContextConsumer with discriminator test', () => {
|
||||
|
||||
type A = { prop: string };
|
||||
|
||||
function discriminator(instance: unknown): instance is A {
|
||||
return typeof (instance as any).prop === 'string';
|
||||
}
|
||||
|
||||
function badDiscriminator(instance: unknown): instance is A {
|
||||
return typeof (instance as any).notExistingProp === 'string';
|
||||
}
|
||||
|
||||
it('discriminator determines the instance type', async () => {
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
document.body,
|
||||
new UmbContextToken(testContextAlias, discriminator),
|
||||
(instance: A) => { console.log(instance)}
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
|
||||
// This bit of code is not really a test but it serves as a TypeScript type test, making sure the given type is matches the one given from the Discriminator method.
|
||||
type TestType = Exclude<(typeof localConsumer.instance), undefined> extends A ? true : never;
|
||||
const test: TestType = true;
|
||||
expect(test).to.be.true;
|
||||
|
||||
localConsumer.destroy();
|
||||
});
|
||||
|
||||
it('approving discriminator still fires callback', (done) => {
|
||||
const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
|
||||
provider.hostConnected();
|
||||
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
new UmbContextToken(testContextAlias, discriminator),
|
||||
(_instance) => {
|
||||
expect(_instance.prop).to.eq('value from provider');
|
||||
Promise.resolve().then(() => {
|
||||
done();
|
||||
localConsumer.hostDisconnected();
|
||||
provider.hostDisconnected();
|
||||
}
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
|
||||
it('disapproving discriminator does not fire callback', (done) => {
|
||||
const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
|
||||
provider.hostConnected();
|
||||
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
new UmbContextToken(testContextAlias, badDiscriminator),
|
||||
(_instance) => {
|
||||
expect(_instance.prop).to.eq('this must not happen!');
|
||||
}
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
|
||||
Promise.resolve().then(() => {
|
||||
done();
|
||||
localConsumer.hostDisconnected();
|
||||
provider.hostDisconnected();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import { UmbContextDiscriminator, UmbContextToken } from '../token/context-token
|
||||
import {
|
||||
isUmbContextProvideEventType,
|
||||
//isUmbContextUnprovidedEventType,
|
||||
umbContextProvideEventType,
|
||||
UMB_CONTEXT_PROVIDE_EVENT_TYPE,
|
||||
//umbContextUnprovidedEventType,
|
||||
} from '../provide/context-provide.event.js';
|
||||
import { UmbContextRequestEventImplementation, UmbContextCallback } from './context-request.event.js';
|
||||
@@ -11,9 +11,7 @@ import { UmbContextRequestEventImplementation, UmbContextCallback } from './cont
|
||||
* @export
|
||||
* @class UmbContextConsumer
|
||||
*/
|
||||
export class UmbContextConsumer<
|
||||
BaseType = unknown,
|
||||
ResultType extends BaseType = BaseType> {
|
||||
export class UmbContextConsumer<BaseType = unknown, ResultType extends BaseType = BaseType> {
|
||||
#callback?: UmbContextCallback<ResultType>;
|
||||
#promise?: Promise<ResultType>;
|
||||
#promiseResolver?: (instance: ResultType) => void;
|
||||
@@ -24,33 +22,36 @@ ResultType extends BaseType = BaseType> {
|
||||
}
|
||||
|
||||
#contextAlias: string;
|
||||
#apiAlias: string;
|
||||
|
||||
#discriminator?: UmbContextDiscriminator<BaseType, ResultType>;
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbContextConsumer.
|
||||
* @param {EventTarget} hostElement
|
||||
* @param {string} contextAlias
|
||||
* @param {string} contextIdentifier
|
||||
* @param {UmbContextCallback} callback
|
||||
* @memberof UmbContextConsumer
|
||||
*/
|
||||
constructor(
|
||||
protected hostElement: EventTarget,
|
||||
contextAlias: string | UmbContextToken<BaseType, ResultType>,
|
||||
callback?: UmbContextCallback<ResultType>
|
||||
contextIdentifier: string | UmbContextToken<BaseType, ResultType>,
|
||||
callback?: UmbContextCallback<ResultType>,
|
||||
) {
|
||||
this.#contextAlias = contextAlias.toString();
|
||||
const idSplit = contextIdentifier.toString().split('#');
|
||||
this.#contextAlias = idSplit[0];
|
||||
this.#apiAlias = idSplit[1] ?? 'default';
|
||||
this.#callback = callback;
|
||||
this.#discriminator = (contextAlias as UmbContextToken<BaseType, ResultType>).getDiscriminator?.();
|
||||
this.#discriminator = (contextIdentifier as UmbContextToken<BaseType, ResultType>).getDiscriminator?.();
|
||||
}
|
||||
|
||||
|
||||
protected _onResponse = (instance: BaseType): boolean => {
|
||||
if (this.#instance === instance) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if(this.#discriminator) {
|
||||
if (this.#discriminator) {
|
||||
// Notice if discriminator returns false, we do not want to setInstance.
|
||||
if(this.#discriminator(instance)) {
|
||||
if (this.#discriminator(instance)) {
|
||||
this.setInstance(instance as unknown as ResultType);
|
||||
return true;
|
||||
}
|
||||
@@ -70,6 +71,11 @@ ResultType extends BaseType = BaseType> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @memberof UmbContextConsumer
|
||||
* @description Get the context as a promise.
|
||||
*/
|
||||
public asPromise() {
|
||||
return (
|
||||
this.#promise ??
|
||||
@@ -80,23 +86,25 @@ ResultType extends BaseType = BaseType> {
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @memberof UmbContextConsumer
|
||||
* @description Request the context from the host element.
|
||||
*/
|
||||
public request() {
|
||||
const event = new UmbContextRequestEventImplementation(this.#contextAlias, this._onResponse);
|
||||
const event = new UmbContextRequestEventImplementation(this.#contextAlias, this.#apiAlias, this._onResponse);
|
||||
this.hostElement.dispatchEvent(event);
|
||||
}
|
||||
|
||||
public hostConnected() {
|
||||
// TODO: We need to use closets application element. We need this in order to have separate Backoffice running within or next to each other.
|
||||
window.addEventListener(umbContextProvideEventType, this.#handleNewProvider);
|
||||
window.addEventListener(UMB_CONTEXT_PROVIDE_EVENT_TYPE, this.#handleNewProvider);
|
||||
//window.addEventListener(umbContextUnprovidedEventType, this.#handleRemovedProvider);
|
||||
this.request();
|
||||
}
|
||||
|
||||
public hostDisconnected() {
|
||||
// TODO: We need to use closets application element. We need this in order to have separate Backoffice running within or next to each other.
|
||||
window.removeEventListener(umbContextProvideEventType, this.#handleNewProvider);
|
||||
window.removeEventListener(UMB_CONTEXT_PROVIDE_EVENT_TYPE, this.#handleNewProvider);
|
||||
//window.removeEventListener(umbContextUnprovidedEventType, this.#handleRemovedProvider);
|
||||
}
|
||||
|
||||
@@ -128,7 +136,6 @@ ResultType extends BaseType = BaseType> {
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO: Test destroy scenarios:
|
||||
public destroy() {
|
||||
this.hostDisconnected();
|
||||
this.#callback = undefined;
|
||||
|
||||
@@ -9,13 +9,18 @@ describe('UmbContextRequestEvent', () => {
|
||||
|
||||
const event: UmbContextRequestEvent = new UmbContextRequestEventImplementation(
|
||||
'my-test-context-alias',
|
||||
contextRequestCallback
|
||||
'my-test-api-alias',
|
||||
contextRequestCallback,
|
||||
);
|
||||
|
||||
it('has context', () => {
|
||||
it('has context alias', () => {
|
||||
expect(event.contextAlias).to.eq('my-test-context-alias');
|
||||
});
|
||||
|
||||
it('has api alias', () => {
|
||||
expect(event.apiAlias).to.eq('my-test-api-alias');
|
||||
});
|
||||
|
||||
it('has a callback', () => {
|
||||
expect(event.callback).to.eq(contextRequestCallback);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { UmbContextToken } from '../token/context-token.js';
|
||||
|
||||
export const umbContextRequestEventType = 'umb:context-request';
|
||||
export const umbDebugContextEventType = 'umb:debug-contexts';
|
||||
export const UMB_CONTENT_REQUEST_EVENT_TYPE = 'umb:context-request';
|
||||
export const UMB_DEBUG_CONTEXT_EVENT_TYPE = 'umb:debug-contexts';
|
||||
|
||||
export type UmbContextCallback<T> = (instance: T) => void;
|
||||
|
||||
@@ -10,7 +8,8 @@ export type UmbContextCallback<T> = (instance: T) => void;
|
||||
* @interface UmbContextRequestEvent
|
||||
*/
|
||||
export interface UmbContextRequestEvent<ResultType = unknown> extends Event {
|
||||
readonly contextAlias: string | UmbContextToken<unknown, ResultType>;
|
||||
readonly contextAlias: string;
|
||||
readonly apiAlias: string;
|
||||
readonly callback: (context: ResultType) => boolean;
|
||||
}
|
||||
|
||||
@@ -20,17 +19,21 @@ export interface UmbContextRequestEvent<ResultType = unknown> extends Event {
|
||||
* @extends {Event}
|
||||
* @implements {UmbContextRequestEvent}
|
||||
*/
|
||||
export class UmbContextRequestEventImplementation<ResultType = unknown> extends Event implements UmbContextRequestEvent<ResultType> {
|
||||
export class UmbContextRequestEventImplementation<ResultType = unknown>
|
||||
extends Event
|
||||
implements UmbContextRequestEvent<ResultType>
|
||||
{
|
||||
public constructor(
|
||||
public readonly contextAlias: string | UmbContextToken<any, ResultType>,
|
||||
public readonly callback: (context: ResultType) => boolean
|
||||
public readonly contextAlias: string,
|
||||
public readonly apiAlias: string,
|
||||
public readonly callback: (context: ResultType) => boolean,
|
||||
) {
|
||||
super(umbContextRequestEventType, { bubbles: true, composed: true, cancelable: true });
|
||||
super(UMB_CONTENT_REQUEST_EVENT_TYPE, { bubbles: true, composed: true, cancelable: true });
|
||||
}
|
||||
}
|
||||
|
||||
export class UmbContextDebugRequest extends Event {
|
||||
public constructor(public readonly callback: any) {
|
||||
super(umbDebugContextEventType, { bubbles: true, composed: true, cancelable: false });
|
||||
super(UMB_DEBUG_CONTEXT_EVENT_TYPE, { bubbles: true, composed: true, cancelable: false });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { UmbContextToken } from '../token/context-token.js';
|
||||
|
||||
export const umbContextProvideEventType = 'umb:context-provide';
|
||||
export const UMB_CONTEXT_PROVIDE_EVENT_TYPE = 'umb:context-provide';
|
||||
|
||||
/**
|
||||
* @export
|
||||
@@ -18,15 +18,15 @@ export interface UmbContextProvideEvent extends Event {
|
||||
*/
|
||||
export class UmbContextProvideEventImplementation extends Event implements UmbContextProvideEvent {
|
||||
public constructor(public readonly contextAlias: string | UmbContextToken) {
|
||||
super(umbContextProvideEventType, { bubbles: true, composed: true });
|
||||
super(UMB_CONTEXT_PROVIDE_EVENT_TYPE, { bubbles: true, composed: true });
|
||||
}
|
||||
}
|
||||
|
||||
export const isUmbContextProvideEventType = (event: Event): event is UmbContextProvideEventImplementation => {
|
||||
return event.type === umbContextProvideEventType;
|
||||
return event.type === UMB_CONTEXT_PROVIDE_EVENT_TYPE;
|
||||
};
|
||||
|
||||
export const umbContextUnprovidedEventType = 'umb:context-unprovided';
|
||||
export const UMB_CONTEXT_UNPROVIDED_EVENT_TYPE = 'umb:context-unprovided';
|
||||
|
||||
/**
|
||||
* @export
|
||||
@@ -44,11 +44,14 @@ export interface UmbContextUnprovidedEvent extends Event {
|
||||
* @implements {UmbContextUnprovidedEvent}
|
||||
*/
|
||||
export class UmbContextUnprovidedEventImplementation extends Event implements UmbContextUnprovidedEvent {
|
||||
public constructor(public readonly contextAlias: string | UmbContextToken, public readonly instance: unknown) {
|
||||
super(umbContextUnprovidedEventType, { bubbles: true, composed: true });
|
||||
public constructor(
|
||||
public readonly contextAlias: string | UmbContextToken,
|
||||
public readonly instance: unknown,
|
||||
) {
|
||||
super(UMB_CONTEXT_UNPROVIDED_EVENT_TYPE, { bubbles: true, composed: true });
|
||||
}
|
||||
}
|
||||
|
||||
export const isUmbContextUnprovidedEventType = (event: Event): event is UmbContextUnprovidedEventImplementation => {
|
||||
return event.type === umbContextUnprovidedEventType;
|
||||
return event.type === UMB_CONTEXT_UNPROVIDED_EVENT_TYPE;
|
||||
};
|
||||
|
||||
@@ -42,11 +42,12 @@ describe('UmbContextProvider', () => {
|
||||
it('handles context request events', (done) => {
|
||||
const event = new UmbContextRequestEventImplementation(
|
||||
'my-test-context',
|
||||
'default',
|
||||
(_instance: UmbTestContextProviderClass) => {
|
||||
expect(_instance.prop).to.eq('value from provider');
|
||||
done();
|
||||
return true;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
document.body.dispatchEvent(event);
|
||||
@@ -63,7 +64,7 @@ describe('UmbContextProvider', () => {
|
||||
expect(_instance?.prop).to.eq('value from provider');
|
||||
done();
|
||||
localConsumer.hostDisconnected();
|
||||
}
|
||||
},
|
||||
);
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
UmbContextRequestEvent,
|
||||
umbContextRequestEventType,
|
||||
umbDebugContextEventType,
|
||||
UMB_CONTENT_REQUEST_EVENT_TYPE,
|
||||
UMB_DEBUG_CONTEXT_EVENT_TYPE,
|
||||
} from '../consume/context-request.event.js';
|
||||
import { UmbContextToken } from '../token/context-token.js';
|
||||
import {
|
||||
@@ -17,6 +17,7 @@ export class UmbContextProvider<BaseType = unknown, ResultType extends BaseType
|
||||
protected hostElement: EventTarget;
|
||||
|
||||
protected _contextAlias: string;
|
||||
protected _apiAlias: string;
|
||||
#instance: unknown;
|
||||
|
||||
/**
|
||||
@@ -31,13 +32,20 @@ export class UmbContextProvider<BaseType = unknown, ResultType extends BaseType
|
||||
/**
|
||||
* Creates an instance of UmbContextProvider.
|
||||
* @param {EventTarget} host
|
||||
* @param {string} contextAlias
|
||||
* @param {string | UmbContextToken} contextIdentifier
|
||||
* @param {*} instance
|
||||
* @memberof UmbContextProvider
|
||||
*/
|
||||
constructor(hostElement: EventTarget, contextAlias: string | UmbContextToken<BaseType, ResultType>, instance: ResultType) {
|
||||
constructor(
|
||||
hostElement: EventTarget,
|
||||
contextIdentifier: string | UmbContextToken<BaseType, ResultType>,
|
||||
instance: ResultType,
|
||||
) {
|
||||
this.hostElement = hostElement;
|
||||
this._contextAlias = contextAlias.toString();
|
||||
|
||||
const idSplit = contextIdentifier.toString().split('#');
|
||||
this._contextAlias = idSplit[0];
|
||||
this._apiAlias = idSplit[1] ?? 'default';
|
||||
this.#instance = instance;
|
||||
}
|
||||
|
||||
@@ -52,7 +60,8 @@ export class UmbContextProvider<BaseType = unknown, ResultType extends BaseType
|
||||
// Since the alias matches, we will stop it from bubbling further up. But we still allow it to ask the other Contexts of the element. Hence not calling `event.stopImmediatePropagation();`
|
||||
event.stopPropagation();
|
||||
|
||||
if(event.callback(this.#instance)) {
|
||||
// First and importantly, check that the apiAlias matches and then call the callback. If that returns true then we can stop the event completely.
|
||||
if (this._apiAlias === event.apiAlias && event.callback(this.#instance)) {
|
||||
// Make sure the event not hits any more Contexts as we have found a match.
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
@@ -62,23 +71,23 @@ export class UmbContextProvider<BaseType = unknown, ResultType extends BaseType
|
||||
* @memberof UmbContextProvider
|
||||
*/
|
||||
public hostConnected() {
|
||||
this.hostElement.addEventListener(umbContextRequestEventType, this.#handleContextRequest);
|
||||
this.hostElement.addEventListener(UMB_CONTENT_REQUEST_EVENT_TYPE, this.#handleContextRequest);
|
||||
this.hostElement.dispatchEvent(new UmbContextProvideEventImplementation(this._contextAlias));
|
||||
|
||||
// Listen to our debug event 'umb:debug-contexts'
|
||||
this.hostElement.addEventListener(umbDebugContextEventType, this._handleDebugContextRequest);
|
||||
this.hostElement.addEventListener(UMB_DEBUG_CONTEXT_EVENT_TYPE, this._handleDebugContextRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @memberof UmbContextProvider
|
||||
*/
|
||||
public hostDisconnected() {
|
||||
this.hostElement.removeEventListener(umbContextRequestEventType, this.#handleContextRequest);
|
||||
this.hostElement.removeEventListener(UMB_CONTENT_REQUEST_EVENT_TYPE, this.#handleContextRequest);
|
||||
// Out-commented for now, but kept if we like to reintroduce this:
|
||||
//window.dispatchEvent(new UmbContextUnprovidedEventImplementation(this._contextAlias, this.#instance));
|
||||
|
||||
// Stop listen to our debug event 'umb:debug-contexts'
|
||||
this.hostElement.removeEventListener(umbDebugContextEventType, this._handleDebugContextRequest);
|
||||
this.hostElement.removeEventListener(UMB_DEBUG_CONTEXT_EVENT_TYPE, this._handleDebugContextRequest);
|
||||
}
|
||||
|
||||
private _handleDebugContextRequest = (event: any) => {
|
||||
|
||||
@@ -4,57 +4,164 @@ import { UmbContextProvider } from '../provide/context-provider.js';
|
||||
import { UmbContextToken } from './context-token.js';
|
||||
|
||||
const testContextAlias = 'my-test-context';
|
||||
const testApiAlias = 'my-test-api';
|
||||
|
||||
class UmbTestContextTokenClass {
|
||||
prop = 'value from provider';
|
||||
}
|
||||
|
||||
describe('UmbContextToken', () => {
|
||||
const contextToken = new UmbContextToken<UmbTestContextTokenClass>(testContextAlias);
|
||||
const typedProvider = new UmbContextProvider(document.body, contextToken, new UmbTestContextTokenClass());
|
||||
typedProvider.hostConnected();
|
||||
describe('Simple context token', () => {
|
||||
const contextToken = new UmbContextToken<UmbTestContextTokenClass>(testContextAlias);
|
||||
const typedProvider = new UmbContextProvider(document.body, contextToken, new UmbTestContextTokenClass());
|
||||
typedProvider.hostConnected();
|
||||
|
||||
after(() => {
|
||||
typedProvider.hostDisconnected();
|
||||
after(() => {
|
||||
typedProvider.hostDisconnected();
|
||||
});
|
||||
|
||||
it('toString returns the alias', () => {
|
||||
expect(contextToken.toString()).to.eq(testContextAlias + '#' + 'default');
|
||||
});
|
||||
|
||||
it('can be used to consume a context API', (done) => {
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
contextToken,
|
||||
(_instance: UmbTestContextTokenClass | undefined) => {
|
||||
expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
|
||||
expect(_instance?.prop).to.eq('value from provider');
|
||||
done();
|
||||
localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
|
||||
},
|
||||
);
|
||||
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
|
||||
it('gives the same result when using the string alias', (done) => {
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
testContextAlias,
|
||||
(_instance: UmbTestContextTokenClass | undefined) => {
|
||||
expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
|
||||
expect(_instance?.prop).to.eq('value from provider');
|
||||
done();
|
||||
localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
|
||||
},
|
||||
);
|
||||
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
});
|
||||
|
||||
it('toString returns the alias', () => {
|
||||
expect(contextToken.toString()).to.eq(testContextAlias);
|
||||
describe('Context Token with alternative api alias', () => {
|
||||
const contextToken = new UmbContextToken<UmbTestContextTokenClass>(testContextAlias, testApiAlias);
|
||||
const typedProvider = new UmbContextProvider(document.body, contextToken, new UmbTestContextTokenClass());
|
||||
typedProvider.hostConnected();
|
||||
|
||||
after(() => {
|
||||
typedProvider.hostDisconnected();
|
||||
});
|
||||
|
||||
it('toString returns the alias', () => {
|
||||
expect(contextToken.toString()).to.eq(testContextAlias + '#' + testApiAlias);
|
||||
});
|
||||
|
||||
it('can be used to consume a context API', (done) => {
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
contextToken,
|
||||
(_instance: UmbTestContextTokenClass | undefined) => {
|
||||
expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
|
||||
expect(_instance?.prop).to.eq('value from provider');
|
||||
done();
|
||||
localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
|
||||
},
|
||||
);
|
||||
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
|
||||
it('gives the same result when using the string alias', (done) => {
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
testContextAlias,
|
||||
(_instance: UmbTestContextTokenClass | undefined) => {
|
||||
expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
|
||||
expect(_instance?.prop).to.eq('value from provider');
|
||||
done();
|
||||
localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
|
||||
},
|
||||
);
|
||||
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
});
|
||||
|
||||
it('can be used to consume a context API', (done) => {
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
contextToken,
|
||||
(_instance: UmbTestContextTokenClass | undefined) => {
|
||||
expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
|
||||
expect(_instance?.prop).to.eq('value from provider');
|
||||
done();
|
||||
localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
|
||||
}
|
||||
);
|
||||
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
|
||||
it('gives the same result when using the string alias', (done) => {
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
describe('Context Token with discriminator method', () => {
|
||||
const contextToken = new UmbContextToken<UmbTestContextTokenClass>(
|
||||
testContextAlias,
|
||||
(_instance: UmbTestContextTokenClass | undefined) => {
|
||||
expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
|
||||
expect(_instance?.prop).to.eq('value from provider');
|
||||
done();
|
||||
localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
|
||||
}
|
||||
undefined,
|
||||
(instance): instance is UmbTestContextTokenClass => instance.prop === 'value from provider',
|
||||
);
|
||||
const typedProvider = new UmbContextProvider(document.body, contextToken, new UmbTestContextTokenClass());
|
||||
typedProvider.hostConnected();
|
||||
|
||||
localConsumer.hostConnected();
|
||||
after(() => {
|
||||
typedProvider.hostDisconnected();
|
||||
});
|
||||
|
||||
it('toString returns the alias', () => {
|
||||
expect(contextToken.toString()).to.eq(testContextAlias + '#' + 'default');
|
||||
});
|
||||
|
||||
it('can be used to consume a context API', (done) => {
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
contextToken,
|
||||
(_instance: UmbTestContextTokenClass | undefined) => {
|
||||
expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
|
||||
expect(_instance?.prop).to.eq('value from provider');
|
||||
done();
|
||||
localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
|
||||
},
|
||||
);
|
||||
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
|
||||
it('gives the same result when using the string alias', (done) => {
|
||||
const element = document.createElement('div');
|
||||
document.body.appendChild(element);
|
||||
|
||||
const localConsumer = new UmbContextConsumer(
|
||||
element,
|
||||
testContextAlias,
|
||||
(_instance: UmbTestContextTokenClass | undefined) => {
|
||||
expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
|
||||
expect(_instance?.prop).to.eq('value from provider');
|
||||
done();
|
||||
localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
|
||||
},
|
||||
);
|
||||
|
||||
localConsumer.hostConnected();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
export type UmbContextDiscriminator<BaseType, DiscriminatorResult extends BaseType> = (
|
||||
instance: BaseType,
|
||||
) => instance is DiscriminatorResult;
|
||||
|
||||
export type UmbContextDiscriminator<BaseType, DiscriminatorResult extends BaseType> = (instance: BaseType) => instance is DiscriminatorResult;
|
||||
|
||||
export class UmbContextToken<
|
||||
BaseType = unknown,
|
||||
ResultType extends BaseType = BaseType> {
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @class UmbContextToken
|
||||
* @template BaseType - A generic type of the API before decimated.
|
||||
* @template ResultType - A concrete type of the API after decimation, use this when you apply a discriminator method. Note this is optional and defaults to the BaseType.
|
||||
*/
|
||||
export class UmbContextToken<BaseType = unknown, ResultType extends BaseType = BaseType> {
|
||||
#discriminator: UmbContextDiscriminator<BaseType, ResultType> | undefined;
|
||||
/**
|
||||
* Get the type of the token
|
||||
@@ -18,12 +22,23 @@ ResultType extends BaseType = BaseType> {
|
||||
readonly TYPE: ResultType = undefined as never;
|
||||
|
||||
/**
|
||||
* @param alias Unique identifier for the token
|
||||
* @param contextAlias Unique identifier for the context
|
||||
* @param apiAlias Unique identifier for the api
|
||||
* @param discriminator A discriminator that will be used to discriminate the API — testing if the API lives up to a certain requirement. If the API does not meet the requirement then the consumer will not receive this API.
|
||||
*/
|
||||
constructor(protected alias: string, discriminator?: UmbContextDiscriminator<BaseType, ResultType>) {
|
||||
constructor(
|
||||
protected contextAlias: string,
|
||||
protected apiAlias: string = 'default',
|
||||
discriminator?: UmbContextDiscriminator<BaseType, ResultType>,
|
||||
) {
|
||||
this.#discriminator = discriminator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the discriminator method for the token
|
||||
*
|
||||
* @returns the discriminator method
|
||||
*/
|
||||
getDiscriminator(): UmbContextDiscriminator<BaseType, ResultType> | undefined {
|
||||
return this.#discriminator;
|
||||
}
|
||||
@@ -35,8 +50,6 @@ ResultType extends BaseType = BaseType> {
|
||||
* @returns the unique alias of the token
|
||||
*/
|
||||
toString(): string {
|
||||
return this.alias;
|
||||
return this.contextAlias + '#' + this.apiAlias;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbDataTypeData } from '../../data/data-type.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const copyHandlers = [
|
||||
rest.post(umbracoPath(`${slug}/:id/copy`), async (req, res, ctx) => {
|
||||
rest.post(umbracoPath(`${UMB_SLUG}/:id/copy`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbDataTypeData } from '../../data/data-type.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const detailHandlers = [
|
||||
rest.post(umbracoPath(`${slug}`), async (req, res, ctx) => {
|
||||
rest.post(umbracoPath(`${UMB_SLUG}`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
|
||||
@@ -13,7 +13,7 @@ export const detailHandlers = [
|
||||
return res(ctx.status(200));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath(`${slug}/:id`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/:id`), (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
@@ -22,7 +22,7 @@ export const detailHandlers = [
|
||||
return res(ctx.status(200), ctx.json(dataType));
|
||||
}),
|
||||
|
||||
rest.put(umbracoPath(`${slug}/:id`), async (req, res, ctx) => {
|
||||
rest.put(umbracoPath(`${UMB_SLUG}/:id`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
const data = await req.json();
|
||||
@@ -33,7 +33,7 @@ export const detailHandlers = [
|
||||
return res(ctx.status(200), ctx.json(saved));
|
||||
}),
|
||||
|
||||
rest.delete<string>(umbracoPath(`${slug}/:id`), async (req, res, ctx) => {
|
||||
rest.delete<string>(umbracoPath(`${UMB_SLUG}/:id`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbDataTypeData } from '../../data/data-type.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
import { ProblemDetails } from '@umbraco-cms/backoffice/backend-api';
|
||||
|
||||
export const folderHandlers = [
|
||||
rest.post(umbracoPath(`${slug}/folder`), async (req, res, ctx) => {
|
||||
rest.post(umbracoPath(`${UMB_SLUG}/folder`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
|
||||
@@ -14,7 +14,7 @@ export const folderHandlers = [
|
||||
return res(ctx.status(200));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath(`${slug}/folder/:id`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/folder/:id`), (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
@@ -23,7 +23,7 @@ export const folderHandlers = [
|
||||
return res(ctx.status(200), ctx.json(dataType));
|
||||
}),
|
||||
|
||||
rest.put(umbracoPath(`${slug}/folder/:id`), async (req, res, ctx) => {
|
||||
rest.put(umbracoPath(`${UMB_SLUG}/folder/:id`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
const data = await req.json();
|
||||
@@ -34,7 +34,7 @@ export const folderHandlers = [
|
||||
return res(ctx.status(200));
|
||||
}),
|
||||
|
||||
rest.delete(umbracoPath(`${slug}/folder/:id`), async (req, res, ctx) => {
|
||||
rest.delete(umbracoPath(`${UMB_SLUG}/folder/:id`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
@@ -48,7 +48,7 @@ export const folderHandlers = [
|
||||
status: 404,
|
||||
type: 'error',
|
||||
detail: 'Not Found',
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbDataTypeData } from '../../data/data-type.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const itemHandlers = [
|
||||
rest.get(umbracoPath(`${slug}/item`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/item`), (req, res, ctx) => {
|
||||
const ids = req.url.searchParams.getAll('id');
|
||||
if (!ids) return;
|
||||
const items = umbDataTypeData.getItems(ids);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbDataTypeData } from '../../data/data-type.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const moveHandlers = [
|
||||
rest.post(umbracoPath(`${slug}/:id/move`), async (req, res, ctx) => {
|
||||
rest.post(umbracoPath(`${UMB_SLUG}/:id/move`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const slug = '/data-type';
|
||||
export const UMB_SLUG = '/data-type';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbDataTypeData } from '../../data/data-type.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const treeHandlers = [
|
||||
rest.get(umbracoPath(`/tree${slug}/root`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`/tree${UMB_SLUG}/root`), (req, res, ctx) => {
|
||||
const rootItems = umbDataTypeData.getTreeRoot();
|
||||
const response = {
|
||||
total: rootItems.length,
|
||||
@@ -13,7 +13,7 @@ export const treeHandlers = [
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath(`/tree${slug}/children`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`/tree${UMB_SLUG}/children`), (req, res, ctx) => {
|
||||
const parentId = req.url.searchParams.get('parentId');
|
||||
if (!parentId) return;
|
||||
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbDocumentTypeData } from '../../data/document-type.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.get(umbracoPath(`${slug}/:id`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/:id`), (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
const document = umbDocumentTypeData.getById(id);
|
||||
return res(ctx.status(200), ctx.json(document));
|
||||
}),
|
||||
|
||||
rest.delete(umbracoPath(`${slug}/:id`), (req, res, ctx) => {
|
||||
rest.delete(umbracoPath(`${UMB_SLUG}/:id`), (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
const document = umbDocumentTypeData.getById(id);
|
||||
return res(ctx.status(200), ctx.json(document));
|
||||
}),
|
||||
|
||||
rest.put(umbracoPath(`${slug}/:id`), async (req, res, ctx) => {
|
||||
rest.put(umbracoPath(`${UMB_SLUG}/:id`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
const data = await req.json();
|
||||
@@ -27,7 +27,7 @@ export const handlers = [
|
||||
return res(ctx.status(200), ctx.json(saved));
|
||||
}),
|
||||
|
||||
rest.post(umbracoPath(`${slug}`), async (req, res, ctx) => {
|
||||
rest.post(umbracoPath(`${UMB_SLUG}`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
umbDocumentTypeData.insert(data);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbDocumentTypeData } from '../../data/document-type.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.get(umbracoPath(`${slug}/item`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/item`), (req, res, ctx) => {
|
||||
const ids = req.url.searchParams.getAll('id');
|
||||
if (!ids) return;
|
||||
const items = umbDocumentTypeData.getItems(ids);
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const slug = '/document-type';
|
||||
export const UMB_SLUG = '/document-type';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbDocumentTypeData } from '../../data/document-type.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.get(umbracoPath(`/tree${slug}/root`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`/tree${UMB_SLUG}/root`), (req, res, ctx) => {
|
||||
const rootItems = umbDocumentTypeData.getTreeRoot();
|
||||
const response = {
|
||||
total: rootItems.length,
|
||||
@@ -13,7 +13,7 @@ export const handlers = [
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath(`/tree${slug}/children`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`/tree${UMB_SLUG}/children`), (req, res, ctx) => {
|
||||
const parentId = req.url.searchParams.get('parentId');
|
||||
if (!parentId) return;
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbDocumentData } from '../../data/document.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.get(umbracoPath(`${slug}/item`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/item`), (req, res, ctx) => {
|
||||
const ids = req.url.searchParams.getAll('id');
|
||||
if (!ids) return;
|
||||
const items = umbDocumentData.getItems(ids);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbDocumentData } from '../../data/document.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
// TODO: temp handlers until we have a real API
|
||||
export const handlers = [
|
||||
rest.get(umbracoPath(`${slug}/:id/permissions`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/:id/permissions`), (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
const response = umbDocumentData.getUserPermissionsForDocument(id);
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const slug = '/document';
|
||||
export const UMB_SLUG = '/document';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbMediaTypeData } from '../../data/media-type.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const detailHandlers = [
|
||||
rest.post(umbracoPath(`${slug}`), async (req, res, ctx) => {
|
||||
rest.post(umbracoPath(`${UMB_SLUG}`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
|
||||
@@ -13,7 +13,7 @@ export const detailHandlers = [
|
||||
return res(ctx.status(200));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath(`${slug}/:id`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/:id`), (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
@@ -22,7 +22,7 @@ export const detailHandlers = [
|
||||
return res(ctx.status(200), ctx.json(data));
|
||||
}),
|
||||
|
||||
rest.put(umbracoPath(`${slug}/:id`), async (req, res, ctx) => {
|
||||
rest.put(umbracoPath(`${UMB_SLUG}/:id`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
const data = await req.json();
|
||||
@@ -33,7 +33,7 @@ export const detailHandlers = [
|
||||
return res(ctx.status(200), ctx.json(saved));
|
||||
}),
|
||||
|
||||
rest.delete<string>(umbracoPath(`${slug}/:id`), async (req, res, ctx) => {
|
||||
rest.delete<string>(umbracoPath(`${UMB_SLUG}/:id`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbMediaTypeData } from '../../data/media-type.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const itemHandlers = [
|
||||
rest.get(umbracoPath(`${slug}/item`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/item`), (req, res, ctx) => {
|
||||
const ids = req.url.searchParams.getAll('id');
|
||||
if (!ids) return;
|
||||
const items = umbMediaTypeData.getItems(ids);
|
||||
return res(ctx.status(200), ctx.json(items));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath(`/tree${slug}/item`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`/tree${UMB_SLUG}/item`), (req, res, ctx) => {
|
||||
const ids = req.url.searchParams.getAll('id');
|
||||
if (!ids) return;
|
||||
const items = umbMediaTypeData.getTreeItems(ids);
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const slug = '/media-type';
|
||||
export const UMB_SLUG = '/media-type';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbMediaTypeData } from '../../data/media-type.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const treeHandlers = [
|
||||
rest.get(umbracoPath(`/tree${slug}/root`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`/tree${UMB_SLUG}/root`), (req, res, ctx) => {
|
||||
const rootItems = umbMediaTypeData.getTreeRoot();
|
||||
const response = {
|
||||
total: rootItems.length,
|
||||
@@ -13,7 +13,7 @@ export const treeHandlers = [
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath(`/tree${slug}/children`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`/tree${UMB_SLUG}/children`), (req, res, ctx) => {
|
||||
const parentId = req.url.searchParams.get('parentId');
|
||||
if (!parentId) return;
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbUserGroupData } from '../../data/user-group.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const collectionHandlers = [
|
||||
rest.get(umbracoPath(`${slug}`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}`), (req, res, ctx) => {
|
||||
const response = umbUserGroupData.getAll();
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbUserGroupData } from '../../data/user-group.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const detailHandlers = [
|
||||
rest.post(umbracoPath(`${slug}`), async (req, res, ctx) => {
|
||||
rest.post(umbracoPath(`${UMB_SLUG}`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
|
||||
@@ -13,7 +13,7 @@ export const detailHandlers = [
|
||||
return res(ctx.status(200));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath(`${slug}/:id`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/:id`), (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
@@ -22,7 +22,7 @@ export const detailHandlers = [
|
||||
return res(ctx.status(200), ctx.json(dataType));
|
||||
}),
|
||||
|
||||
rest.put(umbracoPath(`${slug}/:id`), async (req, res, ctx) => {
|
||||
rest.put(umbracoPath(`${UMB_SLUG}/:id`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
const data = await req.json();
|
||||
@@ -33,7 +33,7 @@ export const detailHandlers = [
|
||||
return res(ctx.status(200));
|
||||
}),
|
||||
|
||||
rest.delete<string>(umbracoPath(`${slug}/:id`), async (req, res, ctx) => {
|
||||
rest.delete<string>(umbracoPath(`${UMB_SLUG}/:id`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbUserGroupData } from '../../data/user-group.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const itemHandlers = [
|
||||
rest.get(umbracoPath(`${slug}/item`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/item`), (req, res, ctx) => {
|
||||
const ids = req.url.searchParams.getAll('id');
|
||||
if (!ids) return;
|
||||
const items = umbUserGroupData.getItems(ids);
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const slug = '/user-group';
|
||||
export const UMB_SLUG = '/user-group';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { ChangePasswordUserRequestModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.post<ChangePasswordUserRequestModel>(umbracoPath(`${slug}/change-password/:id`), async (req, res, ctx) => {
|
||||
rest.post<ChangePasswordUserRequestModel>(umbracoPath(`${UMB_SLUG}/change-password/:id`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
if (!data.newPassword) return;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbUsersData } from '../../data/user.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.get(umbracoPath(`${slug}/current`), (_req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/current`), (_req, res, ctx) => {
|
||||
const loggedInUser = umbUsersData.getCurrentUser();
|
||||
return res(ctx.status(200), ctx.json(loggedInUser));
|
||||
}),
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbUsersData } from '../../data/user.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.get(umbracoPath(`${slug}`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}`), (req, res, ctx) => {
|
||||
const response = umbUsersData.getAll();
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.post(umbracoPath(`${slug}`), async (req, res, ctx) => {
|
||||
rest.post(umbracoPath(`${UMB_SLUG}`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
|
||||
@@ -18,7 +18,7 @@ export const handlers = [
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath(`${slug}/:id`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/:id`), (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
@@ -27,7 +27,7 @@ export const handlers = [
|
||||
return res(ctx.status(200), ctx.json(item));
|
||||
}),
|
||||
|
||||
rest.put(umbracoPath(`${slug}/:id`), async (req, res, ctx) => {
|
||||
rest.put(umbracoPath(`${UMB_SLUG}/:id`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
const data = await req.json();
|
||||
@@ -38,7 +38,7 @@ export const handlers = [
|
||||
return res(ctx.status(200));
|
||||
}),
|
||||
|
||||
rest.delete<string>(umbracoPath(`${slug}/:id`), async (req, res, ctx) => {
|
||||
rest.delete<string>(umbracoPath(`${UMB_SLUG}/:id`), async (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbUsersData } from '../../data/user.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { DisableUserRequestModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.post<DisableUserRequestModel>(umbracoPath(`${slug}/disable`), async (req, res, ctx) => {
|
||||
rest.post<DisableUserRequestModel>(umbracoPath(`${UMB_SLUG}/disable`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
if (!data.userIds) return;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbUsersData } from '../../data/user.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { EnableUserRequestModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.post<EnableUserRequestModel>(umbracoPath(`${slug}/enable`), async (req, res, ctx) => {
|
||||
rest.post<EnableUserRequestModel>(umbracoPath(`${UMB_SLUG}/enable`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
if (!data.userIds) return;
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbUsersData } from '../../data/user.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.get(umbracoPath(`${slug}/filter`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/filter`), (req, res, ctx) => {
|
||||
const skip = Number(req.url.searchParams.get('skip'));
|
||||
const take = Number(req.url.searchParams.get('take'));
|
||||
const orderBy = req.url.searchParams.get('orderBy');
|
||||
const orderDirection = req.url.searchParams.get('orderDirection');
|
||||
const userGroupIds = req.url.searchParams.getAll('userGroupIds');
|
||||
const userStates = req.url.searchParams.getAll('userStates');
|
||||
const filter = req.url.searchParams.get('filter');
|
||||
|
||||
const skip = Number(req.url.searchParams.get('skip'));
|
||||
const take = Number(req.url.searchParams.get('take'));
|
||||
const orderBy = req.url.searchParams.get('orderBy');
|
||||
const orderDirection = req.url.searchParams.get('orderDirection');
|
||||
const userGroupIds = req.url.searchParams.getAll('userGroupIds');
|
||||
const userStates = req.url.searchParams.getAll('userStates');
|
||||
const filter = req.url.searchParams.get('filter');
|
||||
const options = {
|
||||
skip: skip || undefined,
|
||||
take: take || undefined,
|
||||
orderBy: orderBy || undefined,
|
||||
orderDirection: orderDirection || undefined,
|
||||
userGroupIds: userGroupIds.length > 0 ? userGroupIds : undefined,
|
||||
userStates: userStates.length > 0 ? userStates : undefined,
|
||||
filter: filter || undefined,
|
||||
};
|
||||
|
||||
const options = {
|
||||
skip: skip || undefined,
|
||||
take: take || undefined,
|
||||
orderBy: orderBy || undefined,
|
||||
orderDirection: orderDirection || undefined,
|
||||
userGroupIds: userGroupIds.length > 0 ? userGroupIds : undefined,
|
||||
userStates: userStates.length > 0 ? userStates : undefined,
|
||||
filter: filter || undefined,
|
||||
};
|
||||
|
||||
const response = umbUsersData.filter(options);
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
const response = umbUsersData.filter(options);
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbUsersData } from '../../data/user.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { InviteUserRequestModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.post<InviteUserRequestModel>(umbracoPath(`${slug}/invite`), async (req, res, ctx) => {
|
||||
rest.post<InviteUserRequestModel>(umbracoPath(`${UMB_SLUG}/invite`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
|
||||
@@ -14,7 +14,7 @@ export const handlers = [
|
||||
return res(ctx.status(200));
|
||||
}),
|
||||
|
||||
rest.post<any>(umbracoPath(`${slug}/invite/resend`), async (req, res, ctx) => {
|
||||
rest.post<any>(umbracoPath(`${UMB_SLUG}/invite/resend`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbUsersData } from '../../data/user.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.get(umbracoPath(`${slug}/item`), (req, res, ctx) => {
|
||||
rest.get(umbracoPath(`${UMB_SLUG}/item`), (req, res, ctx) => {
|
||||
const ids = req.url.searchParams.getAll('id');
|
||||
if (!ids) return;
|
||||
const items = umbUsersData.getItems(ids);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbUsersData } from '../../data/user.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.post(umbracoPath(`${slug}/set-user-groups`), async (req, res, ctx) => {
|
||||
rest.post(umbracoPath(`${UMB_SLUG}/set-user-groups`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const slug = '/user';
|
||||
export const UMB_SLUG = '/user';
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbUsersData } from '../../data/user.data.js';
|
||||
import { slug } from './slug.js';
|
||||
import { UMB_SLUG } from './slug.js';
|
||||
import { UnlockUsersRequestModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.post<UnlockUsersRequestModel>(umbracoPath(`${slug}/unlock`), async (req, res, ctx) => {
|
||||
rest.post<UnlockUsersRequestModel>(umbracoPath(`${UMB_SLUG}/unlock`), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
if (!data.userIds) return;
|
||||
|
||||
@@ -12,9 +12,6 @@ export class UmbCollectionViewBundleElement extends UmbLitElement {
|
||||
@state()
|
||||
_currentView?: ManifestCollectionView;
|
||||
|
||||
@state()
|
||||
private _isOpen = false;
|
||||
|
||||
@state()
|
||||
private _collectionRootPathname = '';
|
||||
|
||||
@@ -33,56 +30,65 @@ export class UmbCollectionViewBundleElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
#observeCurrentView() {
|
||||
this.observe(this.#collectionContext!.currentView, (view) => {
|
||||
this._currentView = view;
|
||||
}, 'umbCurrentCollectionViewObserver');
|
||||
this.observe(
|
||||
this.#collectionContext!.currentView,
|
||||
(view) => {
|
||||
//TODO: This is not called when the view is changed
|
||||
this._currentView = view;
|
||||
},
|
||||
'umbCurrentCollectionViewObserver',
|
||||
);
|
||||
}
|
||||
|
||||
#observeViews() {
|
||||
this.observe(this.#collectionContext!.views, (views) => {
|
||||
this._views = views;
|
||||
}, 'umbCollectionViewsObserver');
|
||||
this.observe(
|
||||
this.#collectionContext!.views,
|
||||
(views) => {
|
||||
this._views = views;
|
||||
},
|
||||
'umbCollectionViewsObserver',
|
||||
);
|
||||
}
|
||||
|
||||
#toggleDropdown() {
|
||||
this._isOpen = !this._isOpen;
|
||||
}
|
||||
|
||||
#closeDropdown() {
|
||||
this._isOpen = false;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`${this.#renderLayoutButton()}`;
|
||||
}
|
||||
|
||||
#renderLayoutButton() {
|
||||
if (!this._currentView) return nothing;
|
||||
|
||||
return html` <umb-dropdown .open="${this._isOpen}" @close=${this.#closeDropdown}>
|
||||
<uui-button slot="trigger" label="status" @click=${this.#toggleDropdown}
|
||||
>${this.#renderItemDisplay(this._currentView)}</uui-button
|
||||
>
|
||||
<div slot="dropdown" class="filter-dropdown">${this._views.map((view) => this.#renderItem(view))}</div>
|
||||
</umb-dropdown>`;
|
||||
return html`
|
||||
<uui-button compact popovertarget="collection-view-bundle-popover" label="status">
|
||||
${this.#renderItemDisplay(this._currentView)}
|
||||
</uui-button>
|
||||
<uui-popover-container id="collection-view-bundle-popover" popover placement="bottom">
|
||||
<umb-popover-layout>
|
||||
<div class="filter-dropdown">${this._views.map((view) => this.#renderItem(view))}</div>
|
||||
</umb-popover-layout>
|
||||
</uui-popover-container>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderItem(view: ManifestCollectionView) {
|
||||
return html`<a href="${this._collectionRootPathname}/${view.meta.pathName}">${this.#renderItemDisplay(view)}</a>`;
|
||||
return html`
|
||||
<uui-button compact href="${this._collectionRootPathname}/${view.meta.pathName}">
|
||||
${this.#renderItemDisplay(view)} <span class="label">${view.meta.label}</span>
|
||||
</uui-button>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderItemDisplay(view: ManifestCollectionView) {
|
||||
return html`<span class="item"><uui-icon name=${view.meta.icon}></uui-icon> ${view.meta.label}</span>`;
|
||||
return html`<uui-icon name=${view.meta.icon}></uui-icon>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
.item {
|
||||
:host {
|
||||
--uui-button-content-align: left;
|
||||
}
|
||||
|
||||
a {
|
||||
display: block;
|
||||
.label {
|
||||
margin-left: var(--uui-size-space-1);
|
||||
}
|
||||
.filter-dropdown {
|
||||
display: flex;
|
||||
gap: var(--uui-size-space-3);
|
||||
flex-direction: column;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@@ -33,3 +33,4 @@ export * from './ref-property-editor-ui/index.js';
|
||||
export * from './table/index.js';
|
||||
export * from './tooltip-menu/index.js';
|
||||
export * from './variant-selector/index.js';
|
||||
export * from './popover-layout/index.js';
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import './popover-layout.element.js';
|
||||
|
||||
export * from './popover-layout.element.js';
|
||||
@@ -0,0 +1,33 @@
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
|
||||
// TODO: maybe move this to UI Library.
|
||||
// TODO: add overwrites for customization.
|
||||
@customElement('umb-popover-layout')
|
||||
export class UmbPopoverLayoutElement extends UmbLitElement {
|
||||
render() {
|
||||
return html`<slot></slot>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
:host {
|
||||
background-color: var(--uui-color-surface);
|
||||
display: block;
|
||||
border: 1px solid var(--uui-color-border);
|
||||
border-radius: var(--uui-border-radius);
|
||||
box-shadow: var(--uui-shadow-depth-3);
|
||||
padding: var(--uui-size-space-3);
|
||||
overflow: clip;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-popover-layout': UmbPopoverLayoutElement;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { UmbCultureRepository } from './culture.repository.js';
|
||||
import { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const CULTURE_REPOSITORY_ALIAS = 'Umb.Repository.Culture';
|
||||
export const UMB_CULTURE_REPOSITORY_ALIAS = 'Umb.Repository.Culture';
|
||||
|
||||
const repository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: CULTURE_REPOSITORY_ALIAS,
|
||||
alias: UMB_CULTURE_REPOSITORY_ALIAS,
|
||||
name: 'Cultures Repository',
|
||||
api: UmbCultureRepository,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DATA_TYPE_ENTITY_TYPE } from '../../entity.js';
|
||||
import { COPY_DATA_TYPE_REPOSITORY_ALIAS } from '../../repository/copy/manifests.js';
|
||||
import { UMB_DATA_TYPE_ENTITY_TYPE } from '../../entity.js';
|
||||
import { UMB_COPY_DATA_TYPE_REPOSITORY_ALIAS } from '../../repository/copy/manifests.js';
|
||||
import { UmbCopyDataTypeEntityAction } from './copy.action.js';
|
||||
import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
@@ -13,8 +13,8 @@ const entityActions: Array<ManifestTypes> = [
|
||||
meta: {
|
||||
icon: 'icon-documents',
|
||||
label: 'Copy to...',
|
||||
repositoryAlias: COPY_DATA_TYPE_REPOSITORY_ALIAS,
|
||||
entityTypes: [DATA_TYPE_ENTITY_TYPE],
|
||||
repositoryAlias: UMB_COPY_DATA_TYPE_REPOSITORY_ALIAS,
|
||||
entityTypes: [UMB_DATA_TYPE_ENTITY_TYPE],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { DATA_TYPE_ENTITY_TYPE, DATA_TYPE_FOLDER_ENTITY_TYPE, DATA_TYPE_ROOT_ENTITY_TYPE } from '../../entity.js';
|
||||
import { DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/detail/manifests.js';
|
||||
import {
|
||||
UMB_DATA_TYPE_ENTITY_TYPE,
|
||||
UMB_DATA_TYPE_FOLDER_ENTITY_TYPE,
|
||||
UMB_DATA_TYPE_ROOT_ENTITY_TYPE,
|
||||
} from '../../entity.js';
|
||||
import { UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/detail/manifests.js';
|
||||
import { UmbCreateDataTypeEntityAction } from './create.action.js';
|
||||
import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
@@ -13,8 +17,8 @@ const entityActions: Array<ManifestTypes> = [
|
||||
meta: {
|
||||
icon: 'icon-add',
|
||||
label: 'Create...',
|
||||
repositoryAlias: DATA_TYPE_DETAIL_REPOSITORY_ALIAS,
|
||||
entityTypes: [DATA_TYPE_ENTITY_TYPE, DATA_TYPE_ROOT_ENTITY_TYPE, DATA_TYPE_FOLDER_ENTITY_TYPE],
|
||||
repositoryAlias: UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS,
|
||||
entityTypes: [UMB_DATA_TYPE_ENTITY_TYPE, UMB_DATA_TYPE_ROOT_ENTITY_TYPE, UMB_DATA_TYPE_FOLDER_ENTITY_TYPE],
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DATA_TYPE_FOLDER_REPOSITORY_ALIAS } from '../../../repository/folder/manifests.js';
|
||||
import { UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS } from '../../../repository/folder/manifests.js';
|
||||
import { UmbDataTypeCreateOptionsModalData } from './index.js';
|
||||
import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
@@ -30,7 +30,7 @@ export class UmbDataTypeCreateOptionsModalElement extends UmbLitElement {
|
||||
#onClick(event: PointerEvent) {
|
||||
event.stopPropagation();
|
||||
const folderModalHandler = this.#modalContext?.open(UMB_FOLDER_MODAL, {
|
||||
repositoryAlias: DATA_TYPE_FOLDER_REPOSITORY_ALIAS,
|
||||
repositoryAlias: UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS,
|
||||
});
|
||||
folderModalHandler?.onSubmit().then(() => this.modalContext?.submit());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DATA_TYPE_FOLDER_ENTITY_TYPE, DATA_TYPE_ENTITY_TYPE } from '../entity.js';
|
||||
import { DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../repository/detail/manifests.js';
|
||||
import { UMB_DATA_TYPE_FOLDER_ENTITY_TYPE, UMB_DATA_TYPE_ENTITY_TYPE } from '../entity.js';
|
||||
import { UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../repository/detail/manifests.js';
|
||||
import { manifests as createManifests } from './create/manifests.js';
|
||||
import { manifests as moveManifests } from './move/manifests.js';
|
||||
import { manifests as copyManifests } from './copy/manifests.js';
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
UmbFolderUpdateEntityAction,
|
||||
} from '@umbraco-cms/backoffice/entity-action';
|
||||
import { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { DATA_TYPE_FOLDER_REPOSITORY_ALIAS } from '../repository/folder/manifests.js';
|
||||
import { UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS } from '../repository/folder/manifests.js';
|
||||
|
||||
const entityActions: Array<ManifestEntityAction> = [
|
||||
{
|
||||
@@ -22,8 +22,8 @@ const entityActions: Array<ManifestEntityAction> = [
|
||||
meta: {
|
||||
icon: 'icon-trash',
|
||||
label: 'Delete...',
|
||||
repositoryAlias: DATA_TYPE_DETAIL_REPOSITORY_ALIAS,
|
||||
entityTypes: [DATA_TYPE_ENTITY_TYPE],
|
||||
repositoryAlias: UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS,
|
||||
entityTypes: [UMB_DATA_TYPE_ENTITY_TYPE],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -35,8 +35,8 @@ const entityActions: Array<ManifestEntityAction> = [
|
||||
meta: {
|
||||
icon: 'icon-trash',
|
||||
label: 'Delete Folder...',
|
||||
repositoryAlias: DATA_TYPE_FOLDER_REPOSITORY_ALIAS,
|
||||
entityTypes: [DATA_TYPE_ENTITY_TYPE, DATA_TYPE_FOLDER_ENTITY_TYPE],
|
||||
repositoryAlias: UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS,
|
||||
entityTypes: [UMB_DATA_TYPE_ENTITY_TYPE, UMB_DATA_TYPE_FOLDER_ENTITY_TYPE],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -48,8 +48,8 @@ const entityActions: Array<ManifestEntityAction> = [
|
||||
meta: {
|
||||
icon: 'icon-edit',
|
||||
label: 'Rename Folder...',
|
||||
repositoryAlias: DATA_TYPE_FOLDER_REPOSITORY_ALIAS,
|
||||
entityTypes: [DATA_TYPE_ENTITY_TYPE, DATA_TYPE_FOLDER_ENTITY_TYPE],
|
||||
repositoryAlias: UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS,
|
||||
entityTypes: [UMB_DATA_TYPE_ENTITY_TYPE, UMB_DATA_TYPE_FOLDER_ENTITY_TYPE],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DATA_TYPE_ENTITY_TYPE } from '../../entity.js';
|
||||
import { MOVE_DATA_TYPE_REPOSITORY_ALIAS } from '../../repository/move/manifests.js';
|
||||
import { UMB_DATA_TYPE_ENTITY_TYPE } from '../../entity.js';
|
||||
import { UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from '../../repository/move/manifests.js';
|
||||
import { UmbMoveDataTypeEntityAction } from './move.action.js';
|
||||
import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
@@ -13,8 +13,8 @@ const entityActions: Array<ManifestTypes> = [
|
||||
meta: {
|
||||
icon: 'icon-enter',
|
||||
label: 'Move to...',
|
||||
repositoryAlias: MOVE_DATA_TYPE_REPOSITORY_ALIAS,
|
||||
entityTypes: [DATA_TYPE_ENTITY_TYPE],
|
||||
repositoryAlias: UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS,
|
||||
entityTypes: [UMB_DATA_TYPE_ENTITY_TYPE],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export const DATA_TYPE_ROOT_ENTITY_TYPE = 'data-type-root';
|
||||
export const DATA_TYPE_ENTITY_TYPE = 'data-type';
|
||||
export const DATA_TYPE_FOLDER_ENTITY_TYPE = 'data-type-folder';
|
||||
export const UMB_DATA_TYPE_ROOT_ENTITY_TYPE = 'data-type-root';
|
||||
export const UMB_DATA_TYPE_ENTITY_TYPE = 'data-type';
|
||||
export const UMB_DATA_TYPE_FOLDER_ENTITY_TYPE = 'data-type-folder';
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export { UmbCopyDataTypeRepository } from './data-type-copy.repository.js';
|
||||
export { COPY_DATA_TYPE_REPOSITORY_ALIAS } from './manifests.js';
|
||||
export { UMB_COPY_DATA_TYPE_REPOSITORY_ALIAS as COPY_DATA_TYPE_REPOSITORY_ALIAS } from './manifests.js';
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { UmbCopyDataTypeRepository } from './data-type-copy.repository.js';
|
||||
import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const COPY_DATA_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Copy';
|
||||
export const UMB_COPY_DATA_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Copy';
|
||||
|
||||
const copyRepository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: COPY_DATA_TYPE_REPOSITORY_ALIAS,
|
||||
alias: UMB_COPY_DATA_TYPE_REPOSITORY_ALIAS,
|
||||
name: 'Copy Data Type Repository',
|
||||
api: UmbCopyDataTypeRepository,
|
||||
};
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export { UmbDataTypeDetailRepository } from './data-type-detail.repository.js';
|
||||
export { DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from './manifests.js';
|
||||
export { UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS as DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from './manifests.js';
|
||||
|
||||
@@ -2,20 +2,20 @@ import { UmbDataTypeDetailRepository } from './data-type-detail.repository.js';
|
||||
import { UmbDataTypeDetailStore } from './data-type-detail.store.js';
|
||||
import { ManifestRepository, ManifestStore } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const DATA_TYPE_DETAIL_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Detail';
|
||||
export const UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Detail';
|
||||
|
||||
const repository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: DATA_TYPE_DETAIL_REPOSITORY_ALIAS,
|
||||
alias: UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS,
|
||||
name: 'Data Type Detail Repository',
|
||||
api: UmbDataTypeDetailRepository,
|
||||
};
|
||||
|
||||
export const DATA_TYPE_DETAIL_STORE_ALIAS = 'Umb.Store.DataType.Detail';
|
||||
export const UMB_DATA_TYPE_DETAIL_STORE_ALIAS = 'Umb.Store.DataType.Detail';
|
||||
|
||||
const store: ManifestStore = {
|
||||
type: 'store',
|
||||
alias: DATA_TYPE_DETAIL_STORE_ALIAS,
|
||||
alias: UMB_DATA_TYPE_DETAIL_STORE_ALIAS,
|
||||
name: 'Data Type Detail Store',
|
||||
api: UmbDataTypeDetailStore,
|
||||
};
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export { UmbDataTypeFolderRepository } from './data-type-folder.repository.js';
|
||||
export { DATA_TYPE_FOLDER_REPOSITORY_ALIAS } from './manifests.js';
|
||||
export { UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS as DATA_TYPE_FOLDER_REPOSITORY_ALIAS } from './manifests.js';
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { UmbDataTypeFolderRepository } from './data-type-folder.repository.js';
|
||||
import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const DATA_TYPE_FOLDER_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Folder';
|
||||
export const UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Folder';
|
||||
|
||||
const folderRepository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: DATA_TYPE_FOLDER_REPOSITORY_ALIAS,
|
||||
alias: UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS,
|
||||
name: 'Data Type Folder Repository',
|
||||
api: UmbDataTypeFolderRepository,
|
||||
};
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export { UmbDataTypeItemRepository } from './data-type-item.repository.js';
|
||||
export { DATA_TYPE_ITEM_REPOSITORY_ALIAS } from './manifests.js';
|
||||
export { UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS as DATA_TYPE_ITEM_REPOSITORY_ALIAS } from './manifests.js';
|
||||
|
||||
@@ -2,19 +2,19 @@ import { UmbDataTypeItemStore } from './data-type-item.store.js';
|
||||
import { UmbDataTypeItemRepository } from './data-type-item.repository.js';
|
||||
import type { ManifestRepository, ManifestItemStore } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const DATA_TYPE_ITEM_REPOSITORY_ALIAS = 'Umb.Repository.DataTypeItem';
|
||||
export const DATA_TYPE_STORE_ALIAS = 'Umb.Store.DataTypeItem';
|
||||
export const UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS = 'Umb.Repository.DataTypeItem';
|
||||
export const UMB_DATA_TYPE_STORE_ALIAS = 'Umb.Store.DataTypeItem';
|
||||
|
||||
const itemRepository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: DATA_TYPE_ITEM_REPOSITORY_ALIAS,
|
||||
alias: UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS,
|
||||
name: 'Data Type Item Repository',
|
||||
api: UmbDataTypeItemRepository,
|
||||
};
|
||||
|
||||
const itemStore: ManifestItemStore = {
|
||||
type: 'itemStore',
|
||||
alias: DATA_TYPE_STORE_ALIAS,
|
||||
alias: UMB_DATA_TYPE_STORE_ALIAS,
|
||||
name: 'Data Type Item Store',
|
||||
api: UmbDataTypeItemStore,
|
||||
};
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export { UmbMoveDataTypeRepository } from './data-type-move.repository.js';
|
||||
export { MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './manifests.js';
|
||||
export { UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS as MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './manifests.js';
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { UmbMoveDataTypeRepository } from './data-type-move.repository.js';
|
||||
import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const MOVE_DATA_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Move';
|
||||
export const UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Move';
|
||||
|
||||
const moveRepository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: MOVE_DATA_TYPE_REPOSITORY_ALIAS,
|
||||
alias: UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS,
|
||||
name: 'Move Data Type Repository',
|
||||
api: UmbMoveDataTypeRepository,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UmbTreeRepositoryBase } from '../../tree/tree-repository-base.js';
|
||||
import { DATA_TYPE_ROOT_ENTITY_TYPE } from '../entity.js';
|
||||
import { UMB_DATA_TYPE_ROOT_ENTITY_TYPE } from '../entity.js';
|
||||
import { UmbDataTypeTreeServerDataSource } from './data-type.tree.server.data.js';
|
||||
import { UMB_DATA_TYPE_TREE_STORE_CONTEXT } from './data-type.tree.store.js';
|
||||
import { UmbDataTypeTreeItemModel, UmbDataTypeTreeRootModel } from './types.js';
|
||||
@@ -17,7 +17,7 @@ export class UmbDataTypeTreeRepository
|
||||
async requestTreeRoot() {
|
||||
const data = {
|
||||
id: null,
|
||||
type: DATA_TYPE_ROOT_ENTITY_TYPE,
|
||||
type: UMB_DATA_TYPE_ROOT_ENTITY_TYPE,
|
||||
name: 'Data Types',
|
||||
icon: 'icon-folder',
|
||||
hasChildren: true,
|
||||
|
||||
@@ -7,19 +7,19 @@ import type {
|
||||
ManifestTreeStore,
|
||||
} from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const DATA_TYPE_TREE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Tree';
|
||||
export const DATA_TYPE_TREE_STORE_ALIAS = 'Umb.Store.DataType.Tree';
|
||||
export const UMB_DATA_TYPE_TREE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Tree';
|
||||
export const UMB_DATA_TYPE_TREE_STORE_ALIAS = 'Umb.Store.DataType.Tree';
|
||||
|
||||
const treeRepository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: DATA_TYPE_TREE_REPOSITORY_ALIAS,
|
||||
alias: UMB_DATA_TYPE_TREE_REPOSITORY_ALIAS,
|
||||
name: 'Data Type Tree Repository',
|
||||
api: UmbDataTypeTreeRepository,
|
||||
};
|
||||
|
||||
const treeStore: ManifestTreeStore = {
|
||||
type: 'treeStore',
|
||||
alias: DATA_TYPE_TREE_STORE_ALIAS,
|
||||
alias: UMB_DATA_TYPE_TREE_STORE_ALIAS,
|
||||
name: 'Data Type Tree Store',
|
||||
api: UmbDataTypeTreeStore,
|
||||
};
|
||||
@@ -29,7 +29,7 @@ const tree: ManifestTree = {
|
||||
alias: 'Umb.Tree.DataTypes',
|
||||
name: 'Data Types Tree',
|
||||
meta: {
|
||||
repositoryAlias: DATA_TYPE_TREE_REPOSITORY_ALIAS,
|
||||
repositoryAlias: UMB_DATA_TYPE_TREE_REPOSITORY_ALIAS,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import type { UmbDataTypeVariantContext } from "./data-type-variant-context.js";
|
||||
import { UmbVariantContext } from "@umbraco-cms/backoffice/workspace";
|
||||
import { UmbContextToken } from "@umbraco-cms/backoffice/context-api";
|
||||
import type { UmbDataTypeVariantContext } from './data-type-variant-context.js';
|
||||
import { UmbVariantContext } from '@umbraco-cms/backoffice/workspace';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export const isDataTypeVariantContext = (context: UmbVariantContext): context is UmbDataTypeVariantContext => ('properties' in context && context.getType() === 'data-type');
|
||||
export const isDataTypeVariantContext = (context: UmbVariantContext): context is UmbDataTypeVariantContext =>
|
||||
'properties' in context && context.getType() === 'data-type';
|
||||
|
||||
export const UMB_DATA_TYPE_VARIANT_CONTEXT = new UmbContextToken<UmbVariantContext, UmbDataTypeVariantContext>(
|
||||
"UmbVariantContext", isDataTypeVariantContext);
|
||||
'UmbVariantContext',
|
||||
undefined,
|
||||
isDataTypeVariantContext,
|
||||
);
|
||||
|
||||
@@ -28,17 +28,17 @@ export class UmbDataTypeWorkspaceContext
|
||||
{
|
||||
// TODO: revisit. temp solution because the create and response models are different.
|
||||
#data = new UmbObjectState<DataTypeResponseModel | undefined>(undefined);
|
||||
data = this.#data.asObservable();
|
||||
readonly data = this.#data.asObservable();
|
||||
#getDataPromise?: Promise<any>;
|
||||
|
||||
name = this.#data.asObservablePart((data) => data?.name);
|
||||
id = this.#data.asObservablePart((data) => data?.id);
|
||||
readonly name = this.#data.asObservablePart((data) => data?.name);
|
||||
readonly id = this.#data.asObservablePart((data) => data?.id);
|
||||
|
||||
propertyEditorUiAlias = this.#data.asObservablePart((data) => data?.propertyEditorUiAlias);
|
||||
propertyEditorSchemaAlias = this.#data.asObservablePart((data) => data?.propertyEditorAlias);
|
||||
readonly propertyEditorUiAlias = this.#data.asObservablePart((data) => data?.propertyEditorUiAlias);
|
||||
readonly propertyEditorSchemaAlias = this.#data.asObservablePart((data) => data?.propertyEditorAlias);
|
||||
|
||||
#properties = new UmbObjectState<Array<PropertyEditorConfigProperty> | undefined>(undefined);
|
||||
properties: Observable<Array<PropertyEditorConfigProperty> | undefined> = this.#properties.asObservable();
|
||||
readonly properties: Observable<Array<PropertyEditorConfigProperty> | undefined> = this.#properties.asObservable();
|
||||
|
||||
private _propertyEditorSchemaConfigDefaultData: Array<PropertyEditorConfigDefaultData> = [];
|
||||
private _propertyEditorUISettingsDefaultData: Array<PropertyEditorConfigDefaultData> = [];
|
||||
@@ -53,13 +53,13 @@ export class UmbDataTypeWorkspaceContext
|
||||
private _propertyEditorUISettingsSchemaAlias?: string;
|
||||
|
||||
#defaults = new UmbArrayState<PropertyEditorConfigDefaultData>([], (entry) => entry.alias);
|
||||
defaults = this.#defaults.asObservable();
|
||||
readonly defaults = this.#defaults.asObservable();
|
||||
|
||||
#propertyEditorUiIcon = new UmbStringState<string | null>(null);
|
||||
propertyEditorUiIcon = this.#propertyEditorUiIcon.asObservable();
|
||||
readonly propertyEditorUiIcon = this.#propertyEditorUiIcon.asObservable();
|
||||
|
||||
#propertyEditorUiName = new UmbStringState<string | null>(null);
|
||||
propertyEditorUiName = this.#propertyEditorUiName.asObservable();
|
||||
readonly propertyEditorUiName = this.#propertyEditorUiName.asObservable();
|
||||
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
super(host, 'Umb.Workspace.DataType', new UmbDataTypeDetailRepository(host));
|
||||
@@ -265,5 +265,6 @@ export const UMB_DATA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbDataTypeWorkspaceContext
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbDataTypeWorkspaceContext => context.getEntityType?.() === 'data-type',
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { contextData, umbDebugContextEventType } from '@umbraco-cms/backoffice/context-api';
|
||||
import { contextData, UMB_DEBUG_CONTEXT_EVENT_TYPE } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbBaseController, UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
// Temp controller to get the code away from the app.element.ts
|
||||
@@ -11,7 +11,10 @@ export class UmbContextDebugController extends UmbBaseController {
|
||||
super.hostConnected();
|
||||
// Maybe this could be part of the context-api? When we create a new root, we could attach the debugger to it?
|
||||
// Listen for the debug event from the <umb-debug> component
|
||||
this.getHostElement().addEventListener(umbDebugContextEventType, this.#onContextDebug as unknown as EventListener);
|
||||
this.getHostElement().addEventListener(
|
||||
UMB_DEBUG_CONTEXT_EVENT_TYPE,
|
||||
this.#onContextDebug as unknown as EventListener,
|
||||
);
|
||||
}
|
||||
|
||||
#onContextDebug = (event: any) => {
|
||||
@@ -38,7 +41,7 @@ export class UmbContextDebugController extends UmbBaseController {
|
||||
hostDisconnected(): void {
|
||||
super.hostDisconnected();
|
||||
this.getHostElement().removeEventListener(
|
||||
umbDebugContextEventType,
|
||||
UMB_DEBUG_CONTEXT_EVENT_TYPE,
|
||||
this.#onContextDebug as unknown as EventListener,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ export interface UmbImportDictionaryModalData {
|
||||
}
|
||||
|
||||
export interface UmbImportDictionaryModalValue {
|
||||
temporaryFileId?: string;
|
||||
temporaryFileId: string;
|
||||
parentId?: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ export * from './invite-user-modal.token.js';
|
||||
export * from './language-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 './property-editor-ui-picker-modal.token.js';
|
||||
export * from './property-settings-modal.token.js';
|
||||
export * from './search-modal.token.js';
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbModalToken, UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
export type UmbMediaTypePickerModalData = UmbTreePickerModalData<EntityTreeItemResponseModel>;
|
||||
export type UmbMediaTypePickerModalValue = UmbPickerModalValue;
|
||||
|
||||
export const UMB_MEDIA_TYPE_PICKER_MODAL = new UmbModalToken<UmbMediaTypePickerModalData, UmbMediaTypePickerModalValue>(
|
||||
'Umb.Modal.TreePicker',
|
||||
{
|
||||
type: 'sidebar',
|
||||
size: 'small',
|
||||
},
|
||||
{
|
||||
treeAlias: 'Umb.Tree.MediaType',
|
||||
},
|
||||
);
|
||||
@@ -35,7 +35,12 @@ export class UmbFileSystemTreeStore
|
||||
return this.rootItems;
|
||||
}
|
||||
|
||||
return this._data.asObservablePart((items) => items.filter((item) => item.path?.startsWith(parentPath + '/')));
|
||||
return this._data.asObservablePart((items) =>
|
||||
items.filter((item) => {
|
||||
const pathCut = item.path?.substring(0, item.path?.lastIndexOf('/'));
|
||||
return parentPath === pathCut;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export type variantObject = { culture?: string | null; segment?: string | null };
|
||||
|
||||
export const INVARIANT_CULTURE = 'invariant';
|
||||
export const UMB_INVARIANT_CULTURE = 'invariant';
|
||||
|
||||
export class UmbVariantId {
|
||||
public static Create(variantData: variantObject): UmbVariantId {
|
||||
@@ -15,7 +15,7 @@ export class UmbVariantId {
|
||||
public readonly segment: string | null = null;
|
||||
|
||||
constructor(variantData: variantObject) {
|
||||
this.culture = (variantData.culture === INVARIANT_CULTURE ? null : variantData.culture) ?? null;
|
||||
this.culture = (variantData.culture === UMB_INVARIANT_CULTURE ? null : variantData.culture) ?? null;
|
||||
this.segment = variantData.segment ?? null;
|
||||
}
|
||||
|
||||
@@ -28,15 +28,15 @@ export class UmbVariantId {
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
return (this.culture || INVARIANT_CULTURE) + (this.segment ? `_${this.segment}` : '');
|
||||
return (this.culture || UMB_INVARIANT_CULTURE) + (this.segment ? `_${this.segment}` : '');
|
||||
}
|
||||
|
||||
public toCultureString(): string {
|
||||
return (this.culture || INVARIANT_CULTURE);
|
||||
return this.culture || UMB_INVARIANT_CULTURE;
|
||||
}
|
||||
|
||||
public toSegmentString(): string {
|
||||
return (this.segment || '');
|
||||
return this.segment || '';
|
||||
}
|
||||
|
||||
public isInvariant(): boolean {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { type UmbVariantContext } from "./variant-context.interface.js";
|
||||
import { UmbNameableVariantContext } from "./nameable-variant-context.interface.js";
|
||||
import { UmbContextToken } from "@umbraco-cms/backoffice/context-api";
|
||||
import { type UmbVariantContext } from './variant-context.interface.js';
|
||||
import { UmbNameableVariantContext } from './nameable-variant-context.interface.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export const isNameablePropertySetContext = (context: UmbVariantContext): context is UmbNameableVariantContext => 'setName' in context;
|
||||
export const isNameablePropertySetContext = (context: UmbVariantContext): context is UmbNameableVariantContext =>
|
||||
'setName' in context;
|
||||
|
||||
export const UMB_NAMEABLE_VARIANT_CONTEXT = new UmbContextToken<UmbVariantContext, UmbNameableVariantContext>(
|
||||
"UmbVariantContext",
|
||||
isNameablePropertySetContext);
|
||||
'UmbVariantContext',
|
||||
undefined,
|
||||
isNameablePropertySetContext,
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { type UmbVariantContext } from "./variant-context.interface.js";
|
||||
import { UmbContextToken } from "@umbraco-cms/backoffice/context-api";
|
||||
import { type UmbVariantContext } from './variant-context.interface.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export const UMB_VARIANT_CONTEXT = new UmbContextToken<UmbVariantContext>("UmbVariantContext");
|
||||
export const UMB_VARIANT_CONTEXT = new UmbContextToken<UmbVariantContext>('UmbVariantContext');
|
||||
|
||||
@@ -6,4 +6,8 @@ import type { UmbEntityBase } from '@umbraco-cms/backoffice/models';
|
||||
export const UMB_VARIANT_WORKSPACE_CONTEXT_TOKEN = new UmbContextToken<
|
||||
UmbWorkspaceContextInterface,
|
||||
UmbVariantableWorkspaceContextInterface<UmbEntityBase>
|
||||
>('UmbWorkspaceContext', (context): context is UmbVariantableWorkspaceContextInterface => 'variants' in context);
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbVariantableWorkspaceContextInterface => 'variants' in context,
|
||||
);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export interface UmbWorkspaceContextInterface {
|
||||
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface UmbWorkspaceContextInterface extends UmbApi {
|
||||
readonly workspaceAlias: string;
|
||||
// TODO: should we consider another name than entity type. File system files are not entities but still have this type.
|
||||
getEntityType(): string;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { UmbPickerInputContext } from '@umbraco-cms/backoffice/picker-input';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UMB_DICTIONARY_ITEM_PICKER_MODAL } from '@umbraco-cms/backoffice/modal';
|
||||
import { DictionaryItemItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
|
||||
export class UmbDictionaryItemPickerContext extends UmbPickerInputContext<DictionaryItemItemResponseModel> {
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
super(host, 'Umb.Repository.Dictionary', UMB_DICTIONARY_ITEM_PICKER_MODAL);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
import { UmbDictionaryItemPickerContext } from './dictionary-item-input.context.js';
|
||||
import { css, html, customElement, property, state, ifDefined, repeat } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
import type { DictionaryItemItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
|
||||
@customElement('umb-dictionary-item-input')
|
||||
export class UmbDictionaryItemInputElement extends FormControlMixin(UmbLitElement) {
|
||||
/**
|
||||
* This is a minimum amount of selected items in this input.
|
||||
* @type {number}
|
||||
* @attr
|
||||
* @default 0
|
||||
*/
|
||||
@property({ type: Number })
|
||||
public get min(): number {
|
||||
return this.#pickerContext.min;
|
||||
}
|
||||
public set min(value: number) {
|
||||
this.#pickerContext.min = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Min validation message.
|
||||
* @type {boolean}
|
||||
* @attr
|
||||
* @default
|
||||
*/
|
||||
@property({ type: String, attribute: 'min-message' })
|
||||
minMessage = 'This field need more items';
|
||||
|
||||
/**
|
||||
* This is a maximum amount of selected items in this input.
|
||||
* @type {number}
|
||||
* @attr
|
||||
* @default Infinity
|
||||
*/
|
||||
@property({ type: Number })
|
||||
public get max(): number {
|
||||
return this.#pickerContext.max;
|
||||
}
|
||||
public set max(value: number) {
|
||||
this.#pickerContext.max = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Max validation message.
|
||||
* @type {boolean}
|
||||
* @attr
|
||||
* @default
|
||||
*/
|
||||
@property({ type: String, attribute: 'min-message' })
|
||||
maxMessage = 'This field exceeds the allowed amount of items';
|
||||
|
||||
public get selectedIds(): Array<string> {
|
||||
return this.#pickerContext.getSelection();
|
||||
}
|
||||
public set selectedIds(ids: Array<string>) {
|
||||
this.#pickerContext.setSelection(ids);
|
||||
}
|
||||
|
||||
@property()
|
||||
public set value(idsString: string) {
|
||||
// Its with full purpose we don't call super.value, as thats being handled by the observation of the context selection.
|
||||
this.selectedIds = idsString.split(/[ ,]+/);
|
||||
}
|
||||
|
||||
@state()
|
||||
private _items?: Array<DictionaryItemItemResponseModel>;
|
||||
|
||||
#pickerContext = new UmbDictionaryItemPickerContext(this);
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.addValidator(
|
||||
'rangeUnderflow',
|
||||
() => this.minMessage,
|
||||
() => !!this.min && this.#pickerContext.getSelection().length < this.min,
|
||||
);
|
||||
|
||||
this.addValidator(
|
||||
'rangeOverflow',
|
||||
() => this.maxMessage,
|
||||
() => !!this.max && this.#pickerContext.getSelection().length > this.max,
|
||||
);
|
||||
|
||||
this.observe(this.#pickerContext.selection, (selection) => (super.value = selection.join(',')));
|
||||
this.observe(this.#pickerContext.selectedItems, (selectedItems) => (this._items = selectedItems));
|
||||
}
|
||||
|
||||
protected getFormElement() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
${this._items
|
||||
? html` <uui-ref-list
|
||||
>${repeat(
|
||||
this._items,
|
||||
(item) => item.id,
|
||||
(item) => this._renderItem(item),
|
||||
)}
|
||||
</uui-ref-list>`
|
||||
: ''}
|
||||
${this.#renderAddButton()}
|
||||
`;
|
||||
}
|
||||
|
||||
#renderAddButton() {
|
||||
if (this.max > 0 && this.selectedIds.length >= this.max) return;
|
||||
return html`<uui-button
|
||||
id="add-button"
|
||||
look="placeholder"
|
||||
@click=${() => this.#pickerContext.openPicker()}
|
||||
label=${this.localize.term('general_add')}></uui-button>`;
|
||||
}
|
||||
|
||||
private _renderItem(item: DictionaryItemItemResponseModel) {
|
||||
if (!item.id) return;
|
||||
return html`
|
||||
<uui-ref-node name=${ifDefined(item.name)} detail=${ifDefined(item.id)}>
|
||||
<!-- TODO: implement is trashed <uui-tag size="s" slot="tag" color="danger">Trashed</uui-tag> -->
|
||||
<uui-action-bar slot="actions">
|
||||
<uui-button
|
||||
@click=${() => this.#pickerContext.requestRemoveItem(item.id!)}
|
||||
label=${this.localize.term('actions_remove')}></uui-button>
|
||||
</uui-action-bar>
|
||||
</uui-ref-node>
|
||||
`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
css`
|
||||
#add-button {
|
||||
width: 100%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export default UmbDictionaryItemInputElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-dictionary-item-input': UmbDictionaryItemInputElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './dictionary-item-input/dictionary-item-input.element.js';
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UmbDictionaryRepository } from '../../repository/dictionary.repository.js';
|
||||
import { UmbTextStyles } from "@umbraco-cms/backoffice/style";
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import {
|
||||
@@ -22,18 +22,30 @@ export default class UmbExportDictionaryEntityAction extends UmbEntityActionBase
|
||||
}
|
||||
|
||||
async execute() {
|
||||
// TODO: what to do if modal service is not available?
|
||||
if (!this.#modalContext) return;
|
||||
|
||||
const modalContext = this.#modalContext?.open(UMB_EXPORT_DICTIONARY_MODAL, { unique: this.unique });
|
||||
|
||||
// TODO: get type from modal result
|
||||
const { includeChildren } = await modalContext.onSubmit();
|
||||
if (includeChildren === undefined) return;
|
||||
|
||||
// Export the file
|
||||
const result = await this.repository?.export(this.unique, includeChildren);
|
||||
const blobContent = await result?.data;
|
||||
|
||||
// TODO => get location header to route to new item
|
||||
console.log(result);
|
||||
if (!blobContent) return;
|
||||
const blob = new Blob([blobContent], { type: 'text/plain' });
|
||||
const a = document.createElement('a');
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
|
||||
// Download
|
||||
a.href = url;
|
||||
a.download = `${this.unique}.udt`;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
|
||||
// Clean up
|
||||
window.URL.revokeObjectURL(url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import '../../components/dictionary-item-input/dictionary-item-input.element.js';
|
||||
import UmbDictionaryItemInputElement from '../../components/dictionary-item-input/dictionary-item-input.element.js';
|
||||
import { UmbDictionaryRepository } from '../../repository/dictionary.repository.js';
|
||||
import { css, html, customElement, query, state, when } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
@@ -7,167 +9,213 @@ import {
|
||||
UmbModalBaseElement,
|
||||
} from '@umbraco-cms/backoffice/modal';
|
||||
import { ImportDictionaryRequestModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbId } from '@umbraco-cms/backoffice/id';
|
||||
|
||||
interface DictionaryItemPreview {
|
||||
name: string;
|
||||
children: Array<DictionaryItemPreview>;
|
||||
}
|
||||
|
||||
@customElement('umb-import-dictionary-modal')
|
||||
export class UmbImportDictionaryModalLayout extends UmbModalBaseElement<
|
||||
UmbImportDictionaryModalData,
|
||||
UmbImportDictionaryModalValue
|
||||
> {
|
||||
@state()
|
||||
private _parentId?: string;
|
||||
|
||||
@state()
|
||||
private _temporaryFileId?: string;
|
||||
|
||||
@query('#form')
|
||||
private _form!: HTMLFormElement;
|
||||
|
||||
#fileReader;
|
||||
|
||||
#fileContent: Array<DictionaryItemPreview> = [];
|
||||
|
||||
#handleClose() {
|
||||
this.modalContext?.reject();
|
||||
}
|
||||
|
||||
#submit() {
|
||||
// TODO: Gotta do a temp file upload before submitting, so that the server can use it
|
||||
console.log('submit:', this._temporaryFileId, this._parentId);
|
||||
//this.modalContext?.submit({ temporaryFileId: this._temporaryFileId, parentId: this._parentId });
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.#fileReader = new FileReader();
|
||||
this.#fileReader.onload = (e) => {
|
||||
if (typeof e.target?.result === 'string') {
|
||||
const fileContent = e.target.result;
|
||||
this.#dictionaryItemBuilder(fileContent);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this._parentId = this.data?.unique ?? undefined;
|
||||
}
|
||||
|
||||
#dictionaryItemBuilder(htmlString: string) {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(htmlString, 'text/xml');
|
||||
const elements = doc.childNodes;
|
||||
|
||||
this.#fileContent = this.#makeDictionaryItems(elements);
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
#makeDictionaryItems(nodeList: NodeListOf<ChildNode>): Array<DictionaryItemPreview> {
|
||||
const items: Array<DictionaryItemPreview> = [];
|
||||
const list: Array<Element> = [];
|
||||
nodeList.forEach((node) => {
|
||||
if (node.nodeType === Node.ELEMENT_NODE && node.nodeName === 'DictionaryItem') {
|
||||
list.push(node as Element);
|
||||
}
|
||||
});
|
||||
|
||||
list.forEach((item) => {
|
||||
items.push({
|
||||
name: item.getAttribute('Name') ?? '',
|
||||
children: this.#makeDictionaryItems(item.childNodes) ?? undefined,
|
||||
});
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
#onUpload(e: Event) {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(this._form);
|
||||
const file = formData.get('file') as Blob;
|
||||
|
||||
this.#fileReader.readAsText(file);
|
||||
this._temporaryFileId = file ? UmbId.new() : undefined;
|
||||
}
|
||||
|
||||
#onParentChange(event: CustomEvent) {
|
||||
this._parentId = (event.target as UmbDictionaryItemInputElement).selectedIds[0] || undefined;
|
||||
//console.log((event.target as UmbDictionaryItemInputElement).selectedIds[0] || undefined);
|
||||
}
|
||||
|
||||
async #onFileInput() {
|
||||
requestAnimationFrame(() => {
|
||||
this._form.requestSubmit();
|
||||
});
|
||||
}
|
||||
|
||||
#onClear() {
|
||||
this._temporaryFileId = '';
|
||||
}
|
||||
|
||||
render() {
|
||||
return html` <umb-body-layout headline=${this.localize.term('general_import')}>
|
||||
<uui-box>
|
||||
${when(
|
||||
this._temporaryFileId,
|
||||
() => this.#renderImportDestination(),
|
||||
() => this.#renderUploadZone(),
|
||||
)}
|
||||
</uui-box>
|
||||
<uui-button
|
||||
slot="actions"
|
||||
type="button"
|
||||
label=${this.localize.term('general_cancel')}
|
||||
@click=${this.#handleClose}></uui-button>
|
||||
</umb-body-layout>`;
|
||||
}
|
||||
|
||||
#renderFileContents(items: Array<DictionaryItemPreview>): any {
|
||||
return html`${items.map((item: DictionaryItemPreview) => {
|
||||
return html`${item.name}
|
||||
<div>${this.#renderFileContents(item.children)}</div>`;
|
||||
})}`;
|
||||
}
|
||||
|
||||
#renderImportDestination() {
|
||||
return html`
|
||||
<div id="wrapper">
|
||||
<div>
|
||||
<strong><umb-localize key="visuallyHiddenTexts_dictionaryItems">Dictionary items</umb-localize>:</strong>
|
||||
<div id="item-list">${this.#renderFileContents(this.#fileContent)}</div>
|
||||
</div>
|
||||
<div>
|
||||
<strong><umb-localize key="actions_chooseWhereToImport">Choose where to import</umb-localize>:</strong>
|
||||
Work in progress<br />
|
||||
${
|
||||
this._parentId
|
||||
// TODO
|
||||
// <umb-dictionary-item-input
|
||||
// @change=${this.#onParentChange}
|
||||
// .selectedIds=${this._parentId ? [this._parentId] : []}
|
||||
// max="1">
|
||||
// </umb-dictionary-item-input>
|
||||
}
|
||||
</div>
|
||||
|
||||
${this.#renderNavigate()}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderNavigate() {
|
||||
return html`<div id="nav">
|
||||
<uui-button label=${this.localize.term('general_import')} look="secondary" @click=${this.#onClear}>
|
||||
<uui-icon name="icon-arrow-left"></uui-icon>
|
||||
${this.localize.term('general_back')}
|
||||
</uui-button>
|
||||
<uui-button
|
||||
type="button"
|
||||
label=${this.localize.term('general_import')}
|
||||
look="primary"
|
||||
@click=${this.#submit}></uui-button>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
#renderUploadZone() {
|
||||
return html`<umb-localize key="dictionary_importDictionaryItemHelp"></umb-localize>
|
||||
<uui-form>
|
||||
<form id="form" name="form" @submit=${this.#onUpload}>
|
||||
<uui-form-layout-item>
|
||||
<uui-label for="file" slot="label" required>${this.localize.term('formFileUpload_pickFile')}</uui-label>
|
||||
<uui-input-file
|
||||
accept=".udt"
|
||||
name="file"
|
||||
id="file"
|
||||
@input=${this.#onFileInput}
|
||||
required
|
||||
required-message=${this.localize.term('formFileUpload_pickFile')}></uui-input-file>
|
||||
</uui-form-layout-item>
|
||||
</form>
|
||||
</uui-form>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
uui-input {
|
||||
width: 100%;
|
||||
}
|
||||
#item-list {
|
||||
padding: var(--uui-size-3) var(--uui-size-4);
|
||||
border: 1px solid var(--uui-color-border);
|
||||
border-radius: var(--uui-border-radius);
|
||||
}
|
||||
#item-list div {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--uui-size-3);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@query('#form')
|
||||
private _form!: HTMLFormElement;
|
||||
|
||||
@state()
|
||||
private _uploadedDictionaryTempId?: string;
|
||||
|
||||
@state()
|
||||
private _showUploadView = true;
|
||||
|
||||
@state()
|
||||
private _showImportView = false;
|
||||
|
||||
@state()
|
||||
private _showErrorView = false;
|
||||
|
||||
@state()
|
||||
private _selection: Array<string> = [];
|
||||
|
||||
#detailRepo = new UmbDictionaryRepository(this);
|
||||
|
||||
async #importDictionary() {
|
||||
if (!this._uploadedDictionaryTempId) return;
|
||||
|
||||
this.modalContext?.submit({
|
||||
temporaryFileId: this._uploadedDictionaryTempId,
|
||||
parentId: this._selection[0],
|
||||
});
|
||||
}
|
||||
|
||||
#handleClose() {
|
||||
this.modalContext?.reject();
|
||||
}
|
||||
|
||||
#submitForm() {
|
||||
this._form?.requestSubmit();
|
||||
}
|
||||
|
||||
async #handleSubmit(e: SubmitEvent) {
|
||||
e.preventDefault();
|
||||
|
||||
if (!this._form.checkValidity()) return;
|
||||
|
||||
const formData = new FormData(this._form);
|
||||
|
||||
const uploadData: ImportDictionaryRequestModel = {
|
||||
temporaryFileId: formData.get('file')?.toString() ?? '',
|
||||
};
|
||||
|
||||
// TODO: fix this upload experience. We need to update our form so it gets temporary file id from the server:
|
||||
const { data } = await this.#detailRepo.upload(uploadData);
|
||||
|
||||
if (!data) return;
|
||||
|
||||
this._uploadedDictionaryTempId = data;
|
||||
// TODO: We need to find another way to gather the data of the uploaded dictionary, to represent the dictionaryItems? See further below.
|
||||
//this._uploadedDictionary = data;
|
||||
|
||||
if (!this._uploadedDictionaryTempId) {
|
||||
this._showErrorView = true;
|
||||
this._showImportView = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._showErrorView = false;
|
||||
this._showUploadView = false;
|
||||
this._showImportView = true;
|
||||
}
|
||||
|
||||
/*
|
||||
#handleSelectionChange(e: CustomEvent) {
|
||||
e.stopPropagation();
|
||||
const element = e.target as UmbTreeElement;
|
||||
this._selection = element.selection;
|
||||
}
|
||||
*/
|
||||
|
||||
#renderUploadView() {
|
||||
return html`<p>
|
||||
To import a dictionary item, find the ".udt" file on your computer by clicking the "Import" button (you'll be
|
||||
asked for confirmation on the next screen)
|
||||
</p>
|
||||
<uui-form>
|
||||
<form id="form" name="form" @submit=${this.#handleSubmit}>
|
||||
<uui-form-layout-item>
|
||||
<uui-label for="file" slot="label" required>File</uui-label>
|
||||
<div>
|
||||
<uui-input-file
|
||||
accept=".udt"
|
||||
name="file"
|
||||
id="file"
|
||||
required
|
||||
required-message="File is required"></uui-input-file>
|
||||
</div>
|
||||
</uui-form-layout-item>
|
||||
</form>
|
||||
</uui-form>
|
||||
<uui-button slot="actions" type="button" label="Cancel" @click=${this.#handleClose}></uui-button>
|
||||
<uui-button slot="actions" type="button" label="Import" look="primary" @click=${this.#submitForm}></uui-button>`;
|
||||
}
|
||||
|
||||
/// TODO => Tree view needs isolation and single-select option
|
||||
#renderImportView() {
|
||||
//TODO: gather this data in some other way, we cannot use the feedback from the server anymore. can we use info about the file directly? or is a change to the end point required?
|
||||
/*
|
||||
if (!this._uploadedDictionary?.dictionaryItems) return;
|
||||
|
||||
return html`
|
||||
<b>Dictionary items</b>
|
||||
<ul>
|
||||
${repeat(
|
||||
this._uploadedDictionary.dictionaryItems,
|
||||
(item) => item.name,
|
||||
(item) => html`<li>${item.name}</li>`
|
||||
)}
|
||||
</ul>
|
||||
<hr />
|
||||
<b>Choose where to import dictionary items (optional)</b>
|
||||
<umb-tree
|
||||
alias="Umb.Tree.Dictionary"
|
||||
@selection-change=${this.#handleSelectionChange}
|
||||
.selection=${this._selection}
|
||||
selectable></umb-tree>
|
||||
|
||||
<uui-button slot="actions" type="button" label="Cancel" @click=${this.#handleClose}></uui-button>
|
||||
<uui-button
|
||||
slot="actions"
|
||||
type="button"
|
||||
label="Import"
|
||||
look="primary"
|
||||
@click=${this.#importDictionary}></uui-button>
|
||||
`;
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO => Determine what to display when dictionary import/upload fails
|
||||
#renderErrorView() {
|
||||
return html`Something went wrong`;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html` <umb-body-layout headline="Import">
|
||||
${when(this._showUploadView, () => this.#renderUploadView())}
|
||||
${when(this._showImportView, () => this.#renderImportView())}
|
||||
${when(this._showErrorView, () => this.#renderErrorView())}
|
||||
</umb-body-layout>`;
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbImportDictionaryModalLayout;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UmbDictionaryRepository } from '../../repository/dictionary.repository.js';
|
||||
import { UmbTextStyles } from "@umbraco-cms/backoffice/style";
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import {
|
||||
@@ -22,18 +22,12 @@ export default class UmbImportDictionaryEntityAction extends UmbEntityActionBase
|
||||
}
|
||||
|
||||
async execute() {
|
||||
// TODO: what to do if modal service is not available?
|
||||
if (!this.#modalContext) return;
|
||||
|
||||
const modalContext = this.#modalContext?.open(UMB_IMPORT_DICTIONARY_MODAL, { unique: this.unique });
|
||||
|
||||
// TODO: get type from modal result
|
||||
const { temporaryFileId, parentId } = await modalContext.onSubmit();
|
||||
if (!temporaryFileId) return;
|
||||
const { parentId, temporaryFileId } = await modalContext.onSubmit();
|
||||
|
||||
const result = await this.repository?.import(temporaryFileId, parentId);
|
||||
|
||||
// TODO => get location header to route to new item
|
||||
console.log(result);
|
||||
await this.repository?.import(temporaryFileId, parentId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './repository/index.js';
|
||||
export * from './tree/index.js';
|
||||
export * from './components/index.js';
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { UmbDictionaryRepository } from '../repository/dictionary.repository.js';
|
||||
import { UmbSaveableWorkspaceContextInterface, UmbEditableWorkspaceContextBase } from '@umbraco-cms/backoffice/workspace';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import {
|
||||
type UmbSaveableWorkspaceContextInterface,
|
||||
UmbEditableWorkspaceContextBase,
|
||||
} from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
|
||||
import { DictionaryItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
@@ -10,10 +13,10 @@ export class UmbDictionaryWorkspaceContext
|
||||
implements UmbSaveableWorkspaceContextInterface<DictionaryItemResponseModel | undefined>
|
||||
{
|
||||
#data = new UmbObjectState<DictionaryItemResponseModel | undefined>(undefined);
|
||||
data = this.#data.asObservable();
|
||||
readonly data = this.#data.asObservable();
|
||||
|
||||
name = this.#data.asObservablePart((data) => data?.name);
|
||||
dictionary = this.#data.asObservablePart((data) => data);
|
||||
readonly name = this.#data.asObservablePart((data) => data?.name);
|
||||
readonly dictionary = this.#data.asObservablePart((data) => data);
|
||||
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
super(host, 'Umb.Workspace.Dictionary', new UmbDictionaryRepository(host));
|
||||
@@ -97,5 +100,6 @@ export const UMB_DICTIONARY_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbDictionaryWorkspaceContext
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbDictionaryWorkspaceContext => context.getEntityType?.() === 'dictionary-item',
|
||||
);
|
||||
|
||||
@@ -4,19 +4,19 @@ import { manifests as menuItemManifests } from './menu-item/manifests.js';
|
||||
import { manifests as workspaceManifests } from './workspace/manifests.js';
|
||||
import type { ManifestStore, ManifestTreeStore } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const DOCUMENT_BLUEPRINT_STORE_ALIAS = 'Umb.Store.DocumentBlueprint';
|
||||
export const DOCUMENT_BLUEPRINT_TREE_STORE_ALIAS = 'Umb.Store.DocumentBlueprintTree';
|
||||
export const UMB_DOCUMENT_BLUEPRINT_STORE_ALIAS = 'Umb.Store.DocumentBlueprint';
|
||||
export const UMB_DOCUMENT_BLUEPRINT_TREE_STORE_ALIAS = 'Umb.Store.DocumentBlueprintTree';
|
||||
|
||||
const store: ManifestStore = {
|
||||
type: 'store',
|
||||
alias: DOCUMENT_BLUEPRINT_STORE_ALIAS,
|
||||
alias: UMB_DOCUMENT_BLUEPRINT_STORE_ALIAS,
|
||||
name: 'Document Blueprint Store',
|
||||
api: UmbDocumentBlueprintStore,
|
||||
};
|
||||
|
||||
const treeStore: ManifestTreeStore = {
|
||||
type: 'treeStore',
|
||||
alias: DOCUMENT_BLUEPRINT_TREE_STORE_ALIAS,
|
||||
alias: UMB_DOCUMENT_BLUEPRINT_TREE_STORE_ALIAS,
|
||||
name: 'Document Blueprint Tree Store',
|
||||
api: UmbDocumentBlueprintTreeStore,
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
DOCUMENT_TYPE_ENTITY_TYPE,
|
||||
DOCUMENT_TYPE_FOLDER_ENTITY_TYPE,
|
||||
DOCUMENT_TYPE_ROOT_ENTITY_TYPE,
|
||||
UMB_DOCUMENT_TYPE_ENTITY_TYPE,
|
||||
UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE,
|
||||
UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE,
|
||||
} from '../../index.js';
|
||||
import { DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/index.js';
|
||||
import { UmbCreateDataTypeEntityAction } from './create.action.js';
|
||||
@@ -18,7 +18,11 @@ const entityActions: Array<ManifestTypes> = [
|
||||
icon: 'icon-add',
|
||||
label: 'Create...',
|
||||
repositoryAlias: DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS,
|
||||
entityTypes: [DOCUMENT_TYPE_ENTITY_TYPE, DOCUMENT_TYPE_ROOT_ENTITY_TYPE, DOCUMENT_TYPE_FOLDER_ENTITY_TYPE],
|
||||
entityTypes: [
|
||||
UMB_DOCUMENT_TYPE_ENTITY_TYPE,
|
||||
UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE,
|
||||
UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE,
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2,6 +2,6 @@ import './components/index.js';
|
||||
|
||||
export * from './repository/index.js';
|
||||
|
||||
export const DOCUMENT_TYPE_ROOT_ENTITY_TYPE = 'document-type-root';
|
||||
export const DOCUMENT_TYPE_ENTITY_TYPE = 'document-type';
|
||||
export const DOCUMENT_TYPE_FOLDER_ENTITY_TYPE = 'document-type-folder';
|
||||
export const UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE = 'document-type-root';
|
||||
export const UMB_DOCUMENT_TYPE_ENTITY_TYPE = 'document-type';
|
||||
export const UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE = 'document-type-folder';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DOCUMENT_TYPE_TREE_ALIAS } from '../tree/manifests.js';
|
||||
import { UMB_DOCUMENT_TYPE_TREE_ALIAS } from '../tree/manifests.js';
|
||||
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
const menuItem: ManifestTypes = {
|
||||
@@ -8,7 +8,7 @@ const menuItem: ManifestTypes = {
|
||||
name: 'Document Types Menu Item',
|
||||
weight: 900,
|
||||
meta: {
|
||||
treeAlias: DOCUMENT_TYPE_TREE_ALIAS,
|
||||
treeAlias: UMB_DOCUMENT_TYPE_TREE_ALIAS,
|
||||
label: 'Document Types',
|
||||
icon: 'icon-folder',
|
||||
menus: ['Umb.Menu.Settings'],
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
export { UmbDocumentTypeDetailRepository } from './document-type-detail.repository.js';
|
||||
export { DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS, DOCUMENT_TYPE_DETAIL_STORE_ALIAS } from './manifests.js';
|
||||
export {
|
||||
UMB_DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS as DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS,
|
||||
UMB_DOCUMENT_TYPE_DETAIL_STORE_ALIAS as DOCUMENT_TYPE_DETAIL_STORE_ALIAS,
|
||||
} from './manifests.js';
|
||||
export { UMB_DOCUMENT_TYPE_DETAIL_STORE_CONTEXT } from './document-type-detail.store.js';
|
||||
|
||||
@@ -2,19 +2,19 @@ import { UmbDocumentTypeDetailRepository } from './document-type-detail.reposito
|
||||
import { UmbDocumentTypeDetailStore } from './document-type-detail.store.js';
|
||||
import { ManifestRepository, ManifestStore } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS = 'Umb.Repository.DocumentType.Detail';
|
||||
export const DOCUMENT_TYPE_DETAIL_STORE_ALIAS = 'Umb.Store.DocumentType.Detail';
|
||||
export const UMB_DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS = 'Umb.Repository.DocumentType.Detail';
|
||||
export const UMB_DOCUMENT_TYPE_DETAIL_STORE_ALIAS = 'Umb.Store.DocumentType.Detail';
|
||||
|
||||
const detailRepository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS,
|
||||
alias: UMB_DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS,
|
||||
name: 'Document Types Repository',
|
||||
api: UmbDocumentTypeDetailRepository,
|
||||
};
|
||||
|
||||
const detailStore: ManifestStore = {
|
||||
type: 'store',
|
||||
alias: DOCUMENT_TYPE_DETAIL_STORE_ALIAS,
|
||||
alias: UMB_DOCUMENT_TYPE_DETAIL_STORE_ALIAS,
|
||||
name: 'Document Type Store',
|
||||
api: UmbDocumentTypeDetailStore,
|
||||
};
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
export { UmbDocumentTypeItemRepository } from './document-type-item.repository.js';
|
||||
export { DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS, DOCUMENT_TYPE_ITEM_STORE_ALIAS } from './manifests.js';
|
||||
export {
|
||||
UMB_DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS as DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS,
|
||||
UMB_DOCUMENT_TYPE_ITEM_STORE_ALIAS as DOCUMENT_TYPE_ITEM_STORE_ALIAS,
|
||||
} from './manifests.js';
|
||||
export * from './types.js';
|
||||
|
||||
@@ -2,19 +2,19 @@ import { UmbDocumentTypeItemRepository } from './document-type-item.repository.j
|
||||
import { UmbDocumentTypeItemStore } from './document-type-item.store.js';
|
||||
import { ManifestItemStore, ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS = 'Umb.Repository.DocumentType.Item';
|
||||
export const DOCUMENT_TYPE_ITEM_STORE_ALIAS = 'Umb.Store.DocumentType.Item';
|
||||
export const UMB_DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS = 'Umb.Repository.DocumentType.Item';
|
||||
export const UMB_DOCUMENT_TYPE_ITEM_STORE_ALIAS = 'Umb.Store.DocumentType.Item';
|
||||
|
||||
const itemRepository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS,
|
||||
alias: UMB_DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS,
|
||||
name: 'Document Type Item Repository',
|
||||
api: UmbDocumentTypeItemRepository,
|
||||
};
|
||||
|
||||
const itemStore: ManifestItemStore = {
|
||||
type: 'itemStore',
|
||||
alias: DOCUMENT_TYPE_ITEM_STORE_ALIAS,
|
||||
alias: UMB_DOCUMENT_TYPE_ITEM_STORE_ALIAS,
|
||||
name: 'Document Type Item Store',
|
||||
api: UmbDocumentTypeItemStore,
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DOCUMENT_TYPE_ROOT_ENTITY_TYPE } from '../index.js';
|
||||
import { UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE } from '../index.js';
|
||||
import { UmbDocumentTypeTreeServerDataSource } from './document-type.tree.server.data-source.js';
|
||||
import { UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT } from './document-type.tree.store.js';
|
||||
import { UmbDocumentTypeTreeItemModel, UmbDocumentTypeTreeRootModel } from './types.js';
|
||||
@@ -17,7 +17,7 @@ export class UmbDocumentTypeTreeRepository
|
||||
async requestTreeRoot() {
|
||||
const data = {
|
||||
id: null,
|
||||
type: DOCUMENT_TYPE_ROOT_ENTITY_TYPE,
|
||||
type: UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE,
|
||||
name: 'Document Types',
|
||||
icon: 'icon-folder',
|
||||
hasChildren: true,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user