diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/media-type-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/media-type-create-options-modal.element.ts index bb154f5629..8d63fbb260 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/media-type-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/media-type-create-options-modal.element.ts @@ -1,4 +1,4 @@ -import { UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../../repository/index.js'; +import { MEDIA_TYPE_FOLDER_REPOSITORY_ALIAS } from '../../../repository/index.js'; import { UmbMediaTypeCreateOptionsModalData } from './index.js'; import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -31,7 +31,8 @@ export class UmbDataTypeCreateOptionsModalElement extends UmbLitElement { event.stopPropagation(); const folderModalHandler = this.#modalContext?.open(UMB_FOLDER_MODAL, { data: { - repositoryAlias: UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS, + repositoryAlias: MEDIA_TYPE_FOLDER_REPOSITORY_ALIAS, + parentUnique: this.data?.parentKey, }, }); folderModalHandler?.onSubmit().then(() => this.modalContext?.submit()); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/folder/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/folder/index.ts new file mode 100644 index 0000000000..9f104e5a13 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/folder/index.ts @@ -0,0 +1,2 @@ +export { UmbMediaTypeFolderRepository } from './media-type-folder.repository.js'; +export { UMB_MEDIA_TYPE_FOLDER_REPOSITORY_ALIAS as MEDIA_TYPE_FOLDER_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/folder/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/folder/manifests.ts new file mode 100644 index 0000000000..3c5228286d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/folder/manifests.ts @@ -0,0 +1,13 @@ +import { UmbMediaTypeFolderRepository } from './media-type-folder.repository.js'; +import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +export const UMB_MEDIA_TYPE_FOLDER_REPOSITORY_ALIAS = 'Umb.Repository.MediaType.Folder'; + +const folderRepository: ManifestRepository = { + type: 'repository', + alias: UMB_MEDIA_TYPE_FOLDER_REPOSITORY_ALIAS, + name: 'Media Type Folder Repository', + api: UmbMediaTypeFolderRepository, +}; + +export const manifests = [folderRepository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/folder/media-type-folder.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/folder/media-type-folder.repository.ts new file mode 100644 index 0000000000..61c1dcb6a1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/folder/media-type-folder.repository.ts @@ -0,0 +1,89 @@ +import { createFolderTreeItem } from '../utils.js'; +import { UMB_MEDIA_TYPE_TREE_STORE_CONTEXT, UmbMediaTypeTreeStore } from '../../tree/media-type-tree.store.js'; +import { UmbMediaTypeFolderServerDataSource } from './media-type-folder.server.data.js'; +import { + type UmbFolderRepository, + type UmbFolderDataSource, + UmbRepositoryBase, +} from '@umbraco-cms/backoffice/repository'; +import { type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { CreateFolderRequestModel, FolderModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; +import { UMB_NOTIFICATION_CONTEXT_TOKEN, UmbNotificationContext } from '@umbraco-cms/backoffice/notification'; +export class UmbMediaTypeFolderRepository extends UmbRepositoryBase implements UmbFolderRepository { + #init: Promise; + #folderSource: UmbFolderDataSource; + #treeStore?: UmbMediaTypeTreeStore; + #notificationContext?: UmbNotificationContext; + + constructor(host: UmbControllerHost) { + super(host); + this.#folderSource = new UmbMediaTypeFolderServerDataSource(this); + + this.#init = Promise.all([ + this.consumeContext(UMB_MEDIA_TYPE_TREE_STORE_CONTEXT, (instance) => { + this.#treeStore = instance; + }).asPromise(), + + this.consumeContext(UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => { + this.#notificationContext = instance; + }).asPromise(), + ]); + } + + async createFolderScaffold(parentId: string | null) { + if (parentId === undefined) throw new Error('Parent id is missing'); + await this.#init; + return this.#folderSource.createScaffold(parentId); + } + + // TODO: temp create type until backend is ready. Remove the id addition when new types are generated. + async createFolder(folderRequest: CreateFolderRequestModel) { + if (!folderRequest) throw new Error('folder request is missing'); + await this.#init; + + const { error } = await this.#folderSource.create(folderRequest); + + if (!error) { + // TODO: We need to push a new item to the tree store to update the tree. How do we want to create the tree items? + const folderTreeItem = createFolderTreeItem(folderRequest); + this.#treeStore!.append(folderTreeItem); + } + + return { error }; + } + + async deleteFolder(id: string) { + if (!id) throw new Error('Key is missing'); + await this.#init; + + const { error } = await this.#folderSource.delete(id); + + if (!error) { + this.#treeStore!.removeItem(id); + } + + return { error }; + } + + async updateFolder(id: string, folder: FolderModelBaseModel) { + if (!id) throw new Error('Key is missing'); + if (!folder) throw new Error('Folder data is missing'); + await this.#init; + + const { error } = await this.#folderSource.update(id, folder); + + if (!error) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this.#treeStore!.updateItem(id, { name: folder.name }); + } + + return { error }; + } + + async requestFolder(id: string) { + if (!id) throw new Error('Key is missing'); + await this.#init; + return await this.#folderSource.read(id); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/folder/media-type-folder.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/folder/media-type-folder.server.data.ts new file mode 100644 index 0000000000..ac9e91ec0c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/folder/media-type-folder.server.data.ts @@ -0,0 +1,111 @@ +import { UmbId } from '@umbraco-cms/backoffice/id'; +import { UmbFolderDataSource } from '@umbraco-cms/backoffice/repository'; +import { + MediaTypeResource, + FolderResponseModel, + CreateFolderRequestModel, + FolderModelBaseModel, +} from '@umbraco-cms/backoffice/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; + +/** + * A data source for a Data Type folder that fetches data from the server + * @export + * @class UmbMediaTypeFolderServerDataSource + * @implements {RepositoryDetailDataSource} + */ +export class UmbMediaTypeFolderServerDataSource implements UmbFolderDataSource { + #host: UmbControllerHost; + + /** + * Creates an instance of UmbMediaTypeFolderServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbMediaTypeFolderServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Creates a Data Type folder with the given id from the server + * @param {string} parentId + * @return {*} + * @memberof UmbMediaTypeFolderServerDataSource + */ + async createScaffold(parentId: string | null) { + const scaffold: FolderResponseModel = { + name: '', + id: UmbId.new(), + parentId, + }; + + return { data: scaffold }; + } + + /** + * Fetches a Data Type folder with the given id from the server + * @param {string} id + * @return {*} + * @memberof UmbMediaTypeFolderServerDataSource + */ + async read(id: string) { + if (!id) throw new Error('Key is missing'); + return tryExecuteAndNotify( + this.#host, + MediaTypeResource.getMediaTypeFolderById({ + id: id, + }), + ); + } + + /** + * Inserts a new Data Type folder on the server + * @param {folder} folder + * @return {*} + * @memberof UmbMediaTypeFolderServerDataSource + */ + async create(folder: CreateFolderRequestModel) { + if (!folder) throw new Error('Folder is missing'); + return tryExecuteAndNotify( + this.#host, + MediaTypeResource.postMediaTypeFolder({ + requestBody: folder, + }), + ); + } + + /** + * Updates a Data Type folder on the server + * @param {folder} folder + * @return {*} + * @memberof UmbMediaTypeFolderServerDataSource + */ + async update(id: string, folder: FolderModelBaseModel) { + if (!id) throw new Error('Key is missing'); + if (!id) throw new Error('Folder data is missing'); + return tryExecuteAndNotify( + this.#host, + MediaTypeResource.putMediaTypeFolderById({ + id: id, + requestBody: folder, + }), + ); + } + + /** + * Deletes a Data Type folder with the given id on the server + * @param {string} id + * @return {*} + * @memberof UmbMediaTypeServerDataSource + */ + async delete(id: string) { + if (!id) throw new Error('Key is missing'); + return tryExecuteAndNotify( + this.#host, + MediaTypeResource.deleteMediaTypeFolderById({ + id: id, + }), + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/index.ts index 1f37e6d2ac..bc07bbbbd8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/index.ts @@ -1,2 +1,3 @@ export * from './item/index.js'; export * from './detail/index.js'; +export * from './folder/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/manifests.ts index bb35952020..168cc81b04 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/manifests.ts @@ -1,4 +1,5 @@ import { manifests as detailManifests } from './detail/manifests.js'; import { manifests as itemManifests } from './item/manifests.js'; +import { manifests as folderManifests } from './folder/manifests.js'; -export const manifests = [...detailManifests, ...itemManifests]; +export const manifests = [...detailManifests, ...itemManifests, ...folderManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/utils.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/utils.ts new file mode 100644 index 0000000000..c7eb49bad9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/utils.ts @@ -0,0 +1,17 @@ +import { CreateFolderRequestModel } from '@umbraco-cms/backoffice/backend-api'; + +export const createFolderTreeItem = (item: CreateFolderRequestModel) => { + if (!item) throw new Error('item is null or undefined'); + if (!item.id) throw new Error('item.id is null or undefined'); + + //TODO: change to Unique + return { + id: item.id!, + parentId: item.parentId!, + name: item.name!, + entityType: 'media-type-folder', + isFolder: true, + isContainer: false, + hasChildren: false, + }; +};