diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-base.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-base.ts new file mode 100644 index 0000000000..42dee34374 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-base.ts @@ -0,0 +1,24 @@ +import { UmbData } from '../data.js'; + +export abstract class UmbEntityMockDbBase extends UmbData { + constructor(data: Array) { + super(data); + } + + create(item: MockItemType) { + this.data.push(item); + } + + read(id: string) { + return this.data.find((item) => item.id === id); + } + + update(id: string, updatedItem: MockItemType) { + const itemIndex = this.data.findIndex((item) => item.id === id); + this.data[itemIndex] = updatedItem; + } + + delete(id: string) { + this.data = this.data.filter((item) => item.id !== id); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-detail.manager.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-detail.manager.ts new file mode 100644 index 0000000000..9bcca3d802 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-detail.manager.ts @@ -0,0 +1,46 @@ +import { UmbEntityMockDbBase } from './entity-base.js'; + +export class UmbMockEntityDetailManager { + #db: UmbEntityMockDbBase; + #createMockItemMapper: (request: any) => MockType; + #readResponseMapper: (mockItem: MockType) => any; + + constructor( + db: UmbEntityMockDbBase, + createMockItemMapper: (request: any) => MockType, + readResponseMapper: (mockItem: MockType) => any, + ) { + this.#db = db; + this.#createMockItemMapper = createMockItemMapper; + this.#readResponseMapper = readResponseMapper; + } + + create(request: any) { + const mockItem = this.#createMockItemMapper(request); + // create mock item in mock db + this.#db.create(mockItem); + return mockItem.id; + } + + read(id: string) { + const item = this.#db.read(id); + if (!item) throw new Error('Item not found'); + const mappedItem = this.#readResponseMapper(item); + return mappedItem; + } + + update(id: string, item: any) { + const mockItem = this.#db.read(id); + + const updatedMockItem = { + ...mockItem, + ...item, + } as unknown as MockType; + + this.#db.update(id, updatedMockItem); + } + + delete(path: string) { + this.#db.delete(path); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-folder.manager.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-folder.manager.ts new file mode 100644 index 0000000000..dd11be95a2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-folder.manager.ts @@ -0,0 +1,61 @@ +import { UmbEntityMockDbBase } from './entity-base.js'; +import { + CreateFolderRequestModel, + FolderResponseModel, + FolderTreeItemResponseModel, + UpdateFolderResponseModel, +} from '@umbraco-cms/backoffice/backend-api'; + +export class UmbMockEntityFolderManager> { + #db: UmbEntityMockDbBase; + #createMockFolderMapper: (request: CreateFolderRequestModel) => MockItemType; + + constructor( + db: UmbEntityMockDbBase, + createMockFolderMapper: (request: CreateFolderRequestModel) => MockItemType, + ) { + this.#db = db; + this.#createMockFolderMapper = createMockFolderMapper; + } + + create(request: CreateFolderRequestModel) { + const newFolder = this.#createMockFolderMapper(request); + this.#db.create(newFolder); + return newFolder.id; + } + + read(id: string) { + const mockItem = this.#db.read(id); + if (mockItem?.isFolder) { + return this.#defaultReadMapper(mockItem); + } else { + return undefined; + } + } + + update(id: string, request: UpdateFolderResponseModel) { + const mockItem = this.#db.read(id); + + const updatedMockItem = { + ...mockItem, + name: request.name, + } as unknown as MockItemType; + + this.#db.update(id, updatedMockItem); + } + + delete(id: string) { + const dbItem = this.#db.read(id); + if (dbItem?.isFolder) { + this.#db.delete(id); + } + } + + #defaultReadMapper = (item: MockItemType): FolderResponseModel => { + return { + name: item.name, + id: item.id, + parentId: item.parentId, + }; + }; +} diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-item.manager.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-item.manager.ts new file mode 100644 index 0000000000..7d3219e7b5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-item.manager.ts @@ -0,0 +1,16 @@ +import { UmbData } from '../data.js'; + +export class UmbMockEntityItemManager { + #db: UmbData; + #itemReadMapper: (item: T) => any; + + constructor(db: UmbData, itemReadMapper: (item: T) => any) { + this.#db = db; + this.#itemReadMapper = itemReadMapper; + } + + getItems(ids: Array) { + const items = this.#db.getData().filter((item) => ids.includes(item.id)); + return items.map((item) => this.#itemReadMapper(item)); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-tree.manager.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-tree.manager.ts new file mode 100644 index 0000000000..724d3e62ce --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/entity/entity-tree.manager.ts @@ -0,0 +1,82 @@ +import { UmbId } from '@umbraco-cms/backoffice/id'; +import { UmbEntityMockDbBase } from './entity-base.js'; +import { EntityTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; + +export class UmbMockEntityTreeManager> { + #db: UmbEntityMockDbBase; + #treeItemMapper: (item: T) => any; + + constructor(mockDb: UmbEntityMockDbBase, treeItemMapper: (item: T) => any) { + this.#db = mockDb; + this.#treeItemMapper = treeItemMapper; + } + + getRoot() { + const items = this.#db.getData().filter((item) => item.parentId === null); + const treeItems = items.map((item) => this.#treeItemMapper(item)); + const total = items.length; + return { items: treeItems, total }; + } + + getChildrenOf(parentId: string) { + const items = this.#db.getData().filter((item) => item.parentId === parentId); + const treeItems = items.map((item) => this.#treeItemMapper(item)); + const total = items.length; + return { items: treeItems, total }; + } + + move(ids: Array, destinationId: string) { + const destinationItem = this.#db.read(destinationId); + if (!destinationItem) throw new Error(`Destination item with id ${destinationId} not found`); + + const items: Array = []; + + ids.forEach((id) => { + const item = this.#db.read(id); + if (!item) throw new Error(`Item with id ${id} not found`); + items.push(item); + }); + + const movedItems = items.map((item) => { + return { + ...item, + parentId: destinationId, + }; + }); + + movedItems.forEach((movedItem: any) => this.#db.update(movedItem.id, movedItem)); + destinationItem.hasChildren = true; + this.#db.update(destinationItem.id, destinationItem); + } + + copy(ids: Array, destinationId: string) { + const destinationItem = this.#db.read(destinationId); + if (!destinationItem) throw new Error(`Destination item with id ${destinationId} not found`); + + // TODO: Notice we don't add numbers to the 'copy' name. + const items: Array = []; + + ids.forEach((id) => { + const item = this.#db.read(id); + if (!item) throw new Error(`Item with id ${id} not found`); + items.push(item); + }); + + const copyItems = items.map((item) => { + return { + ...item, + name: item.name + ' Copy', + id: UmbId.new(), + parentId: destinationId, + }; + }); + + copyItems.forEach((copyItem) => this.#db.create(copyItem)); + const newIds = copyItems.map((item) => item.id); + + destinationItem.hasChildren = true; + this.#db.update(destinationItem.id, destinationItem); + + return newIds; + } +}