Feature/tree store base (#514)

* out comment temprorary for development

* initial prep

* comment

* change port number for dev generate api

* generated new apis

* document-type repository

* rename to item

* rename to document

* use ItemType

* not name detail for full models

* correct token

* imports

* correct imports

* use DocumentTypeTreeItem

* mega type adapt commit

* move DataType import

* rename document detail store

* add document

* new mock data

* partialUpdateFrozenArray

* imports

* document context work

* document and document type in context

* data-type stores + data-sources

* byKey document + data-type

* remove type

* comment

* data-type repository

* data-type context adjustments

* data-type data observable

* fix model import

* use ContentTypeCompositionType

* correct mock data

* .

* split treedata / data

* correct mock endpoints

* new models

* update model usage

* correct models

* imports

* correct models

* update model imports

* update models

* update type

* update docuemnt models

* use DocumentModel

* DocumentModel

* import lit/decorators.js

* lint fixes

* remove console.logs

* implementation of tree store base class

---------

Co-authored-by: Mads Rasmussen <madsr@hey.com>
This commit is contained in:
Niels Lyngsø
2023-02-13 14:23:53 +01:00
committed by GitHub
parent 818bcb35bb
commit 60ad1c3835
8 changed files with 121 additions and 302 deletions

View File

@@ -1,5 +1,5 @@
import { DeepState } from "./deep-state";
import { pushToUniqueArray } from "./push-to-unique-array.method";
import { DeepState } from './deep-state';
import { pushToUniqueArray } from './push-to-unique-array.method';
/**
* @export
@@ -12,14 +12,41 @@ import { pushToUniqueArray } from "./push-to-unique-array.method";
*/
export class ArrayState<T> extends DeepState<T[]> {
constructor(initialData: T[], private _getUnique?: (entry: T) => unknown) {
super(initialData);
}
/**
* @method append
* @method remove
* @param {unknown[]} uniques - The unique values to remove.
* @return {ArrayState<T>} Reference to it self.
* @description - Remove some new data of this Subject.
* @example <caption>Example remove entry with key '1' and '2'</caption>
* const data = [
* { key: 1, value: 'foo'},
* { key: 2, value: 'bar'}
* ];
* const myState = new ArrayState(data, (x) => x.key);
* myState.remove([1, 2]);
*/
remove(uniques: unknown[]) {
let next = this.getValue();
if (this._getUnique) {
uniques.forEach((unique) => {
next = next.filter((x) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return this._getUnique(x) !== unique;
});
});
this.next(next);
}
return this;
}
/**
* @method removeOne
* @param {unknown} unique - The unique value to remove.
* @return {ArrayState<T>} Reference to it self.
* @description - Remove some new data of this Subject.
@@ -29,19 +56,16 @@ export class ArrayState<T> extends DeepState<T[]> {
* { key: 2, value: 'bar'}
* ];
* const myState = new ArrayState(data, (x) => x.key);
* myState.remove([1]);
* myState.removeOne(1);
*/
remove(uniques: unknown[]) {
removeOne(unique: unknown) {
let next = this.getValue();
if (this._getUnique) {
uniques.forEach( unique => {
next = next.filter(x => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return this._getUnique(x) !== unique;
})
}
);
next = next.filter((x) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return this._getUnique(x) !== unique;
});
this.next(next);
}
@@ -89,7 +113,7 @@ export class ArrayState<T> extends DeepState<T[]> {
*/
appendOne(entry: T) {
const next = [...this.getValue()];
if(this._getUnique) {
if (this._getUnique) {
pushToUniqueArray(next, entry, this._getUnique);
} else {
next.push(entry);
@@ -115,9 +139,9 @@ export class ArrayState<T> extends DeepState<T[]> {
* ]);
*/
append(entries: T[]) {
if(this._getUnique) {
if (this._getUnique) {
const next = [...this.getValue()];
entries.forEach(entry => {
entries.forEach((entry) => {
pushToUniqueArray(next, entry, this._getUnique!);
});
this.next(next);

View File

@@ -1,3 +1,4 @@
export * from './icon/icon.store';
export * from './store';
export * from './store-base';
export * from './tree-store-base';

View File

@@ -0,0 +1,68 @@
import { EntityTreeItemModel } from '@umbraco-cms/backend-api';
import { ArrayState, partialUpdateFrozenArray } from '@umbraco-cms/observable-api';
import { UmbStoreBase } from '@umbraco-cms/store';
/**
* @export
* @class UmbTreeStoreBase
* @extends {UmbStoreBase}
* @description - General Tree Data Store
*/
// TODO: consider if tree store could be turned into a general EntityTreeStore class?
export class UmbTreeStoreBase extends UmbStoreBase {
#data = new ArrayState<EntityTreeItemModel>([], (x) => x.key);
/**
* Appends items to the store
* @param {Array<EntityTreeItemModel>} items
* @memberof UmbTreeStoreBase
*/
appendItems(items: Array<EntityTreeItemModel>) {
this.#data.append(items);
}
/**
* Updates an item in the store
* @param {string} key
* @param {Partial<EntityTreeItemModel>} data
* @memberof UmbTreeStoreBase
*/
updateItem(key: string, data: Partial<EntityTreeItemModel>) {
this.#data.next(partialUpdateFrozenArray(this.#data.getValue(), data, (entry) => entry.key === key));
}
/**
* Removes an item from the store
* @param {string} key
* @memberof UmbTreeStoreBase
*/
removeItem(key: string) {
this.#data.removeOne(key);
}
/**
* An observable to observe the root items
* @memberof UmbTreeStoreBase
*/
rootItems = this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === null));
/**
* Returns an observable to observe the children of a given parent
* @param {(string | null)} parentKey
* @return {*}
* @memberof UmbTreeStoreBase
*/
childrenOf(parentKey: string | null) {
return this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === parentKey));
}
/**
* Returns an observable to observe the items with the given keys
* @param {Array<string>} keys
* @return {*}
* @memberof UmbTreeStoreBase
*/
items(keys: Array<string>) {
return this.#data.getObservablePart((items) => items.filter((item) => keys.includes(item.key ?? '')));
}
}

View File

@@ -1,7 +1,5 @@
import { EntityTreeItemModel } from '@umbraco-cms/backend-api';
import { UmbContextToken } from '@umbraco-cms/context-api';
import { ArrayState } from '@umbraco-cms/observable-api';
import { UmbStoreBase } from '@umbraco-cms/store';
import { UmbTreeStoreBase } from '@umbraco-cms/store';
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
/**
@@ -11,9 +9,7 @@ import { UmbControllerHostInterface } from '@umbraco-cms/controller';
* @description - Tree Data Store for Document-Types
*/
// TODO: consider if tree store could be turned into a general EntityTreeStore class?
export class UmbDocumentTypeTreeStore extends UmbStoreBase {
#data = new ArrayState<EntityTreeItemModel>([], (x) => x.key);
export class UmbDocumentTypeTreeStore extends UmbTreeStoreBase {
/**
* Creates an instance of UmbDocumentTypeTreeStore.
* @param {UmbControllerHostInterface} host
@@ -22,70 +18,6 @@ export class UmbDocumentTypeTreeStore extends UmbStoreBase {
constructor(host: UmbControllerHostInterface) {
super(host, UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN.toString());
}
/**
* Appends items to the store
* @param {Array<EntityTreeItemModel>} items
* @memberof UmbDocumentTypeTreeStore
*/
appendItems(items: Array<EntityTreeItemModel>) {
this.#data.append(items);
}
/**
* Updates an item in the store
* @param {string} key
* @param {Partial<EntityTreeItemModel>} data
* @memberof UmbDocumentTypeTreeStore
*/
updateItem(key: string, data: Partial<EntityTreeItemModel>) {
const entries = this.#data.getValue();
const entry = entries.find((entry) => entry.key === key);
if (entry) {
this.#data.appendOne({ ...entry, ...data });
}
}
/**
* Removes an item from the store
* @param {string} key
* @memberof UmbDocumentTypeTreeStore
*/
removeItem(key: string) {
const entries = this.#data.getValue();
const entry = entries.find((entry) => entry.key === key);
if (entry) {
this.#data.remove([key]);
}
}
/**
* An observable to observe the root items
* @memberof UmbDocumentTypeTreeStore
*/
rootItems = this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === null));
/**
* Returns an observable to observe the children of a given parent
* @param {(string | null)} parentKey
* @return {*}
* @memberof UmbDocumentTypeTreeStore
*/
childrenOf(parentKey: string | null) {
return this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === parentKey));
}
/**
* Returns an observable to observe the items with the given keys
* @param {Array<string>} keys
* @return {*}
* @memberof UmbDocumentTypeTreeStore
*/
items(keys: Array<string>) {
return this.#data.getObservablePart((items) => items.filter((item) => keys.includes(item.key ?? '')));
}
}
export const UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbDocumentTypeTreeStore>(

View File

@@ -1,19 +1,14 @@
import { EntityTreeItemModel } from '@umbraco-cms/backend-api';
import { UmbContextToken } from '@umbraco-cms/context-api';
import { ArrayState } from '@umbraco-cms/observable-api';
import { UmbStoreBase } from '@umbraco-cms/store';
import { UmbTreeStoreBase } from '@umbraco-cms/store';
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
/**
* @export
* @class UmbDocumentTreeStore
* @extends {UmbStoreBase}
* @extends {UmbTreeStoreBase}
* @description - Tree Data Store for Templates
*/
// TODO: consider if tree store could be turned into a general EntityTreeStore class?
export class UmbDocumentTreeStore extends UmbStoreBase {
#data = new ArrayState<EntityTreeItemModel>([], (x) => x.key);
export class UmbDocumentTreeStore extends UmbTreeStoreBase {
/**
* Creates an instance of UmbDocumentTreeStore.
* @param {UmbControllerHostInterface} host
@@ -22,70 +17,6 @@ export class UmbDocumentTreeStore extends UmbStoreBase {
constructor(host: UmbControllerHostInterface) {
super(host, UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN.toString());
}
/**
* Appends items to the store
* @param {Array<EntityTreeItemModel>} items
* @memberof UmbDocumentTreeStore
*/
appendItems(items: Array<EntityTreeItemModel>) {
this.#data.append(items);
}
/**
* Updates an item in the store
* @param {string} key
* @param {Partial<EntityTreeItemModel>} data
* @memberof UmbDocumentTreeStore
*/
updateItem(key: string, data: Partial<EntityTreeItemModel>) {
const entries = this.#data.getValue();
const entry = entries.find((entry) => entry.key === key);
if (entry) {
this.#data.appendOne({ ...entry, ...data });
}
}
/**
* Removes an item from the store
* @param {string} key
* @memberof UmbDocumentTreeStore
*/
removeItem(key: string) {
const entries = this.#data.getValue();
const entry = entries.find((entry) => entry.key === key);
if (entry) {
this.#data.remove([key]);
}
}
/**
* An observable to observe the root items
* @memberof UmbDocumentTreeStore
*/
rootItems = this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === null));
/**
* Returns an observable to observe the children of a given parent
* @param {(string | null)} parentKey
* @return {*}
* @memberof UmbDocumentTreeStore
*/
childrenOf(parentKey: string | null) {
return this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === parentKey));
}
/**
* Returns an observable to observe the items with the given keys
* @param {Array<string>} keys
* @return {*}
* @memberof UmbDocumentTreeStore
*/
items(keys: Array<string>) {
return this.#data.getObservablePart((items) => items.filter((item) => keys.includes(item.key ?? '')));
}
}
export const UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbDocumentTreeStore>(

View File

@@ -1,8 +1,6 @@
import { EntityTreeItemModel } from '@umbraco-cms/backend-api';
import { UmbContextToken } from '@umbraco-cms/context-api';
import { ArrayState } from '@umbraco-cms/observable-api';
import { UmbStoreBase } from '@umbraco-cms/store';
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
import { UmbTreeStoreBase } from '@umbraco-cms/store';
/**
* @export
@@ -11,9 +9,7 @@ import { UmbControllerHostInterface } from '@umbraco-cms/controller';
* @description - Tree Data Store for Data-Types
*/
// TODO: consider if tree store could be turned into a general EntityTreeStore class?
export class UmbDataTypeTreeStore extends UmbStoreBase {
#data = new ArrayState<EntityTreeItemModel>([], (x) => x.key);
export class UmbDataTypeTreeStore extends UmbTreeStoreBase {
/**
* Creates an instance of UmbDataTypeTreeStore.
* @param {UmbControllerHostInterface} host
@@ -22,70 +18,6 @@ export class UmbDataTypeTreeStore extends UmbStoreBase {
constructor(host: UmbControllerHostInterface) {
super(host, UMB_DATA_TYPE_TREE_STORE_CONTEXT_TOKEN.toString());
}
/**
* Appends items to the store
* @param {Array<EntityTreeItemModel>} items
* @memberof UmbDataTypeTreeStore
*/
appendItems(items: Array<EntityTreeItemModel>) {
this.#data.append(items);
}
/**
* Updates an item in the store
* @param {string} key
* @param {Partial<EntityTreeItemModel>} data
* @memberof UmbDataTypeTreeStore
*/
updateItem(key: string, data: Partial<EntityTreeItemModel>) {
const entries = this.#data.getValue();
const entry = entries.find((entry) => entry.key === key);
if (entry) {
this.#data.appendOne({ ...entry, ...data });
}
}
/**
* Removes an item from the store
* @param {string} key
* @memberof UmbDataTypeTreeStore
*/
removeItem(key: string) {
const entries = this.#data.getValue();
const entry = entries.find((entry) => entry.key === key);
if (entry) {
this.#data.remove([key]);
}
}
/**
* An observable to observe the root items
* @memberof UmbDataTypeTreeStore
*/
rootItems = this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === null));
/**
* Returns an observable to observe the children of a given parent
* @param {(string | null)} parentKey
* @return {*}
* @memberof UmbDataTypeTreeStore
*/
childrenOf(parentKey: string | null) {
return this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === parentKey));
}
/**
* Returns an observable to observe the items with the given keys
* @param {Array<string>} keys
* @return {*}
* @memberof UmbDataTypeTreeStore
*/
items(keys: Array<string>) {
return this.#data.getObservablePart((items) => items.filter((item) => keys.includes(item.key ?? '')));
}
}
export const UMB_DATA_TYPE_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbDataTypeTreeStore>(

View File

@@ -1,7 +1,5 @@
import type { EntityTreeItemModel } from '@umbraco-cms/backend-api';
import { UmbContextToken } from '@umbraco-cms/context-api';
import { ArrayState } from '@umbraco-cms/observable-api';
import { UmbStoreBase } from '@umbraco-cms/store';
import { UmbTreeStoreBase } from '@umbraco-cms/store';
import type { UmbControllerHostInterface } from '@umbraco-cms/controller';
/**
@@ -10,9 +8,7 @@ import type { UmbControllerHostInterface } from '@umbraco-cms/controller';
* @extends {UmbStoreBase}
* @description - Tree Data Store for Templates
*/
export class UmbTemplateTreeStore extends UmbStoreBase {
#data = new ArrayState<EntityTreeItemModel>([], (x) => x.key);
export class UmbTemplateTreeStore extends UmbTreeStoreBase {
/**
* Creates an instance of UmbTemplateTreeStore.
* @param {UmbControllerHostInterface} host
@@ -21,71 +17,6 @@ export class UmbTemplateTreeStore extends UmbStoreBase {
constructor(host: UmbControllerHostInterface) {
super(host, UMB_TEMPLATE_TREE_STORE_CONTEXT_TOKEN.toString());
}
/**
* Appends items to the store
* @param {Array<EntityTreeItem>} items
* @memberof UmbTemplateTreeStore
*/
appendItems(items: Array<EntityTreeItemModel>) {
this.#data.append(items);
}
/**
* Updates an item in the store
* @param {string} key
* @param {Partial<EntityTreeItem>} data
* @memberof UmbTemplateTreeStore
*/
updateItem(key: string, data: Partial<EntityTreeItemModel>) {
const entries = this.#data.getValue();
const entry = entries.find((entry) => entry.key === key);
if (entry) {
this.#data.appendOne({ ...entry, ...data });
}
}
/**
* Removes an item from the store
* @param {string} key
* @memberof UmbTemplateTreeStore
*/
removeItem(key: string) {
const entries = this.#data.getValue();
const entry = entries.find((entry) => entry.key === key);
if (entry) {
this.#data.remove([key]);
}
}
/**
* Returns an observable to observe the root items
* @return {*}
* @memberof UmbTemplateTreeStore
*/
rootItems = this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === null));
/**
* Returns an observable to observe the children of a given parent
* @param {(string | null)} parentKey
* @return {*}
* @memberof UmbTemplateTreeStore
*/
childrenOf(parentKey: string | null) {
return this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === parentKey));
}
/**
* Returns an observable to observe the items with the given keys
* @param {Array<string>} keys
* @return {*}
* @memberof UmbTemplateTreeStore
*/
items(keys: Array<string>) {
return this.#data.getObservablePart((items) => items.filter((item) => keys.includes(item.key ?? '')));
}
}
export const UMB_TEMPLATE_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbTemplateTreeStore>(

View File

@@ -379,7 +379,7 @@ export const treeData: Array<DocumentTreeItemModel> = [
name: 'All property editors',
type: 'document',
icon: 'icon-item-arrangement',
hasChildren: false,
hasChildren: true,
},
{
isProtected: false,