Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
184bfe5
ability to set discriminator method
nielslyngsoe Aug 22, 2023
dac1b04
test context discriminator
nielslyngsoe Aug 22, 2023
a9b3034
clean up
nielslyngsoe Aug 23, 2023
1743448
Merge remote-tracking branch 'origin/main' into feature/context-api-d…
nielslyngsoe Aug 23, 2023
d9361f3
Embed the discriminator method in ContextToken
nielslyngsoe Aug 23, 2023
f1df5de
main type dance, still 6 minor things to correct.
nielslyngsoe Aug 23, 2023
5e682ed
temp commit, before test removing DicriminatorType
nielslyngsoe Aug 24, 2023
7c568cd
one less generic type to parse around
nielslyngsoe Aug 24, 2023
0566c08
implement UMB_DATA_TYPE_WORKSPACE_CONTEXT
nielslyngsoe Aug 24, 2023
2b1f130
user workspace context token
nielslyngsoe Aug 24, 2023
be80bca
stylesheet
nielslyngsoe Aug 24, 2023
ce64884
media
nielslyngsoe Aug 24, 2023
b8770e4
member
nielslyngsoe Aug 24, 2023
8882d97
document
nielslyngsoe Aug 24, 2023
4ff3ddd
language
nielslyngsoe Aug 24, 2023
19b6e24
template
nielslyngsoe Aug 24, 2023
03b5f89
media-type
nielslyngsoe Aug 24, 2023
2995880
user group
nielslyngsoe Aug 24, 2023
0673f08
dictionary
nielslyngsoe Aug 24, 2023
f377531
member type
nielslyngsoe Aug 24, 2023
e1816f6
member group
nielslyngsoe Aug 24, 2023
b71b8ab
correct member group token
nielslyngsoe Aug 24, 2023
363eea6
relation type
nielslyngsoe Aug 24, 2023
ef136ac
partial views
nielslyngsoe Aug 24, 2023
95789d4
document-type
nielslyngsoe Aug 24, 2023
cae029b
remove unused prop
nielslyngsoe Aug 24, 2023
8d51012
remove console.log
nielslyngsoe Aug 24, 2023
49c2f89
docs
nielslyngsoe Aug 24, 2023
7f1bbc7
import order
nielslyngsoe Aug 24, 2023
9bfbf98
variable name update
nielslyngsoe Aug 24, 2023
339b970
correct text
nielslyngsoe Aug 24, 2023
a3b5e1f
added implementation example
nielslyngsoe Aug 24, 2023
1e791b9
minor correction
nielslyngsoe Aug 24, 2023
37ce69d
Mega refactor v.1
nielslyngsoe Aug 25, 2023
df5b10d
fix broken story
nielslyngsoe Aug 27, 2023
0a8113f
variant dataset for documents
nielslyngsoe Aug 27, 2023
b39f395
split-view folder name
nielslyngsoe Aug 27, 2023
a89e9d8
UMB_VARIANT_WORKSPACE_CONTEXT_TOKEN
nielslyngsoe Aug 27, 2023
20078ea
data-type workspace using dataset
nielslyngsoe Aug 27, 2023
9e73c90
datatype editor reactive corrections
nielslyngsoe Aug 28, 2023
4fb3c22
restructure
nielslyngsoe Aug 28, 2023
abd8ff9
invariant dataset
nielslyngsoe Aug 28, 2023
b076104
controller aliases
nielslyngsoe Aug 28, 2023
88d646a
expose registry on backoffice element
nielslyngsoe Aug 28, 2023
4933306
JSDocs
nielslyngsoe Aug 28, 2023
716ba3e
UmbServerExtensionRegistrator
nielslyngsoe Aug 28, 2023
f6e7ae0
notes
nielslyngsoe Aug 28, 2023
2659e6a
clean up
nielslyngsoe Aug 28, 2023
e012db3
fixing todos
nielslyngsoe Aug 28, 2023
a4ea14c
more notes
nielslyngsoe Aug 28, 2023
fa00a12
Header app manifest correction
nielslyngsoe Aug 28, 2023
a229cab
remove custom element from ist of extensions
nielslyngsoe Aug 28, 2023
6aa3524
custom bundle package
nielslyngsoe Aug 28, 2023
eb489c5
fix tabs bar displaying
nielslyngsoe Aug 28, 2023
a944bee
correction bundle section
nielslyngsoe Aug 28, 2023
938380a
entry point as a controller
nielslyngsoe Aug 28, 2023
2650790
correct entry point to use onInit method
nielslyngsoe Aug 29, 2023
0b0f719
remove comma
nielslyngsoe Aug 29, 2023
9800143
adding a line break
nielslyngsoe Aug 29, 2023
8ea40ca
remove test code
nielslyngsoe Aug 29, 2023
5380fa3
a bit of documentation
nielslyngsoe Aug 29, 2023
52fe1e9
more docs notes
nielslyngsoe Aug 29, 2023
d6f394b
fix type issue
nielslyngsoe Aug 29, 2023
e4ca30c
remove unused file
nielslyngsoe Sep 1, 2023
4279c50
improve variantID
nielslyngsoe Sep 1, 2023
895c67b
rename to createVariantDatasetContext
nielslyngsoe Sep 1, 2023
d8d8732
rename to variant context
nielslyngsoe Sep 4, 2023
a208b92
Merge branch 'main' into feature/variant-context-as-workspace-context
nielslyngsoe Sep 4, 2023
e17f102
Merge remote-tracking branch 'origin/feature/variant-context-as-datas…
nielslyngsoe Sep 4, 2023
78f56bf
rename to extensionRegistry
nielslyngsoe Sep 4, 2023
2b02f43
Merge remote-tracking branch 'origin/main' into feature/variant-conte…
nielslyngsoe Sep 5, 2023
6430842
rename dataset to variant
nielslyngsoe Sep 6, 2023
3c0918a
Update src/apps/backoffice/backoffice.element.ts
nielslyngsoe Sep 6, 2023
419070e
rename create methods
nielslyngsoe Sep 6, 2023
1ee3895
Merge branch 'feature/variant-context-as-workspace-context' of https:…
nielslyngsoe Sep 6, 2023
317202d
createVariantContext
nielslyngsoe Sep 6, 2023
5d07dd7
isDataTypeVariantContext
nielslyngsoe Sep 6, 2023
b55ea27
clean up
nielslyngsoe Sep 6, 2023
3bb77d3
more corrections
nielslyngsoe Sep 6, 2023
2697b8a
comment for future refactor
nielslyngsoe Sep 6, 2023
697a4b4
Merge remote-tracking branch 'origin/main' into feature/variant-conte…
nielslyngsoe Sep 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
"Backoffice",
"combobox",
"Elementable",
"invariantable",
"Niels",
"pickable",
"Registrator",
"templating",
"tinymce",
"umbraco",
Expand Down
13 changes: 13 additions & 0 deletions public-assets/App_Plugins/custom-bundle-package/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const manifests = [
{
type: 'section',
alias: 'MyBundle.Section.Custom',
name: 'Custom Section',
js: '/App_Plugins/section.js',
weight: 1,
meta: {
label: 'My Bundle Section',
pathname: 'my-custom-bundle',
},
}
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "My Package Name",
"version": "1.0.0",
"extensions": [
{
"type": "bundle",
"alias": "My.Package.Bundle",
"name": "My Package Bundle",
"js": "/App_Plugins/custom-bundle-package/index.js"
}
]
}
4 changes: 2 additions & 2 deletions public-assets/App_Plugins/custom-entrypoint.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
console.log('Hello from the custom entrypoint file!');
export default function () {
console.log('Hello from the custom entrypoint inside the default function!');
export function onInit() {
console.log('Hello from the custom entrypoint inside the onInit function!');
}
20 changes: 17 additions & 3 deletions src/apps/backoffice/backoffice.element.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { UmbBackofficeContext, UMB_BACKOFFICE_CONTEXT_TOKEN } from './backoffice.context.js';
import { UmbExtensionInitializer } from './extension-initializer.controller.js';
import { UmbServerExtensionRegistrator } from './server-extension-registrator.controller.js';
import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import {
Expand Down Expand Up @@ -28,14 +28,28 @@ const CORE_PACKAGES = [

@customElement('umb-backoffice')
export class UmbBackofficeElement extends UmbLitElement {

/**
* Backoffice extension registry.
* This enables to register and unregister extensions via DevTools, or just via querying this element via the DOM.
* @type {UmbExtensionsRegistry}
*/
public extensionRegistry = umbExtensionsRegistry;

constructor() {
super();

this.provideContext(UMB_BACKOFFICE_CONTEXT_TOKEN, new UmbBackofficeContext(this));
new UmbBundleExtensionInitializer(this, umbExtensionsRegistry);
new UmbEntryPointExtensionInitializer(this, umbExtensionsRegistry);
new UmbServerExtensionRegistrator(this, umbExtensionsRegistry);

// So far local packages are this simple to registerer, so no need for a manager to do that:
CORE_PACKAGES.forEach(async (packageImport) => {
const packageModule = await packageImport;
umbExtensionsRegistry.registerMany(packageModule.extensions);
});

const extensionInitializer = new UmbExtensionInitializer(this, umbExtensionsRegistry);
extensionInitializer.setLocalPackages(CORE_PACKAGES);
}

render() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,44 +1,22 @@
import { Subject } from '@umbraco-cms/backoffice/external/rxjs';
import { PackageResource, OpenAPI } from '@umbraco-cms/backoffice/backend-api';
import { UmbBaseController, UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbBackofficeExtensionRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
import { ManifestBase, isManifestJSType } from '@umbraco-cms/backoffice/extension-api';

// TODO: consider if this can be replaced by the new extension controllers.
// TODO: consider if this can be replaced by the new extension controllers
// TODO: move local part out of this, and name something with server.
export class UmbExtensionInitializer extends UmbBaseController {
export class UmbServerExtensionRegistrator extends UmbBaseController {
#extensionRegistry: UmbBackofficeExtensionRegistry;
#unobserve = new Subject<void>();
#localPackages: Array<Promise<any>> = [];
#apiBaseUrl = OpenAPI.BASE;

constructor(host: UmbControllerHost, extensionRegistry: UmbBackofficeExtensionRegistry) {
super(host, UmbExtensionInitializer.name);
super(host, UmbServerExtensionRegistrator.name);
this.#extensionRegistry = extensionRegistry;
}

setLocalPackages(localPackages: Array<Promise<any>>) {
this.#localPackages = localPackages;
this.#loadLocalPackages();
}

hostConnected(): void {
// TODO: This was before in hostConnected(), but I don't see the reason to wait. lets just do it right away.
this.#loadServerPackages();
}

hostDisconnected(): void {
this.#unobserve.next();
this.#unobserve.complete();
}

async #loadLocalPackages() {
this.#localPackages.forEach(async (packageImport) => {
const packageModule = await packageImport;
this.#extensionRegistry.registerMany(packageModule.extensions);
});
}

async #loadServerPackages() {
/* TODO: we need a new endpoint here, to remove the dependency on the package repository, to get the modules available for the backoffice scope
/ we will need a similar endpoint for the login, installer etc at some point.
Expand Down
7 changes: 4 additions & 3 deletions src/libs/extension-api/bundle-extension-initializer.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import type { ManifestBase, ManifestBundle } from './types.js';
import { loadExtension } from './load-extension.function.js';
import { UmbExtensionRegistry } from './registry/extension.registry.js';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbBaseController, UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';

export class UmbBundleExtensionInitializer {
export class UmbBundleExtensionInitializer extends UmbBaseController {
#extensionRegistry;
#bundleMap = new Map();

constructor(host: UmbControllerHostElement, extensionRegistry: UmbExtensionRegistry<ManifestBundle>) {
super(host);
this.#extensionRegistry = extensionRegistry;
extensionRegistry.extensionsOfType('bundle').subscribe((bundles) => {
this.observe(extensionRegistry.extensionsOfType('bundle'), (bundles) => {
// Unregister removed bundles:
this.#bundleMap.forEach((existingBundle) => {
if (!bundles.find((b) => b.alias === existingBundle.alias)) {
Expand Down
7 changes: 5 additions & 2 deletions src/libs/extension-api/entry-point-extension-initializer.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { UmbBaseController } from '../controller-api/controller.class.js';
import type { ManifestEntryPoint } from './types.js';
import { hasInitExport } from './has-init-export.function.js';
import { loadExtension } from './load-extension.function.js';
import { UmbExtensionRegistry } from './registry/extension.registry.js';
import { UmbElement } from '@umbraco-cms/backoffice/element-api';

export class UmbEntryPointExtensionInitializer {
export class UmbEntryPointExtensionInitializer extends UmbBaseController {

#host;
#extensionRegistry;
#entryPointMap = new Map();

constructor(host: UmbElement, extensionRegistry: UmbExtensionRegistry<ManifestEntryPoint>) {
super(host);
this.#host = host;
this.#extensionRegistry = extensionRegistry;
extensionRegistry.extensionsOfType('entryPoint').subscribe((entryPoints) => {
this.observe(extensionRegistry.extensionsOfType('entryPoint'), (entryPoints) => {
entryPoints.forEach((entryPoint) => {
if (this.#entryPointMap.has(entryPoint.alias)) return;
this.#entryPointMap.set(entryPoint.alias, entryPoint);
Expand Down
12 changes: 12 additions & 0 deletions src/mocks/handlers/manifests.handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ export const manifestDevelopmentHandler = rest.get(umbracoPath('/package/manifes
// Respond with a 200 status code
ctx.status(200),
ctx.json<PackageManifestResponse>([
{
name: 'My Package Name',
version: '1.0.0',
extensions: [
{
type: 'bundle',
alias: 'My.Package.Bundle',
name: 'My Package Bundle',
js: '/App_Plugins/custom-bundle-package/index.js',
},
],
},
{
name: 'Named Package',
version: '1.0.0',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ export class UmbCollectionSelectionActionsElement extends UmbLitElement {
// TODO: Make sure it only updates on length change.
this.observe(this._collectionContext.items, (mediaItems) => {
this._nodesLength = mediaItems.length;
});
}, 'observeItem');

this.observe(this._collectionContext.selection, (selection) => {
this._selectionLength = selection.length;
this._selection = selection;
});
}, 'observeSelection');
}

private _renderSelectionCount() {
Expand All @@ -74,6 +74,7 @@ export class UmbCollectionSelectionActionsElement extends UmbLitElement {
(bulkActions) => {
this._entityBulkActions = bulkActions;
}
, 'observeEntityBulkActions'
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,22 @@
import { html, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from "@umbraco-cms/backoffice/style";
import {
PropertyEditorConfigDefaultData,
PropertyEditorConfigProperty,
umbExtensionsRegistry,
} from '@umbraco-cms/backoffice/extension-registry';

import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UMB_PROPERTY_EDITOR_SCHEMA_ALIAS_DEFAULT } from '@umbraco-cms/backoffice/property-editor';
import { UMB_DATA_TYPE_VARIANT_CONTEXT } from '@umbraco-cms/backoffice/data-type';

/**
* @element umb-property-editor-config
* @description - Element for displaying the configuration for a Property Editor based on a Property Editor UI Alias and a Property Editor Model alias.
* @element umb-property-editor-config
* @description - Element for displaying the configuration for a Property Editor based on a Property Editor UI Alias and a Property Editor Model alias.
* This element requires a UMB_DATA_TYPE_WORKSPACE_CONTEXT to be present.
*/
@customElement('umb-property-editor-config')
export class UmbPropertyEditorConfigElement extends UmbLitElement {
/**
* Property Editor UI Alias. The element will render configuration for a Property Editor UI with this alias.
* @type {string}
* @attr
* @default ''
*/
private _propertyEditorUiAlias = '';
@property({ type: String, attribute: 'property-editor-ui-alias' })
public get propertyEditorUiAlias(): string {
return this._propertyEditorUiAlias;
}
public set propertyEditorUiAlias(value: string) {
const oldVal = this._propertyEditorUiAlias;
this._propertyEditorUiAlias = value;
this.requestUpdate('propertyEditorUiAlias', oldVal);
this._observePropertyEditorUIConfig();
}

// TODO: Make this element generic, so its not bound to DATA-TYPEs. This will require moving some functionality of Data-Type-Context to this. and this might need to self provide a variant Context for its inner property editor UIs.
#variantContext?: typeof UMB_DATA_TYPE_VARIANT_CONTEXT.TYPE;

/**
* Data. The element will render configuration editors with values from this data.
Expand All @@ -46,62 +31,17 @@ export class UmbPropertyEditorConfigElement extends UmbLitElement {
@state()
private _properties: Array<PropertyEditorConfigProperty> = [];

private _propertyEditorSchemaConfigDefaultData: Array<PropertyEditorConfigDefaultData> = [];
private _propertyEditorUISettingsDefaultData: Array<PropertyEditorConfigDefaultData> = [];

private _configDefaultData?: Array<PropertyEditorConfigDefaultData>;

private _propertyEditorSchemaConfigProperties: Array<PropertyEditorConfigProperty> = [];
private _propertyEditorUISettingsProperties: Array<PropertyEditorConfigProperty> = [];
constructor() {
super();

private _observePropertyEditorUIConfig() {
if (!this._propertyEditorUiAlias) return;

this.observe(
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUi', this.propertyEditorUiAlias),
(manifest) => {
this._observePropertyEditorSchemaConfig(
manifest?.meta.propertyEditorSchemaAlias || UMB_PROPERTY_EDITOR_SCHEMA_ALIAS_DEFAULT
);
this._propertyEditorUISettingsProperties = manifest?.meta.settings?.properties || [];
this._propertyEditorUISettingsDefaultData = manifest?.meta.settings?.defaultData || [];
this._mergeConfigProperties();
this._mergeConfigDefaultData();
}
);
}
this.consumeContext(UMB_DATA_TYPE_VARIANT_CONTEXT, (instance) => {
this.#variantContext = instance;
this.observe(this.#variantContext.properties, (properties) => {
this._properties = properties as Array<PropertyEditorConfigProperty>;
}, 'observeProperties');
});

private _observePropertyEditorSchemaConfig(propertyEditorSchemaAlias: string) {
this.observe(
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorSchema', propertyEditorSchemaAlias),
(manifest) => {
this._propertyEditorSchemaConfigProperties = manifest?.meta.settings?.properties || [];
this._propertyEditorSchemaConfigDefaultData = manifest?.meta.settings?.defaultData || [];
this._mergeConfigProperties();
this._mergeConfigDefaultData();
}
);
}

private _mergeConfigProperties() {
this._properties = [...this._propertyEditorSchemaConfigProperties, ...this._propertyEditorUISettingsProperties];
}

private _mergeConfigDefaultData() {
this._configDefaultData = [
...this._propertyEditorSchemaConfigDefaultData,
...this._propertyEditorUISettingsDefaultData,
];
}

/**
* Get the stored value for a property. It will render the default value from the configuration if no value is stored in the database.
*/
private _getValue(property: PropertyEditorConfigProperty) {
const value = this.data.find((data) => data.alias === property.alias)?.value;
if (value) return value;
const defaultValue = this._configDefaultData?.find((data) => data.alias === property.alias)?.value;
return defaultValue ?? null;
}

render() {
Expand All @@ -115,7 +55,6 @@ export class UmbPropertyEditorConfigElement extends UmbLitElement {
description="${ifDefined(property.description)}"
alias="${property.alias}"
property-editor-ui-alias="${property.propertyEditorUiAlias}"
.value=${this._getValue(property)}
.config=${property.config}></umb-workspace-property>
`
)}
Expand Down
Loading