Merge remote-tracking branch 'origin/main' into feature/property-editor-content-picker

This commit is contained in:
Niels Lyngsø
2023-01-12 09:26:07 +01:00
13 changed files with 2585 additions and 1036 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -55,7 +55,7 @@
"npm": ">=8.0.0 < 9"
},
"dependencies": {
"@umbraco-ui/uui": "^1.0.2",
"@umbraco-ui/uui": "^1.1.0",
"@umbraco-ui/uui-css": "^1.0.0",
"@umbraco-ui/uui-modal": "file:umbraco-ui-uui-modal-0.0.0.tgz",
"@umbraco-ui/uui-modal-container": "file:umbraco-ui-uui-modal-container-0.0.0.tgz",
@@ -96,9 +96,9 @@
"babel-loader": "^9.1.2",
"eslint": "^8.31.0",
"eslint-config-prettier": "^8.6.0",
"eslint-import-resolver-typescript": "^3.5.2",
"eslint-import-resolver-typescript": "^3.5.3",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-lit": "^1.7.2",
"eslint-plugin-lit": "^1.8.0",
"eslint-plugin-lit-a11y": "^2.3.0",
"eslint-plugin-local-rules": "^1.3.2",
"eslint-plugin-storybook": "^0.6.8",

View File

@@ -20,6 +20,7 @@ import { UmbDocumentBlueprintStore } from './documents/document-blueprints/docum
import { UmbSectionStore } from './shared/components/section/section.store';
import { UmbDataTypeStore } from './settings/data-types/data-type.store';
import { UmbLitElement } from '@umbraco-cms/element';
// Domains
import './settings';
@@ -31,7 +32,6 @@ import './users';
import './packages';
import './search';
import './shared';
import { UmbLitElement } from '@umbraco-cms/element';
@defineElement('umb-backoffice')
export class UmbBackofficeElement extends UmbLitElement {
@@ -53,23 +53,24 @@ export class UmbBackofficeElement extends UmbLitElement {
constructor() {
super();
this.provideContext('umbModalService', new UmbModalService());
this.provideContext('umbNotificationService', new UmbNotificationService());
// TODO: find a way this is possible outside this element. It needs to be possible to register stores in extensions
this.provideContext('umbCurrentUserStore', new UmbCurrentUserStore());
this.provideContext('umbDocumentStore', new UmbDocumentStore());
this.provideContext('umbMediaStore', new UmbMediaStore());
this.provideContext('umbDataTypeStore', new UmbDataTypeStore());
this.provideContext('umbDocumentTypeStore', new UmbDocumentTypeStore());
this.provideContext('umbMediaTypeStore', new UmbMediaTypeStore());
this.provideContext('umbMemberTypeStore', new UmbMemberTypeStore());
this.provideContext('umbUserStore', new UmbUserStore());
this.provideContext('umbUserGroupStore', new UmbUserGroupStore());
this.provideContext('umbMemberGroupStore', new UmbMemberGroupStore());
this.provideContext('umbNotificationService', new UmbNotificationService());
this.provideContext('umbModalService', new UmbModalService());
this.provideContext('umbDocumentStore', new UmbDocumentStore(this));
this.provideContext('umbMediaStore', new UmbMediaStore(this));
this.provideContext('umbDataTypeStore', new UmbDataTypeStore(this));
this.provideContext('umbDocumentTypeStore', new UmbDocumentTypeStore(this));
this.provideContext('umbMediaTypeStore', new UmbMediaTypeStore(this));
this.provideContext('umbMemberTypeStore', new UmbMemberTypeStore(this));
this.provideContext('umbUserStore', new UmbUserStore(this));
this.provideContext('umbUserGroupStore', new UmbUserGroupStore(this));
this.provideContext('umbMemberGroupStore', new UmbMemberGroupStore(this));
this.provideContext('umbSectionStore', new UmbSectionStore());
this.provideContext('umbCurrentUserHistoryStore', new UmbCurrentUserHistoryStore());
this.provideContext('umbDictionaryStore', new UmbDictionaryStore());
this.provideContext('umbDocumentBlueprintStore', new UmbDocumentBlueprintStore());
this.provideContext('umbDictionaryStore', new UmbDictionaryStore(this));
this.provideContext('umbDocumentBlueprintStore', new UmbDocumentBlueprintStore(this));
}
render() {

View File

@@ -1,7 +1,8 @@
import { map, Observable } from 'rxjs';
import { UmbDataStoreBase } from '../../../core/stores/store';
import { ApiError, DocumentTypeResource, DocumentTypeTreeItem, ProblemDetails } from '@umbraco-cms/backend-api';
import { DocumentTypeResource, DocumentTypeTreeItem } from '@umbraco-cms/backend-api';
import type { DocumentTypeDetails } from '@umbraco-cms/models';
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
export const isDocumentTypeDetails = (
documentType: DocumentTypeDetails | DocumentTypeTreeItem
@@ -57,39 +58,26 @@ export class UmbDocumentTypeStore extends UmbDataStoreBase<UmbDocumentTypeStoreI
}
getTreeRoot(): Observable<Array<DocumentTypeTreeItem>> {
DocumentTypeResource.getTreeDocumentTypeRoot({}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(this.host, DocumentTypeResource.getTreeDocumentTypeRoot({})).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null)));
}
getTreeItemChildren(key: string): Observable<Array<DocumentTypeTreeItem>> {
DocumentTypeResource.getTreeDocumentTypeChildren({
parentKey: key,
}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(
this.host,
DocumentTypeResource.getTreeDocumentTypeChildren({
parentKey: key,
})
).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
return this.items.pipe(map((items) => items.filter((item) => item.parentKey === key)));
}

View File

@@ -1,7 +1,8 @@
import { map, Observable } from 'rxjs';
import { UmbNodeStoreBase } from '../../../core/stores/store';
import type { DocumentDetails } from '@umbraco-cms/models';
import { ApiError, DocumentResource, DocumentTreeItem, FolderTreeItem, ProblemDetails } from '@umbraco-cms/backend-api';
import { DocumentResource, DocumentTreeItem, FolderTreeItem } from '@umbraco-cms/backend-api';
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
export const isDocumentDetails = (document: DocumentDetails | DocumentTreeItem): document is DocumentDetails => {
return (document as DocumentDetails).data !== undefined;
@@ -79,19 +80,11 @@ export class UmbDocumentStore extends UmbNodeStoreBase<UmbDocumentStoreItemType>
}
getTreeRoot(): Observable<Array<DocumentTreeItem>> {
DocumentResource.getTreeDocumentRoot({}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(this.host, DocumentResource.getTreeDocumentRoot({})).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
// TODO: how do we handle trashed items?
// TODO: remove ignore when we know how to handle trashed items.
@@ -101,21 +94,16 @@ export class UmbDocumentStore extends UmbNodeStoreBase<UmbDocumentStoreItemType>
}
getTreeItemChildren(key: string): Observable<Array<FolderTreeItem>> {
DocumentResource.getTreeDocumentChildren({
parentKey: key,
}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(
this.host,
DocumentResource.getTreeDocumentChildren({
parentKey: key,
})
).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
// TODO: how do we handle trashed items?
// TODO: remove ignore when we know how to handle trashed items.
@@ -126,21 +114,16 @@ export class UmbDocumentStore extends UmbNodeStoreBase<UmbDocumentStoreItemType>
getTreeItems(keys: Array<string>): Observable<Array<FolderTreeItem>> {
if (keys?.length > 0) {
DocumentResource.getTreeDocumentItem({
key: keys,
}).then(
(items) => {
this.updateItems(items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(
this.host,
DocumentResource.getTreeDocumentItem({
key: keys,
})
).then(({ data }) => {
if (data) {
this.updateItems(data);
}
);
});
}
return this.items.pipe(map((items) => items.filter((item) => keys.includes(item.key ?? ''))));

View File

@@ -1,7 +1,8 @@
import { map, Observable } from 'rxjs';
import { UmbNodeStoreBase } from '../../../core/stores/store';
import { MediaTypeResource, ApiError, ProblemDetails, FolderTreeItem } from '@umbraco-cms/backend-api';
import { MediaTypeResource, FolderTreeItem } from '@umbraco-cms/backend-api';
import type { MediaTypeDetails } from '@umbraco-cms/models';
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
export type UmbMediaTypeStoreItemType = MediaTypeDetails | FolderTreeItem;
/**
@@ -60,39 +61,26 @@ export class UmbMediaTypeStore extends UmbNodeStoreBase<UmbMediaTypeStoreItemTyp
}
getTreeRoot(): Observable<Array<FolderTreeItem>> {
MediaTypeResource.getTreeMediaTypeRoot({}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(this.host, MediaTypeResource.getTreeMediaTypeRoot({})).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null)));
}
getTreeItemChildren(key: string): Observable<Array<FolderTreeItem>> {
MediaTypeResource.getTreeMediaTypeChildren({
parentKey: key,
}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(
this.host,
MediaTypeResource.getTreeMediaTypeChildren({
parentKey: key,
})
).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
return this.items.pipe(map((items) => items.filter((item) => item.parentKey === key)));
}

View File

@@ -1,7 +1,8 @@
import { map, Observable } from 'rxjs';
import { UmbDataStoreBase } from '../../../core/stores/store';
import type { MediaDetails } from '@umbraco-cms/models';
import { ApiError, ContentTreeItem, MediaResource, ProblemDetails } from '@umbraco-cms/backend-api';
import { ContentTreeItem, MediaResource } from '@umbraco-cms/backend-api';
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
const isMediaDetails = (media: UmbMediaStoreItemType): media is MediaDetails => {
return (media as MediaDetails).data !== undefined;
@@ -75,19 +76,11 @@ export class UmbMediaStore extends UmbDataStoreBase<UmbMediaStoreItemType> {
}
getTreeRoot(): Observable<Array<ContentTreeItem>> {
MediaResource.getTreeMediaRoot({}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(this.host, MediaResource.getTreeMediaRoot({})).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
// TODO: how do we handle trashed items?
// TODO: remove ignore when we know how to handle trashed items.
@@ -97,21 +90,16 @@ export class UmbMediaStore extends UmbDataStoreBase<UmbMediaStoreItemType> {
}
getTreeItemChildren(key: string): Observable<Array<ContentTreeItem>> {
MediaResource.getTreeMediaChildren({
parentKey: key,
}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(
this.host,
MediaResource.getTreeMediaChildren({
parentKey: key,
})
).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
// TODO: how do we handle trashed items?
// TODO: remove ignore when we know how to handle trashed items.

View File

@@ -1,7 +1,8 @@
import { map, Observable } from 'rxjs';
import { UmbNodeStoreBase } from '../../../core/stores/store';
import { ApiError, EntityTreeItem, MemberGroupResource, ProblemDetails } from '@umbraco-cms/backend-api';
import { EntityTreeItem, MemberGroupResource } from '@umbraco-cms/backend-api';
import type { MemberGroupDetails } from '@umbraco-cms/models';
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
export type UmbMemberGroupStoreItemType = MemberGroupDetails | EntityTreeItem;
@@ -23,19 +24,11 @@ export class UmbMemberGroupStore extends UmbNodeStoreBase<UmbMemberGroupStoreIte
}
getTreeRoot(): Observable<Array<EntityTreeItem>> {
MemberGroupResource.getTreeMemberGroupRoot({}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(this.host, MemberGroupResource.getTreeMemberGroupRoot({})).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null)));
}

View File

@@ -1,7 +1,8 @@
import { map, Observable } from 'rxjs';
import { UmbDataStoreBase } from '../../../core/stores/store';
import { MemberTypeResource, ApiError, EntityTreeItem, ProblemDetails } from '@umbraco-cms/backend-api';
import { MemberTypeResource, EntityTreeItem } from '@umbraco-cms/backend-api';
import type { MemberTypeDetails } from '@umbraco-cms/models';
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
export type UmbMemberTypeStoreItemType = MemberTypeDetails | EntityTreeItem;
@@ -23,19 +24,11 @@ export class UmbMemberTypeStore extends UmbDataStoreBase<UmbMemberTypeStoreItemT
}
getTreeRoot(): Observable<Array<EntityTreeItem>> {
MemberTypeResource.getTreeMemberTypeRoot({}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(this.host, MemberTypeResource.getTreeMemberTypeRoot({})).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null)));
}

View File

@@ -1,7 +1,8 @@
import { map, Observable } from 'rxjs';
import { UmbDataStoreBase } from '../../../core/stores/store';
import type { DataTypeDetails } from '@umbraco-cms/models';
import { ApiError, DataTypeResource, FolderTreeItem, ProblemDetails } from '@umbraco-cms/backend-api';
import { DataTypeResource, FolderTreeItem } from '@umbraco-cms/backend-api';
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
const isDataTypeDetails = (dataType: DataTypeDetails | FolderTreeItem): dataType is DataTypeDetails => {
return (dataType as DataTypeDetails).data !== undefined;
@@ -14,7 +15,6 @@ export type UmbDataTypeStoreItemType = DataTypeDetails | FolderTreeItem;
// TODO: research how we write names of global consts.
export const STORE_ALIAS = 'umbDataTypeStore';
/**
* @export
* @class UmbDataTypesStore
@@ -22,7 +22,6 @@ export const STORE_ALIAS = 'umbDataTypeStore';
* @description - Data Store for Data Types
*/
export class UmbDataTypeStore extends UmbDataStoreBase<UmbDataTypeStoreItemType> {
public readonly storeAlias = STORE_ALIAS;
/**
@@ -95,19 +94,11 @@ export class UmbDataTypeStore extends UmbDataStoreBase<UmbDataTypeStoreItemType>
* @memberof UmbDataTypesStore
*/
getTreeRoot(): Observable<Array<FolderTreeItem>> {
DataTypeResource.getTreeDataTypeRoot({}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(this.host, DataTypeResource.getTreeDataTypeRoot({})).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null)));
}
@@ -119,21 +110,16 @@ export class UmbDataTypeStore extends UmbDataStoreBase<UmbDataTypeStoreItemType>
* @memberof UmbDataTypesStore
*/
getTreeItemChildren(key: string): Observable<Array<FolderTreeItem>> {
DataTypeResource.getTreeDataTypeChildren({
parentKey: key,
}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(
this.host,
DataTypeResource.getTreeDataTypeChildren({
parentKey: key,
})
).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
return this.items.pipe(map((items) => items.filter((item) => item.parentKey === key)));
}

View File

@@ -146,7 +146,7 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
this.observe(this._propertyContext.label, (label) => {
this._label = label;
});
this.observe(this._propertyContext.label, (description) => {
this.observe(this._propertyContext.description, (description) => {
this._description = description;
});

View File

@@ -1,6 +1,7 @@
import { map, Observable } from 'rxjs';
import { UmbDataStoreBase } from '../../../core/stores/store';
import { ApiError, DictionaryResource, EntityTreeItem, ProblemDetails } from '@umbraco-cms/backend-api';
import { DictionaryResource, EntityTreeItem } from '@umbraco-cms/backend-api';
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
/**
* @export
@@ -17,19 +18,11 @@ export class UmbDictionaryStore extends UmbDataStoreBase<EntityTreeItem> {
* @memberof UmbDictionaryStore
*/
getTreeRoot(): Observable<Array<EntityTreeItem>> {
DictionaryResource.getTreeDictionaryRoot({}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(this.host, DictionaryResource.getTreeDictionaryRoot({})).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
return this.items.pipe(map((items) => items.filter((item) => item.parentKey === null)));
}
@@ -41,21 +34,16 @@ export class UmbDictionaryStore extends UmbDataStoreBase<EntityTreeItem> {
* @memberof UmbDataTypesStore
*/
getTreeItemChildren(key: string): Observable<Array<EntityTreeItem>> {
DictionaryResource.getTreeDictionaryChildren({
parentKey: key,
}).then(
(res) => {
this.updateItems(res.items);
},
(e) => {
if (e instanceof ApiError) {
const error = e.body as ProblemDetails;
if (e.status === 400) {
console.log(error.detail);
}
}
tryExecuteAndNotify(
this.host,
DictionaryResource.getTreeDictionaryChildren({
parentKey: key,
})
).then(({ data }) => {
if (data) {
this.updateItems(data.items);
}
);
});
return this.items.pipe(map((items) => items.filter((item) => item.parentKey === key)));
}

View File

@@ -1,4 +1,5 @@
import type { Observable } from 'rxjs';
import { UmbControllerHostInterface } from '../controller/controller-host.mixin';
import { UniqueBehaviorSubject } from '../observable-api/unique-behavior-subject';
export interface UmbDataStoreIdentifiers {
@@ -30,6 +31,12 @@ export abstract class UmbDataStoreBase<T extends UmbDataStoreIdentifiers> implem
protected _items = new UniqueBehaviorSubject(<Array<T>>[]);
public readonly items = this._items.asObservable();
protected host: UmbControllerHostInterface;
constructor(host: UmbControllerHostInterface) {
this.host = host;
}
/**
* @description - Delete items from the store.
* @param {Array<string>} keys
@@ -40,8 +47,6 @@ export abstract class UmbDataStoreBase<T extends UmbDataStoreIdentifiers> implem
this._items.next(remainingItems);
}
/**
* @description - Update the store with new items. Existing items are updated, new items are added, old are kept. Items are matched by the compareKey.
* @param {Array<T>} items
@@ -52,7 +57,7 @@ export abstract class UmbDataStoreBase<T extends UmbDataStoreIdentifiers> implem
const newData = [...this._items.getValue()];
items.forEach((newItem) => {
const storedItemIndex = newData.findIndex((item) => item[compareKey] === newItem[compareKey]);
if(storedItemIndex !== -1) {
if (storedItemIndex !== -1) {
newData[storedItemIndex] = newItem;
} else {
newData.push(newItem);