Merge remote-tracking branch 'origin/main' into feature/setup-stylesheet-workspace

# Conflicts:
#	src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts
#	src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts
This commit is contained in:
Niels Lyngsø
2023-09-05 13:06:35 +02:00
61 changed files with 553 additions and 269 deletions

View File

@@ -16,8 +16,8 @@ export interface UmbClassMixinInterface extends UmbControllerHost, UmbController
unique?: string
): UmbObserverController<T>;
provideContext<R = unknown>(alias: string | UmbContextToken<R>, instance: R): UmbContextProviderController<R>;
consumeContext<R = unknown>(
alias: string | UmbContextToken<R>,
callback: UmbContextCallback<R>
): UmbContextConsumerController<R>;
consumeContext<BaseType = unknown, ResultType extends BaseType = BaseType>(
alias: string | UmbContextToken<BaseType, ResultType>,
callback: UmbContextCallback<ResultType>
): UmbContextConsumerController<BaseType, ResultType>;
}

View File

@@ -27,11 +27,15 @@ declare class UmbClassMixinDeclaration implements UmbClassMixinInterface {
callback: (_value: T) => void,
controllerAlias?: UmbControllerAlias
): UmbObserverController<T>;
provideContext<R = unknown>(alias: string | UmbContextToken<R>, instance: R): UmbContextProviderController<R>;
consumeContext<R = unknown>(
alias: string | UmbContextToken<R>,
callback: UmbContextCallback<R>
): UmbContextConsumerController<R>;
provideContext<
BaseType = unknown,
ResultType extends BaseType = BaseType,
InstanceType extends ResultType = ResultType
>(alias: string | UmbContextToken<BaseType, ResultType>, instance: InstanceType): UmbContextProviderController<BaseType, ResultType, InstanceType>;
consumeContext<BaseType = unknown, ResultType extends BaseType = BaseType>(
alias: string | UmbContextToken<BaseType, ResultType>,
callback: UmbContextCallback<ResultType>
): UmbContextConsumerController<BaseType, ResultType>;
hasController(controller: UmbController): boolean;
getControllers(filterMethod: (ctrl: UmbController) => boolean): UmbController[];
addController(controller: UmbController): void;
@@ -82,11 +86,17 @@ export const UmbClassMixin = <T extends ClassConstructor>(superClass: T) => {
* @return {UmbContextProviderController} Reference to a Context Provider Controller instance
* @memberof UmbElementMixin
*/
provideContext<R = unknown>(
contextAlias: string | UmbContextToken<R>,
instance: R
): UmbContextProviderController<R> {
return new UmbContextProviderController(this, contextAlias, instance);
provideContext
<
BaseType = unknown,
ResultType extends BaseType = BaseType,
InstanceType extends ResultType = ResultType
>
(
contextAlias: string | UmbContextToken<BaseType, ResultType>,
instance: InstanceType
): UmbContextProviderController {
return new UmbContextProviderController<BaseType, ResultType, InstanceType>(this, contextAlias, instance);
}
/**
@@ -96,10 +106,10 @@ export const UmbClassMixin = <T extends ClassConstructor>(superClass: T) => {
* @return {UmbContextConsumerController} Reference to a Context Consumer Controller instance
* @memberof UmbElementMixin
*/
consumeContext<R = unknown>(
contextAlias: string | UmbContextToken<R>,
callback: UmbContextCallback<R>
): UmbContextConsumerController<R> {
consumeContext<BaseType = unknown, ResultType extends BaseType = BaseType>(
contextAlias: string | UmbContextToken<BaseType, ResultType>,
callback: UmbContextCallback<ResultType>
): UmbContextConsumerController<BaseType, ResultType> {
return new UmbContextConsumerController(this, contextAlias, callback);
}
}

View File

@@ -3,7 +3,11 @@ import { UmbContextConsumer } from './context-consumer.js';
import { UmbContextCallback } from './context-request.event.js';
import type { UmbControllerHost, UmbController } from '@umbraco-cms/backoffice/controller-api';
export class UmbContextConsumerController<T = unknown> extends UmbContextConsumer<T> implements UmbController {
export class UmbContextConsumerController<
BaseType = unknown,
ResultType extends BaseType = BaseType
> extends UmbContextConsumer<BaseType, ResultType> implements UmbController {
#controllerAlias = Symbol();
#host: UmbControllerHost;
@@ -11,7 +15,7 @@ export class UmbContextConsumerController<T = unknown> extends UmbContextConsume
return this.#controllerAlias;
}
constructor(host: UmbControllerHost, contextAlias: string | UmbContextToken<T>, callback: UmbContextCallback<T>) {
constructor(host: UmbControllerHost, contextAlias: string | UmbContextToken<BaseType, ResultType>, callback: UmbContextCallback<ResultType>) {
super(host.getHostElement(), contextAlias, callback);
this.#host = host;
host.addController(this);

View File

@@ -1,12 +1,13 @@
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';
const testContextAlias = 'my-test-context';
class UmbTestContextConsumerClass {
prop = 'value from provider';
public prop: string = 'value from provider';
}
describe('UmbContextConsumer', () => {
@@ -18,6 +19,11 @@ describe('UmbContextConsumer', () => {
});
describe('Public API', () => {
describe('properties', () => {
it('has a instance property', () => {
expect(consumer).to.have.property('instance').that.is.undefined;
});
});
describe('methods', () => {
it('has a request method', () => {
expect(consumer).to.have.property('request').that.is.a('function');
@@ -34,6 +40,7 @@ describe('UmbContextConsumer', () => {
expect(event).to.exist;
expect(event.type).to.eq(umbContextRequestEventType);
expect(event.contextAlias).to.eq(testContextAlias);
consumer.hostDisconnected();
});
});
});
@@ -90,3 +97,78 @@ describe('UmbContextConsumer', () => {
});
*/
});
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');
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();
});
});
});

View File

@@ -1,4 +1,4 @@
import { UmbContextToken } from '../token/context-token.js';
import { UmbContextDiscriminator, UmbContextToken } from '../token/context-token.js';
import {
isUmbContextProvideEventType,
//isUmbContextUnprovidedEventType,
@@ -11,51 +11,72 @@ import { UmbContextRequestEventImplementation, UmbContextCallback } from './cont
* @export
* @class UmbContextConsumer
*/
export class UmbContextConsumer<T = unknown> {
#callback?: UmbContextCallback<T>;
#promise?: Promise<T>;
#promiseResolver?: (instance: T) => void;
export class UmbContextConsumer<
BaseType = unknown,
ResultType extends BaseType = BaseType> {
#callback?: UmbContextCallback<ResultType>;
#promise?: Promise<ResultType>;
#promiseResolver?: (instance: ResultType) => void;
#instance?: T;
#instance?: ResultType;
get instance() {
return this.#instance;
}
#contextAlias: string;
#discriminator?: UmbContextDiscriminator<BaseType, ResultType>;
/**
* Creates an instance of UmbContextConsumer.
* @param {EventTarget} hostElement
* @param {string} contextAlias
* @param {UmbContextCallback} _callback
* @param {UmbContextCallback} callback
* @memberof UmbContextConsumer
*/
constructor(
protected hostElement: EventTarget,
contextAlias: string | UmbContextToken<T>,
callback?: UmbContextCallback<T>
contextAlias: string | UmbContextToken<BaseType, ResultType>,
callback?: UmbContextCallback<ResultType>
) {
this.#contextAlias = contextAlias.toString();
this.#callback = callback;
this.#discriminator = (contextAlias as any).getDiscriminator?.();
}
/* Idea: Niels: If we need to filter for specific contexts, we could make the response method return true/false. If false, the event should then then not be stopped. Alternatively parse the event it self on to the response-callback. This will enable the event to continue to bubble up finding a context that matches. The reason for such would be to have some who are more specific than others. For example, some might just need the current workspace-context, others might need the closest handling a certain entityType. As I'm writting this is not relevant, but I wanted to keep the idea as we have had some circumstance that might be solved with this approach.*/
protected _onResponse = (instance: T) => {
/* Idea: Niels: If we need to filter for specific contexts, we could make the response method return true/false. If false, the event should then then not be stopped. Alternatively parse the event it self on to the response-callback.
This will enable the event to continue to bubble up finding a context that matches.
The reason for such would be to have some who are more specific than others. For example, some might just need the current workspace-context, others might need the closest handling a certain entityType.
As I'm writing this is not relevant, but I wanted to keep the idea as we have had some circumstance that might be solved with this approach.
*/
protected _onResponse = (instance: BaseType) => {
if (this.#instance === instance) {
return;
}
if(this.#discriminator) {
// Notice if discriminator returns false, we do not want to setInstance.
if(this.#discriminator(instance)) {
this.setInstance(instance as unknown as ResultType);
}
} else {
this.setInstance(instance as ResultType);
}
};
protected setInstance(instance: ResultType) {
this.#instance = instance;
this.#callback?.(instance);
if (instance !== undefined) {
this.#promiseResolver?.(instance);
this.#promise = undefined;
}
};
}
public asPromise() {
return (
this.#promise ??
(this.#promise = new Promise<T>((resolve) => {
(this.#promise = new Promise<ResultType>((resolve) => {
this.#instance ? resolve(this.#instance) : (this.#promiseResolver = resolve);
}))
);

View File

@@ -9,9 +9,9 @@ export type UmbContextCallback<T> = (instance: T) => void;
* @export
* @interface UmbContextRequestEvent
*/
export interface UmbContextRequestEvent<T = unknown> extends Event {
readonly contextAlias: string | UmbContextToken<T>;
readonly callback: UmbContextCallback<T>;
export interface UmbContextRequestEvent<ResultType = unknown> extends Event {
readonly contextAlias: string | UmbContextToken<unknown, ResultType>;
readonly callback: UmbContextCallback<ResultType>;
}
/**
@@ -20,10 +20,10 @@ export interface UmbContextRequestEvent<T = unknown> extends Event {
* @extends {Event}
* @implements {UmbContextRequestEvent}
*/
export class UmbContextRequestEventImplementation<T = unknown> extends Event implements UmbContextRequestEvent<T> {
export class UmbContextRequestEventImplementation<ResultType = unknown> extends Event implements UmbContextRequestEvent<ResultType> {
public constructor(
public readonly contextAlias: string | UmbContextToken<T>,
public readonly callback: UmbContextCallback<T>
public readonly contextAlias: string | UmbContextToken<any, ResultType>,
public readonly callback: UmbContextCallback<ResultType>
) {
super(umbContextRequestEventType, { bubbles: true, composed: true, cancelable: true });
}

View File

@@ -2,14 +2,18 @@ import { UmbContextToken } from '../token/context-token.js';
import { UmbContextProvider } from './context-provider.js';
import type { UmbControllerHost, UmbController } from '@umbraco-cms/backoffice/controller-api';
export class UmbContextProviderController<T = unknown> extends UmbContextProvider implements UmbController {
export class UmbContextProviderController<
BaseType = unknown,
ResultType extends BaseType = BaseType,
InstanceType extends ResultType = ResultType
> extends UmbContextProvider<BaseType, ResultType> implements UmbController {
#host: UmbControllerHost;
public get controllerAlias() {
return this._contextAlias.toString();
}
constructor(host: UmbControllerHost, contextAlias: string | UmbContextToken<T>, instance: T) {
constructor(host: UmbControllerHost, contextAlias: string | UmbContextToken<BaseType, ResultType>, instance: InstanceType) {
super(host.getHostElement(), contextAlias, instance);
this.#host = host;

View File

@@ -13,7 +13,7 @@ import {
* @export
* @class UmbContextProvider
*/
export class UmbContextProvider {
export class UmbContextProvider<BaseType = unknown, ResultType extends BaseType = BaseType> {
protected hostElement: EventTarget;
protected _contextAlias: string;
@@ -35,7 +35,7 @@ export class UmbContextProvider {
* @param {*} instance
* @memberof UmbContextProvider
*/
constructor(hostElement: EventTarget, contextAlias: string | UmbContextToken, instance: unknown) {
constructor(hostElement: EventTarget, contextAlias: string | UmbContextToken<BaseType, ResultType>, instance: ResultType) {
this.hostElement = hostElement;
this._contextAlias = contextAlias.toString();
this.#instance = instance;

View File

@@ -1,4 +1,11 @@
export class UmbContextToken<T = unknown> {
export type UmbContextDiscriminator<BaseType, DiscriminatorResult extends BaseType> = (instance: BaseType) => instance is DiscriminatorResult;
export class UmbContextToken<
BaseType = unknown,
ResultType extends BaseType = BaseType> {
#discriminator: UmbContextDiscriminator<BaseType, ResultType> | undefined;
/**
* Get the type of the token
*
@@ -8,15 +15,18 @@ export class UmbContextToken<T = unknown> {
* @example `typeof MyToken.TYPE`
* @returns undefined
*/
readonly TYPE: T = undefined as never;
readonly TYPE: ResultType = undefined as never;
/**
* @param alias Unique identifier for the token,
* @param _desc Description for the token,
* used only for debugging purposes,
* it should but does not need to be unique
* @param alias Unique identifier for the token
*/
constructor(protected alias: string, protected _desc?: string) {}
constructor(protected alias: string, discriminator?: UmbContextDiscriminator<BaseType, ResultType>) {
this.#discriminator = discriminator;
}
getDiscriminator(): UmbContextDiscriminator<BaseType, ResultType> | undefined {
return this.#discriminator;
}
/**
* This method must always return the unique alias of the token since that
@@ -27,4 +37,6 @@ export class UmbContextToken<T = unknown> {
toString(): string {
return this.alias;
}
}

View File

@@ -24,11 +24,15 @@ export declare class UmbElement extends UmbControllerHostElement {
callback: ObserverCallback<T>,
unique?: string
): UmbObserverController<T>;
provideContext<R = unknown>(alias: string | UmbContextToken<R>, instance: R): UmbContextProviderController<R>;
consumeContext<R = unknown>(
alias: string | UmbContextToken<R>,
callback: UmbContextCallback<R>
): UmbContextConsumerController<R>;
provideContext<
BaseType = unknown,
ResultType extends BaseType = BaseType,
InstanceType extends ResultType = ResultType
>(alias: string | UmbContextToken<BaseType, ResultType>, instance: InstanceType): UmbContextProviderController<BaseType, ResultType, InstanceType>;
consumeContext<BaseType = unknown, ResultType extends BaseType = BaseType>(
alias: string | UmbContextToken<BaseType, ResultType>,
callback: UmbContextCallback<ResultType>
): UmbContextConsumerController<BaseType, ResultType>;
}
export const UmbElementMixin = <T extends HTMLElementConstructor>(superClass: T) => {
@@ -53,7 +57,12 @@ export const UmbElementMixin = <T extends HTMLElementConstructor>(superClass: T)
* @return {UmbContextProviderController} Reference to a Context Provider Controller instance
* @memberof UmbElementMixin
*/
provideContext<R = unknown>(alias: string | UmbContextToken<R>, instance: R): UmbContextProviderController<R> {
provideContext<
BaseType = unknown,
ResultType extends BaseType = BaseType,
InstanceType extends ResultType = ResultType
>
(alias: string | UmbContextToken<BaseType, ResultType>, instance: InstanceType): UmbContextProviderController<BaseType, ResultType, InstanceType> {
return new UmbContextProviderController(this, alias, instance);
}
@@ -64,10 +73,10 @@ export const UmbElementMixin = <T extends HTMLElementConstructor>(superClass: T)
* @return {UmbContextConsumerController} Reference to a Context Consumer Controller instance
* @memberof UmbElementMixin
*/
consumeContext<R = unknown>(
alias: string | UmbContextToken<R>,
callback: UmbContextCallback<R>
): UmbContextConsumerController<R> {
consumeContext<BaseType = unknown, ResultType extends BaseType = BaseType>(
alias: string | UmbContextToken<BaseType, ResultType>,
callback: UmbContextCallback<ResultType>
): UmbContextConsumerController<BaseType, ResultType> {
return new UmbContextConsumerController(this, alias, callback);
}
}

View File

@@ -2,12 +2,11 @@ import { UmbDataTypeConfig } from '../../property-editor/index.js';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbDataTypeRepository } from '@umbraco-cms/backoffice/data-type';
import { UmbDocumentWorkspaceContext } from '@umbraco-cms/backoffice/document';
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/document';
import type { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import type { DataTypeResponseModel, PropertyTypeModelBaseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
@customElement('umb-property-type-based-property')
export class UmbPropertyTypeBasedPropertyElement extends UmbLitElement {
@@ -57,12 +56,12 @@ export class UmbPropertyTypeBasedPropertyElement extends UmbLitElement {
}
private _propertyVariantId?: UmbVariantId | undefined;
private _workspaceContext?: UmbDocumentWorkspaceContext;
private _workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE;
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => {
this._workspaceContext = workspaceContext as UmbDocumentWorkspaceContext;
this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (workspaceContext) => {
this._workspaceContext = workspaceContext;
this._observeProperty();
});
}

View File

@@ -1,6 +1,5 @@
import { UmbEntityWorkspaceContextInterface } from './workspace-entity-context.interface.js';
import { UmbContextConsumerController, UmbContextProviderController } from '@umbraco-cms/backoffice/context-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbBaseController, UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api';
import type { UmbEntityBase } from '@umbraco-cms/backoffice/models';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
@@ -12,6 +11,7 @@ TODO: We need to figure out if we like to keep using same alias for all workspac
If so we need to align on a interface that all of these implements. otherwise consumers cant trust the workspace-context.
*/
export abstract class UmbWorkspaceContext<RepositoryType, EntityType extends UmbEntityBase>
extends UmbBaseController
implements UmbEntityWorkspaceContextInterface<EntityType>
{
public readonly host: UmbControllerHostElement;
@@ -25,11 +25,12 @@ export abstract class UmbWorkspaceContext<RepositoryType, EntityType extends Umb
isNew = this.#isNew.asObservable();
constructor(host: UmbControllerHostElement, workspaceAlias: string, repository: RepositoryType) {
super(host)
this.host = host;
this.workspaceAlias = workspaceAlias;
this.repository = repository;
new UmbContextProviderController(host, UMB_WORKSPACE_CONTEXT, this);
new UmbContextConsumerController(host, UMB_MODAL_CONTEXT_TOKEN, (context) => {
this.provideContext(UMB_WORKSPACE_CONTEXT, this);
this.consumeContext(UMB_MODAL_CONTEXT_TOKEN, (context) => {
(this.modalContext as UmbModalContext) = context;
});
}
@@ -59,5 +60,4 @@ export abstract class UmbWorkspaceContext<RepositoryType, EntityType extends Umb
abstract getEntityType(): string; // TODO: consider of this should be on the repository because a repo is responsible for one entity type
abstract getData(): EntityType | undefined;
abstract save(): Promise<void>;
abstract destroy(): void;
}

View File

@@ -1,4 +1,3 @@
import { UmbDocumentWorkspaceContext } from '../../../documents/documents/workspace/document-workspace.context.js';
import { UmbWorkspaceVariableEntityContextInterface } from '../workspace-context/workspace-variable-entity-context.interface.js';
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import {
@@ -47,7 +46,7 @@ export class UmbWorkspaceVariantContext {
// How do we ensure this connects to a document workspace context? and not just any other context? (We could start providing workspace contexts twice, under the general name and under a specific name)
// TODO: Figure out if this is the best way to consume the context or if it can be strongly typed with an UmbContextToken
new UmbContextConsumerController(host, UMB_WORKSPACE_CONTEXT, (context) => {
this.#workspaceContext = context as UmbDocumentWorkspaceContext;
this.#workspaceContext = context as UmbWorkspaceVariableEntityContextInterface;
this._observeVariant();
});

View File

@@ -1,20 +1,19 @@
import { UmbDictionaryWorkspaceContext } from './dictionary-workspace.context.js';
import { UMB_DICTIONARY_WORKSPACE_CONTEXT } from './dictionary-workspace.context.js';
import { UUIInputElement, UUIInputEvent, UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-dictionary-workspace-editor')
export class UmbDictionaryWorkspaceEditorElement extends UmbLitElement {
@state()
private _name?: string | null = '';
#workspaceContext?: UmbDictionaryWorkspaceContext;
#workspaceContext?: typeof UMB_DICTIONARY_WORKSPACE_CONTEXT.TYPE;
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance as UmbDictionaryWorkspaceContext;
this.consumeContext(UMB_DICTIONARY_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance;
this.#observeName();
});
}

View File

@@ -3,6 +3,7 @@ import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbrac
import { 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';
export class UmbDictionaryWorkspaceContext
extends UmbWorkspaceContext<UmbDictionaryRepository, DictionaryItemResponseModel>
@@ -83,3 +84,9 @@ export class UmbDictionaryWorkspaceContext
this.#data.complete();
}
}
export const UMB_DICTIONARY_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbDictionaryWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbDictionaryWorkspaceContext => context.getEntityType?.() === 'dictionary-item'
);

View File

@@ -1,10 +1,9 @@
import { UmbDictionaryWorkspaceContext } from '../../dictionary-workspace.context.js';
import { UMB_DICTIONARY_WORKSPACE_CONTEXT } from '../../dictionary-workspace.context.js';
import { UmbDictionaryRepository } from '../../../repository/dictionary.repository.js';
import { UUITextStyles, UUITextareaElement, UUITextareaEvent } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { DictionaryItemResponseModel, LanguageResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-workspace-view-dictionary-editor')
export class UmbWorkspaceViewDictionaryEditorElement extends UmbLitElement {
@state()
@@ -15,7 +14,7 @@ export class UmbWorkspaceViewDictionaryEditorElement extends UmbLitElement {
@state()
private _languages: Array<LanguageResponseModel> = [];
#workspaceContext!: UmbDictionaryWorkspaceContext;
#workspaceContext!: typeof UMB_DICTIONARY_WORKSPACE_CONTEXT.TYPE;
async connectedCallback() {
super.connectedCallback();
@@ -23,8 +22,8 @@ export class UmbWorkspaceViewDictionaryEditorElement extends UmbLitElement {
this.#repo = new UmbDictionaryRepository(this);
this._languages = await this.#repo.getLanguages();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (_instance) => {
this.#workspaceContext = _instance as UmbDictionaryWorkspaceContext;
this.consumeContext(UMB_DICTIONARY_WORKSPACE_CONTEXT, (_instance) => {
this.#workspaceContext = _instance;
this.#observeDictionary();
});
}

View File

@@ -7,6 +7,7 @@ import type {
DocumentTypeResponseModel,
} from '@umbraco-cms/backoffice/backend-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
type EntityType = DocumentTypeResponseModel;
export class UmbDocumentTypeWorkspaceContext
@@ -151,5 +152,13 @@ export class UmbDocumentTypeWorkspaceContext
public destroy(): void {
this.structure.destroy();
super.destroy();
}
}
export const UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbDocumentTypeWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbDocumentTypeWorkspaceContext => context.getEntityType?.() === 'document-type'
);

View File

@@ -19,7 +19,6 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement {
}
public set ownerTabId(value: string | null | undefined) {
if (value === this._ownerTabId) return;
console.log('ownerTabId', value);
const oldValue = this._ownerTabId;
this._ownerTabId = value;
this._groupStructureHelper.setOwnerId(value);

View File

@@ -1,11 +1,11 @@
import { UmbDocumentWorkspaceSplitViewElement } from './document-workspace-split-view.element.js';
import { UmbDocumentWorkspaceContext } from './document-workspace.context.js';
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from './document-workspace.context.js';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { customElement, state, css, html } from '@umbraco-cms/backoffice/external/lit';
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import type { UmbRoute, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router';
import { VariantModelBaseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_WORKSPACE_CONTEXT, ActiveVariant } from '@umbraco-cms/backoffice/workspace';
import { ActiveVariant } from '@umbraco-cms/backoffice/workspace';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
@customElement('umb-document-workspace-editor')
export class UmbDocumentWorkspaceEditorElement extends UmbLitElement {
@@ -21,13 +21,13 @@ export class UmbDocumentWorkspaceEditorElement extends UmbLitElement {
@state()
_workspaceSplitViews: Array<ActiveVariant> = [];
#workspaceContext?: UmbDocumentWorkspaceContext;
#workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE;
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance as UmbDocumentWorkspaceContext;
this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance;
this.#observeVariants();
this.#observeSplitViews();
});

View File

@@ -1,11 +1,11 @@
import { UmbDocumentWorkspaceContext } from './document-workspace.context.js';
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from './document-workspace.context.js';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, nothing, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit';
import { ActiveVariant, UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import { ActiveVariant } from '@umbraco-cms/backoffice/workspace';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
@customElement('umb-document-workspace-split-view')
export class UmbDocumentWorkspaceSplitViewElement extends UmbLitElement {
private _workspaceContext?: UmbDocumentWorkspaceContext;
private _workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE;
@state()
_unique?: string;
@@ -16,8 +16,8 @@ export class UmbDocumentWorkspaceSplitViewElement extends UmbLitElement {
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (context) => {
this._workspaceContext = context as UmbDocumentWorkspaceContext;
this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => {
this._workspaceContext = context;
this._observeActiveVariantInfo();
});
}

View File

@@ -3,6 +3,7 @@ import { UmbDocumentTypeRepository } from '../../document-types/repository/docum
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import { UmbContentTypePropertyStructureManager } from '@umbraco-cms/backoffice/content-type';
import {
UmbEntityWorkspaceContextInterface,
UmbWorkspaceContext,
UmbWorkspaceSplitViewManager,
UmbWorkspaceVariableEntityContextInterface,
@@ -15,6 +16,7 @@ import {
UmbObserverController,
} from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
// TODO: should this context be called DocumentDraft instead of workspace? or should the draft be part of this?
// TODO: Should we have a DocumentStructureContext and maybe even a DocumentDraftContext?
@@ -200,7 +202,14 @@ export class UmbDocumentWorkspaceContext
public destroy(): void {
this.#draft.complete();
this.structure.destroy();
super.destroy();
}
}
export default UmbDocumentWorkspaceContext;
export const UMB_DOCUMENT_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbDocumentWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbDocumentWorkspaceContext => context.getEntityType?.() === 'document'
);

View File

@@ -1 +1 @@
export { UmbDocumentWorkspaceContext } from './document-workspace.context.js';
export * from './document-workspace.context.js';

View File

@@ -1,10 +1,9 @@
import { UmbDocumentWorkspaceContext } from '../../document-workspace.context.js';
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../document-workspace.context.js';
import { css, html, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { UmbContentTypePropertyStructureHelper, PropertyContainerTypes } from '@umbraco-cms/backoffice/content-type';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { PropertyTypeModelBaseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-document-workspace-view-edit-properties')
export class UmbDocumentWorkspaceViewEditPropertiesElement extends UmbLitElement {
@property({ type: String, attribute: 'container-name', reflect: false })
@@ -31,8 +30,8 @@ export class UmbDocumentWorkspaceViewEditPropertiesElement extends UmbLitElement
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => {
this._propertyStructureHelper.setStructureManager((workspaceContext as UmbDocumentWorkspaceContext).structure);
this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (workspaceContext) => {
this._propertyStructureHelper.setStructureManager(workspaceContext.structure);
});
this.observe(this._propertyStructureHelper.propertyStructure, (propertyStructure) => {
this._propertyStructure = propertyStructure;

View File

@@ -1,10 +1,9 @@
import { UmbDocumentWorkspaceContext } from '../../document-workspace.context.js';
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../document-workspace.context.js';
import { css, html, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { UmbContentTypeContainerStructureHelper } from '@umbraco-cms/backoffice/content-type';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { PropertyTypeContainerModelBaseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import './document-workspace-view-edit-properties.element.js';
@customElement('umb-document-workspace-view-edit-tab')
@@ -53,8 +52,8 @@ export class UmbDocumentWorkspaceViewEditTabElement extends UmbLitElement {
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => {
this._groupStructureHelper.setStructureManager((workspaceContext as UmbDocumentWorkspaceContext).structure);
this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (workspaceContext) => {
this._groupStructureHelper.setStructureManager(workspaceContext.structure);
});
this.observe(this._groupStructureHelper.containers, (groups) => {
this._groups = groups;

View File

@@ -1,4 +1,4 @@
import { UmbDocumentWorkspaceContext } from '../../document-workspace.context.js';
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../document-workspace.context.js';
import type { UmbDocumentWorkspaceViewEditTabElement } from './document-workspace-view-edit-tab.element.js';
import { css, html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
@@ -11,7 +11,6 @@ import {
} from '@umbraco-cms/backoffice/router';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { PropertyTypeContainerModelBaseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import { UmbWorkspaceEditorViewExtensionElement } from '@umbraco-cms/backoffice/extension-registry';
@customElement('umb-document-workspace-view-edit')
@@ -34,7 +33,7 @@ export class UmbDocumentWorkspaceViewEditElement
@state()
private _activePath = '';
private _workspaceContext?: UmbDocumentWorkspaceContext;
private _workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE;
private _tabsStructureHelper = new UmbContentTypeContainerStructureHelper(this);
@@ -50,9 +49,9 @@ export class UmbDocumentWorkspaceViewEditElement
// _hasRootProperties can be gotten via _tabsStructureHelper.hasProperties. But we do not support root properties currently.
this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => {
this._workspaceContext = workspaceContext as UmbDocumentWorkspaceContext;
this._tabsStructureHelper.setStructureManager((workspaceContext as UmbDocumentWorkspaceContext).structure);
this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (workspaceContext) => {
this._workspaceContext = workspaceContext;
this._tabsStructureHelper.setStructureManager(workspaceContext.structure);
this._observeRootGroups();
});
}

View File

@@ -1,19 +1,18 @@
import { UmbWorkspaceMediaTypeContext } from './media-type-workspace.context.js';
import { UMB_MEDIA_TYPE_WORKSPACE_CONTEXT } from './media-type-workspace.context.js';
import { UUITextStyles, UUIInputElement, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-media-type-workspace-editor')
export class UmbMediaTypeWorkspaceEditorElement extends UmbLitElement {
@state()
private _mediaTypeName?: string | null = '';
#workspaceContext?: UmbWorkspaceMediaTypeContext;
#workspaceContext?: typeof UMB_MEDIA_TYPE_WORKSPACE_CONTEXT.TYPE;
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance as UmbWorkspaceMediaTypeContext;
this.consumeContext(UMB_MEDIA_TYPE_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance;
this.#observeName();
});
}

View File

@@ -3,9 +3,10 @@ import type { MediaTypeDetails } from '../types.js';
import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
type EntityType = MediaTypeDetails;
export class UmbWorkspaceMediaTypeContext
export class UmbMediaTypeWorkspaceContext
extends UmbWorkspaceContext<UmbMediaTypeRepository, EntityType>
implements UmbEntityWorkspaceContextInterface<EntityType | undefined>
{
@@ -61,3 +62,9 @@ export class UmbWorkspaceMediaTypeContext
this.#data.complete();
}
}
export const UMB_MEDIA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbMediaTypeWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbMediaTypeWorkspaceContext => context.getEntityType?.() === 'media-type'
);

View File

@@ -1,4 +1,4 @@
import { UmbWorkspaceMediaTypeContext } from './media-type-workspace.context.js';
import { UmbMediaTypeWorkspaceContext } from './media-type-workspace.context.js';
import { UmbMediaTypeWorkspaceEditorElement } from './media-type-workspace-editor.element.js';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
@@ -7,7 +7,7 @@ import type { UmbRoute } from '@umbraco-cms/backoffice/router';
@customElement('umb-media-type-workspace')
export class UmbMediaTypeWorkspaceElement extends UmbLitElement {
#workspaceContext = new UmbWorkspaceMediaTypeContext(this);
#workspaceContext = new UmbMediaTypeWorkspaceContext(this);
#element = new UmbMediaTypeWorkspaceEditorElement();
@state()

View File

@@ -1,20 +1,19 @@
import { UmbMediaWorkspaceContext } from './media-workspace.context.js';
import { UMB_MEDIA_WORKSPACE_CONTEXT } from './media-workspace.context.js';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-media-workspace-editor')
export class UmbMediaWorkspaceEditorElement extends UmbLitElement {
@state()
_id?: string;
#umbWorkspaceContext?: UmbMediaWorkspaceContext;
#umbWorkspaceContext?: typeof UMB_MEDIA_WORKSPACE_CONTEXT.TYPE;
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
this.#umbWorkspaceContext = instance as UmbMediaWorkspaceContext;
this.consumeContext(UMB_MEDIA_WORKSPACE_CONTEXT, (instance) => {
this.#umbWorkspaceContext = instance;
this.#observeId();
});
}

View File

@@ -3,6 +3,7 @@ import type { MediaDetails } from '../index.js';
import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
import { appendToFrozenArray, UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
type EntityType = MediaDetails;
export class UmbMediaWorkspaceContext
@@ -81,3 +82,8 @@ export class UmbMediaWorkspaceContext
this.#data.complete();
}
}
export const UMB_MEDIA_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbMediaWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbMediaWorkspaceContext => context.getEntityType?.() === 'media'
);

View File

@@ -1,16 +1,15 @@
import type { MemberGroupDetails } from '../types.js';
import { UmbWorkspaceMemberGroupContext } from './member-group-workspace.context.js';
import { UMB_MEMBER_GROUP_WORKSPACE_CONTEXT } from './member-group-workspace.context.js';
import { UUITextStyles, UUIInputElement, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
/**
* @element umb-member-group-edit-workspace
* @description - Element for displaying a Member Group Workspace
*/
@customElement('umb-member-group-workspace-editor')
export class UmbMemberGroupWorkspaceEditorElement extends UmbLitElement {
#workspaceContext?: UmbWorkspaceMemberGroupContext;
#workspaceContext?: typeof UMB_MEMBER_GROUP_WORKSPACE_CONTEXT.TYPE;
@state()
private _memberGroup?: MemberGroupDetails;
@@ -18,8 +17,8 @@ export class UmbMemberGroupWorkspaceEditorElement extends UmbLitElement {
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance as UmbWorkspaceMemberGroupContext;
this.consumeContext(UMB_MEMBER_GROUP_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance;
this.#observeMemberGroup();
});
}

View File

@@ -3,9 +3,10 @@ import type { MemberGroupDetails } from '../types.js';
import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
type EntityType = MemberGroupDetails;
export class UmbWorkspaceMemberGroupContext
export class UmbMemberGroupWorkspaceContext
extends UmbWorkspaceContext<UmbMemberGroupRepository, EntityType>
implements UmbEntityWorkspaceContextInterface<EntityType | undefined>
{
@@ -63,3 +64,10 @@ export class UmbWorkspaceMemberGroupContext
this.#data.complete();
}
}
export const UMB_MEMBER_GROUP_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbMemberGroupWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbMemberGroupWorkspaceContext => context.getEntityType?.() === 'member-group'
);

View File

@@ -1,4 +1,4 @@
import { UmbWorkspaceMemberGroupContext } from './member-group-workspace.context.js';
import { UmbMemberGroupWorkspaceContext } from './member-group-workspace.context.js';
import { UmbMemberGroupWorkspaceEditorElement } from './member-group-workspace-editor.element.js';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
@@ -11,7 +11,7 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
*/
@customElement('umb-member-group-workspace')
export class UmbMemberGroupWorkspaceElement extends UmbLitElement {
#workspaceContext = new UmbWorkspaceMemberGroupContext(this);
#workspaceContext = new UmbMemberGroupWorkspaceContext(this);
#element = new UmbMemberGroupWorkspaceEditorElement();
@state()

View File

@@ -1,22 +1,20 @@
import { UmbWorkspaceMemberGroupContext } from '../../member-group-workspace.context.js';
import { UMB_MEMBER_GROUP_WORKSPACE_CONTEXT } from '../../member-group-workspace.context.js';
import type { MemberGroupDetails } from '../../../types.js';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-workspace-view-member-group-info')
export class UmbWorkspaceViewMemberGroupInfoElement extends UmbLitElement {
@state()
private _memberGroup?: MemberGroupDetails;
#workspaceContext?: UmbWorkspaceMemberGroupContext;
#workspaceContext?: typeof UMB_MEMBER_GROUP_WORKSPACE_CONTEXT.TYPE;
constructor() {
super();
// TODO: Figure out if this is the best way to consume the context or if it can be strongly typed with an UmbContextToken
this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance as UmbWorkspaceMemberGroupContext;
this.consumeContext(UMB_MEMBER_GROUP_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance;
this.#observeMemberGroup();
});
}
@@ -26,10 +24,7 @@ export class UmbWorkspaceViewMemberGroupInfoElement extends UmbLitElement {
this.observe(this.#workspaceContext.data, (memberGroup) => {
if (!memberGroup) return;
// TODO: handle if model is not of the type wanted.
// TODO: Make method to identify wether data is of type MemberGroupDetails
this._memberGroup = memberGroup as MemberGroupDetails;
this._memberGroup = memberGroup;
});
}

View File

@@ -2,6 +2,7 @@ import { UmbMemberTypeRepository } from '../repository/member-type.repository.js
import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
// TODO => use correct tpye
type EntityType = any;
@@ -73,3 +74,8 @@ export class UmbMemberTypeWorkspaceContext
this.#data.complete();
}
}
export const UMB_MEMBER_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbMemberTypeWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbMemberTypeWorkspaceContext => context.getEntityType?.() === 'member-type'
);

View File

@@ -2,6 +2,7 @@ import { UmbMemberRepository } from '../repository/member.repository.js';
import type { MemberDetails } from '../types.js';
import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export class UmbMemberWorkspaceContext
extends UmbWorkspaceContext<UmbMemberRepository, MemberDetails>
@@ -35,3 +36,8 @@ export class UmbMemberWorkspaceContext
console.log('destroy');
}
}
export const UMB_MEMBER_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbMemberWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbMemberWorkspaceContext => context.getEntityType?.() === 'member'
);

View File

@@ -1,28 +1,28 @@
import { UmbDataTypeWorkspaceContext } from './data-type-workspace.context.js';
import { UMB_DATA_TYPE_WORKSPACE_CONTEXT } from './data-type-workspace.context.js';
import { UUIInputElement, UUIInputEvent, UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
/**
* @element umb-data-type-workspace-editor
* @description - Element for displaying the Data Type Workspace edit route.
*/
@customElement('umb-data-type-workspace-editor')
export class UmbDataTypeWorkspaceEditorElement extends UmbLitElement {
@property()
@property({attribute: false})
manifest?: ManifestWorkspace;
@state()
private _dataTypeName = '';
#workspaceContext?: UmbDataTypeWorkspaceContext;
#workspaceContext?: typeof UMB_DATA_TYPE_WORKSPACE_CONTEXT.TYPE;
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => {
this.#workspaceContext = workspaceContext as UmbDataTypeWorkspaceContext;
this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, (workspaceContext) => {
this.#workspaceContext = workspaceContext;
this.#observeIsNew();
this.#observeName();
});

View File

@@ -3,6 +3,7 @@ import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbrac
import type { DataTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { appendToFrozenArray, UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export class UmbDataTypeWorkspaceContext
extends UmbWorkspaceContext<UmbDataTypeRepository, DataTypeResponseModel>
@@ -95,3 +96,8 @@ export class UmbDataTypeWorkspaceContext
this.#data.complete();
}
}
export const UMB_DATA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbDataTypeWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbDataTypeWorkspaceContext => context.getEntityType?.() === 'data-type'
);

View File

@@ -1,7 +1,6 @@
import { UmbDataTypeWorkspaceContext } from '../../data-type-workspace.context.js';
import { UMB_DATA_TYPE_WORKSPACE_CONTEXT } from '../../data-type-workspace.context.js';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import {
UmbModalManagerContext,
UMB_MODAL_MANAGER_CONTEXT_TOKEN,
@@ -37,7 +36,7 @@ export class UmbDataTypeDetailsWorkspaceViewEditElement
@state()
private _data: Array<any> = [];
private _workspaceContext?: UmbDataTypeWorkspaceContext;
private _workspaceContext?: typeof UMB_DATA_TYPE_WORKSPACE_CONTEXT.TYPE;
private _modalContext?: UmbModalManagerContext;
constructor() {
@@ -47,9 +46,8 @@ export class UmbDataTypeDetailsWorkspaceViewEditElement
this._modalContext = instance;
});
// TODO: Figure out if this is the best way to consume a context or if it could be strongly typed using UmbContextToken
this.consumeContext(UMB_WORKSPACE_CONTEXT, (_instance) => {
this._workspaceContext = _instance as UmbDataTypeWorkspaceContext;
this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, (_instance) => {
this._workspaceContext = _instance;
this._observeDataType();
});
}

View File

@@ -1,7 +1,6 @@
import { UmbDataTypeWorkspaceContext } from '../../data-type-workspace.context.js';
import { UMB_DATA_TYPE_WORKSPACE_CONTEXT } from '../../data-type-workspace.context.js';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { DataTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbWorkspaceEditorViewExtensionElement } from '@umbraco-cms/backoffice/extension-registry';
@@ -14,14 +13,13 @@ export class UmbWorkspaceViewDataTypeInfoElement
@state()
_dataType?: DataTypeResponseModel;
private _workspaceContext?: UmbDataTypeWorkspaceContext;
private _workspaceContext?: typeof UMB_DATA_TYPE_WORKSPACE_CONTEXT.TYPE;
constructor() {
super();
// TODO: Figure out if this is the best way to consume the context or if it can be strongly typed with an UmbContextToken
this.consumeContext(UMB_WORKSPACE_CONTEXT, (dataTypeContext) => {
this._workspaceContext = dataTypeContext as UmbDataTypeWorkspaceContext;
this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, (dataTypeContext) => {
this._workspaceContext = dataTypeContext;
this._observeDataType();
});
}

View File

@@ -1,12 +1,11 @@
import { UmbLanguageWorkspaceContext } from './language-workspace.context.js';
import { UMB_LANGUAGE_WORKSPACE_CONTEXT } from './language-workspace.context.js';
import { UUITextStyles, UUIInputElement, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { LanguageResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-language-workspace-editor')
export class UmbLanguageWorkspaceEditorElement extends UmbLitElement {
#workspaceContext?: UmbLanguageWorkspaceContext;
#workspaceContext?: typeof UMB_LANGUAGE_WORKSPACE_CONTEXT.TYPE;
@state()
_language?: LanguageResponseModel;
@@ -17,8 +16,8 @@ export class UmbLanguageWorkspaceEditorElement extends UmbLitElement {
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (context) => {
this.#workspaceContext = context as UmbLanguageWorkspaceContext;
this.consumeContext(UMB_LANGUAGE_WORKSPACE_CONTEXT, (context) => {
this.#workspaceContext = context;
this.#observeData();
});
}

View File

@@ -3,6 +3,7 @@ import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbrac
import { ApiError, LanguageResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export class UmbLanguageWorkspaceContext
extends UmbWorkspaceContext<UmbLanguageRepository, LanguageResponseModel>
@@ -100,3 +101,9 @@ export class UmbLanguageWorkspaceContext
this.#data.complete();
}
}
export const UMB_LANGUAGE_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbLanguageWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbLanguageWorkspaceContext => context.getEntityType?.() === 'language'
);

View File

@@ -1,13 +1,11 @@
import { UmbLanguageWorkspaceContext } from '../../language-workspace.context.js';
import { UMB_LANGUAGE_WORKSPACE_CONTEXT } from '../../language-workspace.context.js';
import type { UmbInputCultureSelectElement } from '../../../../../cultures/components/input-culture-select/input-culture-select.element.js';
import type { UmbInputLanguagePickerElement } from '../../../../components/input-language-picker/input-language-picker.element.js';
import { UUIBooleanInputEvent, UUIToggleElement, UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, nothing, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
// TODO: set up import alias for these modules
import { UmbChangeEvent } from '@umbraco-cms/backoffice/events';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { LanguageResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import { UmbWorkspaceEditorViewExtensionElement } from '@umbraco-cms/backoffice/extension-registry';
@customElement('umb-language-details-workspace-view')
@@ -27,7 +25,7 @@ export class UmbLanguageDetailsWorkspaceViewElement
@state()
_validationErrors?: { [key: string]: Array<any> };
#languageWorkspaceContext?: UmbLanguageWorkspaceContext;
#languageWorkspaceContext?: typeof UMB_LANGUAGE_WORKSPACE_CONTEXT.TYPE;
constructor() {
super();
@@ -36,8 +34,8 @@ export class UmbLanguageDetailsWorkspaceViewElement
In the language workspace we want to clear a default language change warning and reset the initial state after a save action has been executed. */
let initialStateSet = false;
this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
this.#languageWorkspaceContext = instance as UmbLanguageWorkspaceContext;
this.consumeContext(UMB_LANGUAGE_WORKSPACE_CONTEXT, (instance) => {
this.#languageWorkspaceContext = instance;
this.observe(this.#languageWorkspaceContext.data, (language) => {
this._language = language;

View File

@@ -1,16 +1,15 @@
import { UmbRelationTypeWorkspaceContext } from './relation-type-workspace.context.js';
import { UMB_RELATION_TYPE_WORKSPACE_CONTEXT } from './relation-type-workspace.context.js';
import { UUIInputElement, UUIInputEvent, UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { RelationTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
/**
* @element umb-relation-type-workspace-editor
* @description - Element for displaying a Relation Type Workspace
*/
@customElement('umb-relation-type-workspace-editor')
export class UmbRelationTypeWorkspaceEditorElement extends UmbLitElement {
#workspaceContext?: UmbRelationTypeWorkspaceContext;
#workspaceContext?: typeof UMB_RELATION_TYPE_WORKSPACE_CONTEXT.TYPE;
@state()
private _relationType?: RelationTypeResponseModel;
@@ -18,8 +17,8 @@ export class UmbRelationTypeWorkspaceEditorElement extends UmbLitElement {
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance as UmbRelationTypeWorkspaceContext;
this.consumeContext(UMB_RELATION_TYPE_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance;
this.#observeRelationType();
});
}

View File

@@ -3,6 +3,7 @@ import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbrac
import type { RelationTypeBaseModel, RelationTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export class UmbRelationTypeWorkspaceContext
extends UmbWorkspaceContext<UmbRelationTypeRepository, RelationTypeResponseModel>
@@ -75,3 +76,10 @@ export class UmbRelationTypeWorkspaceContext
this.#data.complete();
}
}
export const UMB_RELATION_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbRelationTypeWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbRelationTypeWorkspaceContext => context.getEntityType?.() === 'relation-type'
);

View File

@@ -1,4 +1,4 @@
import { UmbRelationTypeWorkspaceContext } from '../../relation-type-workspace.context.js';
import { UMB_RELATION_TYPE_WORKSPACE_CONTEXT } from '../../relation-type-workspace.context.js';
import {
UUITextStyles,
UUIBooleanInputEvent,
@@ -9,7 +9,6 @@ import {
import { css, html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import type { RelationTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import { UmbWorkspaceEditorViewExtensionElement } from '@umbraco-cms/backoffice/extension-registry';
@customElement('umb-relation-type-workspace-view-relation-type')
@@ -20,13 +19,13 @@ export class UmbRelationTypeWorkspaceViewRelationTypeElement
@state()
private _relationType?: RelationTypeResponseModel;
#workspaceContext?: UmbRelationTypeWorkspaceContext;
#workspaceContext?: typeof UMB_RELATION_TYPE_WORKSPACE_CONTEXT.TYPE;
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance as UmbRelationTypeWorkspaceContext;
this.consumeContext(UMB_RELATION_TYPE_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance;
this._observeRelationType();
});
}

View File

@@ -5,7 +5,7 @@ const workspace: ManifestWorkspace = {
type: 'workspace',
alias: 'Umb.Workspace.PartialView',
name: 'Partial View Workspace',
loader: () => import('./partial-views-workspace.element.js'),
loader: () => import('./partial-view-workspace.element.js'),
meta: {
entityType: 'partial-view',
},

View File

@@ -1,17 +1,16 @@
import { UmbTemplatingInsertMenuElement } from '../../components/index.js';
import { UMB_TEMPLATE_QUERY_BUILDER_MODAL } from '../../templates/modals/modal-tokens.js';
import { getQuerySnippet } from '../../utils.js';
import { UmbPartialViewsWorkspaceContext } from './partial-views-workspace.context.js';
import { UMB_PARTIAL_VIEW_WORKSPACE_CONTEXT } from './partial-view-workspace.context.js';
import type { UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor';
import { UUITextStyles, UUIInputElement } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, query, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext } from '@umbraco-cms/backoffice/modal';
import { Subject, debounceTime } from '@umbraco-cms/backoffice/external/rxjs';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-partial-views-workspace-edit')
export class UmbPartialViewsWorkspaceEditElement extends UmbLitElement {
@customElement('umb-partial-view-workspace-edit')
export class UmbPartialViewWorkspaceEditElement extends UmbLitElement {
#name: string | undefined = '';
@state()
private get _name() {
@@ -35,11 +34,9 @@ export class UmbPartialViewsWorkspaceEditElement extends UmbLitElement {
@query('umb-code-editor')
private _codeEditor?: UmbCodeEditorElement;
#partialViewsWorkspaceContext?: UmbPartialViewsWorkspaceContext;
#partialViewWorkspaceContext?: typeof UMB_PARTIAL_VIEW_WORKSPACE_CONTEXT.TYPE;
private _modalContext?: UmbModalManagerContext;
#isNew = false;
private inputQuery$ = new Subject<string>();
constructor() {
@@ -49,31 +46,26 @@ export class UmbPartialViewsWorkspaceEditElement extends UmbLitElement {
this._modalContext = instance;
});
//tODO: should this be called something else here?
this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => {
this.#partialViewsWorkspaceContext = workspaceContext as UmbPartialViewsWorkspaceContext;
this.observe(this.#partialViewsWorkspaceContext.name, (name) => {
this.consumeContext(UMB_PARTIAL_VIEW_WORKSPACE_CONTEXT, (workspaceContext) => {
this.#partialViewWorkspaceContext = workspaceContext;
this.observe(this.#partialViewWorkspaceContext.name, (name) => {
this._name = name;
});
this.observe(this.#partialViewsWorkspaceContext.content, (content) => {
this.observe(this.#partialViewWorkspaceContext.content, (content) => {
this._content = content;
});
this.observe(this.#partialViewsWorkspaceContext.path, (path) => {
this.observe(this.#partialViewWorkspaceContext.path, (path) => {
this._path = path;
});
this.observe(this.#partialViewsWorkspaceContext.isNew, (isNew) => {
this.#isNew = !!isNew;
});
this.observe(this.#partialViewsWorkspaceContext.isCodeEditorReady, (isReady) => {
this.observe(this.#partialViewWorkspaceContext.isCodeEditorReady, (isReady) => {
this._ready = isReady;
});
this.inputQuery$.pipe(debounceTime(250)).subscribe((nameInputValue: string) => {
this.#partialViewsWorkspaceContext?.setName(`${nameInputValue}.cshtml`);
this.#partialViewWorkspaceContext?.setName(`${nameInputValue}.cshtml`);
});
});
}
@@ -87,7 +79,7 @@ export class UmbPartialViewsWorkspaceEditElement extends UmbLitElement {
#onCodeEditorInput(event: Event) {
const target = event.target as UmbCodeEditorElement;
const value = target.code as string;
this.#partialViewsWorkspaceContext?.setContent(value);
this.#partialViewWorkspaceContext?.setContent(value);
}
#insertSnippet(event: Event) {
@@ -206,10 +198,10 @@ export class UmbPartialViewsWorkspaceEditElement extends UmbLitElement {
];
}
export default UmbPartialViewsWorkspaceEditElement;
export default UmbPartialViewWorkspaceEditElement;
declare global {
interface HTMLElementTagNameMap {
'umb-partial-views-workspace-edit': UmbPartialViewsWorkspaceEditElement;
'umb-partial-view-workspace-edit': UmbPartialViewWorkspaceEditElement;
}
}

View File

@@ -2,20 +2,20 @@ import { UmbPartialViewsRepository } from '../repository/partial-views.repositor
import { PartialViewDetails } from '../config.js';
import { createObservablePart, UmbBooleanState, UmbDeepState } from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
import { loadCodeEditor } from '@umbraco-cms/backoffice/code-editor';
import { UpdatePartialViewRequestModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
// TODO: I think this should be named PartialViewWorkspace... not with an 's'
export class UmbPartialViewsWorkspaceContext extends UmbWorkspaceContext<
export class UmbPartialViewWorkspaceContext extends UmbWorkspaceContext<
UmbPartialViewsRepository,
PartialViewDetails
> {
> implements UmbEntityWorkspaceContextInterface {
getEntityId(): string | undefined {
return this.getData()?.path;
}
getEntityType(): string {
return 'partial-views';
return 'partial-view';
}
save(): Promise<void> {
const partialView = this.getData();
@@ -41,9 +41,7 @@ export class UmbPartialViewsWorkspaceContext extends UmbWorkspaceContext<
this.repository.save(partialView.path, updateRequestBody);
return Promise.resolve();
}
destroy(): void {
throw new Error('Method not implemented.');
}
#data = new UmbDeepState<PartialViewDetails | undefined>(undefined);
data = this.#data.asObservable();
name = createObservablePart(this.#data, (data) => data?.name);
@@ -54,7 +52,7 @@ export class UmbPartialViewsWorkspaceContext extends UmbWorkspaceContext<
isCodeEditorReady = this.#isCodeEditorReady.asObservable();
constructor(host: UmbControllerHostElement) {
super(host, 'Umb.Workspace.PartialViews', new UmbPartialViewsRepository(host));
super(host, 'Umb.Workspace.PartialView', new UmbPartialViewsRepository(host));
this.#loadCodeEditor();
}
@@ -99,3 +97,10 @@ export class UmbPartialViewsWorkspaceContext extends UmbWorkspaceContext<
this.#data.next(newPartial);
}
}
export const UMB_PARTIAL_VIEW_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbPartialViewWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbPartialViewWorkspaceContext => context.getEntityType?.() === 'partial-view'
);

View File

@@ -1,19 +1,19 @@
import { UmbPartialViewsWorkspaceContext } from './partial-views-workspace.context.js';
import { UmbPartialViewWorkspaceContext } from './partial-view-workspace.context.js';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UmbRoute, IRoutingInfo, PageComponent } from '@umbraco-cms/backoffice/router';
import './partial-views-workspace-edit.element.js';
import './partial-view-workspace-edit.element.js';
import '../../components/insert-menu/templating-insert-menu.element.js';
import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-partial-views-workspace')
export class UmbPartialViewsWorkspaceElement extends UmbLitElement {
#partialViewsWorkspaceContext = new UmbPartialViewsWorkspaceContext(this);
@customElement('umb-partial-view-workspace')
export class UmbPartialViewWorkspaceElement extends UmbLitElement {
#partialViewWorkspaceContext = new UmbPartialViewWorkspaceContext(this);
#element = document.createElement('umb-partial-views-workspace-edit');
#element = document.createElement('umb-partial-view-workspace-edit');
@state()
_routes: UmbRoute[] = [
@@ -24,11 +24,11 @@ export class UmbPartialViewsWorkspaceElement extends UmbLitElement {
const parentKey = info.match.params.parentKey;
const decodePath = decodeURIComponent(parentKey);
const snippetName = info.match.params.snippetName;
this.#partialViewsWorkspaceContext.create(decodePath === 'null' ? null : parentKey, snippetName);
this.#partialViewWorkspaceContext.create(decodePath === 'null' ? null : parentKey, snippetName);
new UmbWorkspaceIsNewRedirectController(
this,
this.#partialViewsWorkspaceContext,
this.#partialViewWorkspaceContext,
this.shadowRoot!.querySelector('umb-router-slot')!
);
},
@@ -39,7 +39,7 @@ export class UmbPartialViewsWorkspaceElement extends UmbLitElement {
setup: (component: PageComponent, info: IRoutingInfo) => {
const key = info.match.params.key;
const decodePath = decodeURIComponent(key).replace('-cshtml', '.cshtml');
this.#partialViewsWorkspaceContext.load(decodePath);
this.#partialViewWorkspaceContext.load(decodePath);
},
},
];
@@ -51,10 +51,10 @@ export class UmbPartialViewsWorkspaceElement extends UmbLitElement {
static styles = [UUITextStyles, css``];
}
export default UmbPartialViewsWorkspaceElement;
export default UmbPartialViewWorkspaceElement;
declare global {
interface HTMLElementTagNameMap {
'umb-partial-views-workspace': UmbPartialViewsWorkspaceElement;
'umb-partial-view-workspace': UmbPartialViewWorkspaceElement;
}
}

View File

@@ -1,14 +1,15 @@
import { UmbStylesheetRepository } from '../repository/stylesheet.repository.js';
import { StylesheetDetails } from '../index.js';
import { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbArrayState, UmbBooleanState, UmbObjectState, createObservablePart } from '@umbraco-cms/backoffice/observable-api';
import { loadCodeEditor } from '@umbraco-cms/backoffice/code-editor';
import { RichTextRuleModel, UpdateStylesheetRequestModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export type RichTextRuleModelSortable = RichTextRuleModel & { sortOrder?: number };
export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext<UmbStylesheetRepository, StylesheetDetails> {
export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext<UmbStylesheetRepository, StylesheetDetails> implements UmbEntityWorkspaceContextInterface {
#data = new UmbObjectState<StylesheetDetails | undefined>(undefined);
#rules = new UmbArrayState<RichTextRuleModelSortable>([], (rule) => rule.name);
data = this.#data.asObservable();
@@ -158,3 +159,8 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext<UmbStyles
this.#data.complete();
}
}
export const UMB_STYLESHEET_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbStylesheetWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbStylesheetWorkspaceContext => context.getEntityType?.() === 'stylesheet'
);

View File

@@ -2,7 +2,7 @@ import type { UmbTemplatingInsertMenuElement } from '../../components/insert-men
import { UMB_MODAL_TEMPLATING_INSERT_SECTION_MODAL } from '../../modals/insert-section-modal/insert-section-modal.element.js';
import { UMB_TEMPLATE_QUERY_BUILDER_MODAL } from '../modals/modal-tokens.js';
import { getQuerySnippet } from '../../utils.js';
import type { UmbTemplateWorkspaceContext } from './template-workspace.context.js';
import { UMB_TEMPLATE_WORKSPACE_CONTEXT } from './template-workspace.context.js';
import type { UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor';
import { camelCase } from '@umbraco-cms/backoffice/external/lodash';
import { UUITextStyles, UUIInputElement } from '@umbraco-cms/backoffice/external/uui';
@@ -14,7 +14,6 @@ import {
} from '@umbraco-cms/backoffice/modal';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { Subject, debounceTime } from '@umbraco-cms/backoffice/external/rxjs';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-template-workspace-editor')
export class UmbTemplateWorkspaceEditorElement extends UmbLitElement {
@@ -36,7 +35,7 @@ export class UmbTemplateWorkspaceEditorElement extends UmbLitElement {
@query('umb-code-editor')
private _codeEditor?: UmbCodeEditorElement;
#templateWorkspaceContext?: UmbTemplateWorkspaceContext;
#templateWorkspaceContext?: typeof UMB_TEMPLATE_WORKSPACE_CONTEXT.TYPE;
#isNew = false;
#masterTemplateId: string | null = null;
@@ -50,8 +49,8 @@ export class UmbTemplateWorkspaceEditorElement extends UmbLitElement {
this._modalContext = instance;
});
this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => {
this.#templateWorkspaceContext = workspaceContext as UmbTemplateWorkspaceContext;
this.consumeContext(UMB_TEMPLATE_WORKSPACE_CONTEXT, (workspaceContext) => {
this.#templateWorkspaceContext = workspaceContext;
this.observe(this.#templateWorkspaceContext.name, (name) => {
this._name = name;
});

View File

@@ -1,6 +1,6 @@
import { UmbTemplateRepository } from '../repository/template.repository.js';
import { loadCodeEditor } from '@umbraco-cms/backoffice/code-editor';
import { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
import {
createObservablePart,
UmbBooleanState,
@@ -9,8 +9,9 @@ import {
} from '@umbraco-cms/backoffice/observable-api';
import type { TemplateItemResponseModel, TemplateResponseModel } from '@umbraco-cms/backoffice/backend-api';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export class UmbTemplateWorkspaceContext extends UmbWorkspaceContext<UmbTemplateRepository, TemplateResponseModel> {
export class UmbTemplateWorkspaceContext extends UmbWorkspaceContext<UmbTemplateRepository, TemplateResponseModel> implements UmbEntityWorkspaceContextInterface {
#data = new UmbDeepState<TemplateResponseModel | undefined>(undefined);
data = this.#data.asObservable();
#masterTemplate = new UmbObjectState<TemplateItemResponseModel | null>(null);
@@ -163,5 +164,13 @@ ${currentContent}`;
public destroy() {
this.#data.complete();
super.destroy();
}
}
export const UMB_TEMPLATE_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbTemplateWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbTemplateWorkspaceContext => context.getEntityType?.() === 'template'
);

View File

@@ -1,21 +1,20 @@
import { UmbUserWorkspaceContext } from '../../../users/workspace/user-workspace.context.js';
import { UMB_USER_WORKSPACE_CONTEXT } from '../../../users/workspace/user-workspace.context.js';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-workspace-action-user-group-save')
export class UmbWorkspaceActionUserGroupSaveElement extends UmbLitElement {
@state()
private _saveButtonState?: UUIButtonState;
private _workspaceContext?: UmbUserWorkspaceContext;
private _workspaceContext?: typeof UMB_USER_WORKSPACE_CONTEXT.TYPE;
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
this._workspaceContext = instance as UmbUserWorkspaceContext;
this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (instance) => {
this._workspaceContext = instance;
});
}

View File

@@ -1,11 +1,10 @@
import { UmbUserGroupWorkspaceContext } from './user-group-workspace.context.js';
import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from './user-group-workspace.context.js';
import { UUIInputElement, UUIInputEvent, UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit';
// TODO: import from package when available
//import { UmbUserInputElement } from '../../users/components/user-input/user-input.element.js';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import { UserGroupResponseModel } from '@umbraco-cms/backoffice/backend-api';
import {
UMB_CONFIRM_MODAL,
@@ -21,14 +20,14 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
@state()
private _userKeys?: Array<string>;
#workspaceContext?: UmbUserGroupWorkspaceContext;
#workspaceContext?: typeof UMB_USER_GROUP_WORKSPACE_CONTEXT.TYPE;
#modalContext?: UmbModalManagerContext;
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance as UmbUserGroupWorkspaceContext;
this.consumeContext(UMB_USER_GROUP_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance;
this.observe(this.#workspaceContext.data, (userGroup) => (this._userGroup = userGroup));
this.observe(this.#workspaceContext.userIds, (userKeys) => (this._userKeys = userKeys));
});

View File

@@ -4,6 +4,7 @@ import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbrac
import type { UserGroupResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbArrayState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export class UmbUserGroupWorkspaceContext
extends UmbWorkspaceContext<UmbUserGroupRepository, UserGroupResponseModel>
@@ -102,3 +103,9 @@ export class UmbUserGroupWorkspaceContext
this.#userIds.next(keys);
}
}
export const UMB_USER_GROUP_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbUserGroupWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbUserGroupWorkspaceContext => context.getEntityType?.() === 'user-group'
);

View File

@@ -1,21 +1,20 @@
import { UmbUserWorkspaceContext } from '../user-workspace.context.js';
import { UMB_USER_WORKSPACE_CONTEXT } from '../user-workspace.context.js';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-user-workspace-action-save')
export class UmbUserWorkspaceActionSaveElement extends UmbLitElement {
@state()
private _saveButtonState?: UUIButtonState;
private _workspaceContext?: UmbUserWorkspaceContext;
private _workspaceContext?: typeof UMB_USER_WORKSPACE_CONTEXT.TYPE;
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
this._workspaceContext = instance as UmbUserWorkspaceContext;
this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (instance) => {
this._workspaceContext = instance;
});
}

View File

@@ -4,7 +4,7 @@ import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbrac
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import type { UpdateUserRequestModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
import { UmbContextConsumerController, UmbContextToken } from '@umbraco-cms/backoffice/context-api';
import { UMB_AUTH } from '@umbraco-cms/backoffice/auth';
import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs';
@@ -81,3 +81,8 @@ export class UmbUserWorkspaceContext
this.#data.complete();
}
}
export const UMB_USER_WORKSPACE_CONTEXT = new UmbContextToken<UmbEntityWorkspaceContextInterface, UmbUserWorkspaceContext>(
'UmbWorkspaceContext',
(context): context is UmbUserWorkspaceContext => context.getEntityType?.() === 'user'
);

View File

@@ -2,6 +2,5 @@ import { IUmbAuth } from './auth.interface.js';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export const UMB_AUTH = new UmbContextToken<IUmbAuth>(
'UmbAuth',
'An instance of UmbAuthFlow that should be shared across the app.'
'UmbAuth'
);

View File

@@ -5,7 +5,7 @@ import { Meta } from '@storybook/blocks';
# Context API
The Context API enables connections between Elements and APIs.
DOM structure defines the context of which an API is exposed for. APIs are provided via an element and can then be consumed by any decending element wthin.
DOM structure defines the context of which an API is exposed for. APIs are provided via an element and can then be consumed by any decending element.
### Consume a Context API.
@@ -18,7 +18,7 @@ this.consumeContext('requestThisContextAlias', (context) => {
});
```
Or with a Controller using a 'host' reference to Controller Host(Umbraco Element/Controller):
Or with a Controller using a 'host' reference to Controller Host(Thats either a Umbraco Element or just another Controller):
```ts
new UmbContextConsumerController(host, 'requestThisContextAlias', (context) => {
@@ -27,6 +27,91 @@ new UmbContextConsumerController(host, 'requestThisContextAlias', (context) => {
});
```
#### Context Token
Using a Context Token gives you a typed context:
```ts
import { UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification';
this.consumeContext(UMB_NOTIFICATION_CONTEXT_TOKEN, (context) => {
// Notice this is a subscription, as context might change or a new one appears, but the value is strongly typed
console.log("I've got the context of the right type", context);
});
```
#### Write your own Context Token
A Context Token is generally just a string matched with a type. In this way users of the token can be sure to get the right type of context.
```ts
import { ContextToken } from '@umbraco-cms/backoffice/context';
type MyContext = {
foo: string;
bar: number;
};
const MY_CONTEXT_TOKEN = new ContextToken<MyContext>('My.Context.Token');
```
#### Context Token with discriminator.
Notice this is only relevant if you are going to make multiple context API for the same context.
In some cases we need to have different APIs for the same context. Our Workspace Contexts is a good example of this.
If someone wants the workspace name, they might not care about the specific API of the Workspace Context. These implementations can use a standard Context Token with a type of a generic Workspace Context.
Our Document Workspace Context, has features around Publishing. We do not want a new Context for these features, as we want to make sure when we are in a Workspace, we do not accidentally retrieve workspace context of a parent workspace. So we need to provide a workspace context in each workspace, the one we retrieve is the one we will be using.
But since publishing is not part of the generic Workspace Context, we need to identify if the context is a Document Workspace Context and then recast it.
To avoid each implementation taking care of this, Context Tokens can be extended with a type discriminator.
This will dicard the given api if it does not live up to the needs, and when it is the decired type, it will cast the api to the desired type.
This example, shows how to create a discriminator Context Token, that will discard the api if it is not a Publishable Context:
Context token example:
```ts
import { ContextToken } from '@umbraco-cms/backoffice/context';
interface MyBaseContext {
foo: string;
bar: number;
};
interface MyPublishableContext extends MyBaseContext {
publish()
};
const MY_PUBLISHABLE_CONTEXT_TOKEN = new ContextToken<MyContext, MyPublishableContext>('My.Context.Token', (context): context is MyPublishableContext => {
return 'publish' in context;
});
```
Implementation of context token example:
```ts
const contextElement = new UmbLitElement();
contextElement.provideContext(MY_PUBLISHABLE_CONTEXT_TOKEN, new MyPublishableContext());
const consumerElement = new UmbLitElement();
contextElement.appendChild(contextElement);
consumerElement.consumeContext(MY_PUBLISHABLE_CONTEXT_TOKEN, (context) => {
// context is of type 'MyPublishableContext'
console.log("I've got the context of the right type", context);
});
```
This enables implementors to request a publishable context, without the knowledge about how do identify such, neither they need to know about the Type.
In details, the Context API will find the first API matching alias 'My.Context.Token', and never look furhter. If that API does live up to the type discriminator, it will be returned. If not the consumer will never reply.
### Provide a Context API.
From a Umbraco Element or Umbraco Controller:

View File

@@ -15,22 +15,6 @@ provideContext<R = unknown>(alias: string | UmbContextToken<R>, instance: R): Um
consumeContext<R = unknown>(alias: string | UmbContextToken<R>, callback: UmbContextCallback<R>): UmbContextConsumerController<R>
```
Use these for an smooth consumption, like this request for a Context API using a simple string context, where the callback value is of an unknown type:
Read about the 'observe' method in the [Store-API](?path=/docs/guides-store--docs).
```ts
this.consumeContext('requestThisContextAlias', (context) => {
// Notice this is a subscription, as context might change or a new one appears.
console.log("I've got the context", context);
});
```
Or use the a Context Token to get a typed context:
```ts
import { UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification';
this.consumeContext(UMB_NOTIFICATION_CONTEXT_TOKEN, (context) => {
// Notice this is a subscription, as context might change or a new one appears, but the value is strongly typed
console.log("I've got the context", context);
});
```
Read about the 'provideContext' and 'consumeContext' methods in the [Context-API](?path=/docs/guides-context-api--docs).