Feature/document using content api (#513)
* 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 * new up router slot * set hasChildren to false * fix hos argument + add todo to revisit this code * add todo --------- Co-authored-by: Mads Rasmussen <madsr@hey.com>
This commit is contained in:
@@ -11,8 +11,11 @@ import { html } from 'lit-html';
|
||||
import { initialize, mswDecorator } from 'msw-storybook-addon';
|
||||
import { setCustomElements } from '@storybook/web-components';
|
||||
|
||||
import { UMB_DATA_TYPE_DETAIL_STORE_CONTEXT_TOKEN, UmbDataTypeDetailStore } from '../src/backoffice/settings/data-types/data-type.detail.store';
|
||||
import { UMB_DOCUMENT_TYPE_DETAIL_STORE_CONTEXT_TOKEN, UmbDocumentTypeDetailStore } from '../src/backoffice/documents/document-types/document-type.detail.store';
|
||||
import { UmbDataTypeStore } from '../src/backoffice/settings/data-types/data-type.store';
|
||||
import {
|
||||
UMB_DOCUMENT_TYPE_DETAIL_STORE_CONTEXT_TOKEN,
|
||||
UmbDocumentTypeStore,
|
||||
} from '../src/backoffice/documents/document-types/document-type.detail.store';
|
||||
|
||||
import customElementManifests from '../custom-elements.json';
|
||||
import { UmbIconStore } from '../libs/store/icon/icon.store';
|
||||
@@ -55,12 +58,19 @@ customElements.define('umb-storybook', UmbStoryBookElement);
|
||||
|
||||
const storybookProvider = (story) => html` <umb-storybook>${story()}</umb-storybook> `;
|
||||
|
||||
// TODO: Stop using this context provider element. If we need to continue this path, then we should make a new element which just has a create method that can be used to spin up code. This is because our ContextAPIs provide them self. so no need for a provider element. just a element.
|
||||
const dataTypeStoreProvider = (story) => html`
|
||||
<umb-context-provider key=${UMB_DATA_TYPE_DETAIL_STORE_CONTEXT_TOKEN.toString()} .create=${host => new UmbDataTypeDetailStore(host)}>${story()}</umb-context-provider>
|
||||
<umb-context-provider
|
||||
key=${UMB_DATA_TYPE_STORE_CONTEXT_TOKEN.toString()}
|
||||
.create=${(host) => new UmbDataTypeStore(host)}
|
||||
>${story()}</umb-context-provider
|
||||
>
|
||||
`;
|
||||
|
||||
const documentTypeStoreProvider = (story) => html`
|
||||
<umb-context-provider key=${UMB_DOCUMENT_TYPE_DETAIL_STORE_CONTEXT_TOKEN.toString()} .create=${host => new UmbDocumentTypeDetailStore(host)}
|
||||
<umb-context-provider
|
||||
key=${UMB_DOCUMENT_TYPE_DETAIL_STORE_CONTEXT_TOKEN.toString()}
|
||||
.create=${(host) => new UmbDocumentTypeStore(host)}
|
||||
>${story()}</umb-context-provider
|
||||
>
|
||||
`;
|
||||
|
||||
@@ -12,7 +12,15 @@ export type { AssemblyModel } from './models/AssemblyModel';
|
||||
export { CallingConventionsModel } from './models/CallingConventionsModel';
|
||||
export type { ConsentLevelModel } from './models/ConsentLevelModel';
|
||||
export type { ConstructorInfoModel } from './models/ConstructorInfoModel';
|
||||
export { ContentStateModel } from './models/ContentStateModel';
|
||||
export type { ContentTreeItemModel } from './models/ContentTreeItemModel';
|
||||
export type { ContentTypeCleanupModel } from './models/ContentTypeCleanupModel';
|
||||
export type { ContentTypeCompositionModel } from './models/ContentTypeCompositionModel';
|
||||
export { ContentTypeCompositionTypeModel } from './models/ContentTypeCompositionTypeModel';
|
||||
export type { ContentTypeSortModel } from './models/ContentTypeSortModel';
|
||||
export type { ContentTypeViewModelBaseDocumentTypePropertyTypeDocumentTypePropertyTypeContainerModel } from './models/ContentTypeViewModelBaseDocumentTypePropertyTypeDocumentTypePropertyTypeContainerModel';
|
||||
export type { ContentUrlInfoModel } from './models/ContentUrlInfoModel';
|
||||
export type { ContentViewModelBaseDocumentPropertyDocumentVariantModel } from './models/ContentViewModelBaseDocumentPropertyDocumentVariantModel';
|
||||
export type { CreatedResultModel } from './models/CreatedResultModel';
|
||||
export type { CultureModel } from './models/CultureModel';
|
||||
export type { CustomAttributeDataModel } from './models/CustomAttributeDataModel';
|
||||
@@ -20,9 +28,11 @@ export type { CustomAttributeNamedArgumentModel } from './models/CustomAttribute
|
||||
export type { CustomAttributeTypedArgumentModel } from './models/CustomAttributeTypedArgumentModel';
|
||||
export type { DatabaseInstallModel } from './models/DatabaseInstallModel';
|
||||
export type { DatabaseSettingsModel } from './models/DatabaseSettingsModel';
|
||||
export type { DataTypeCopyModel } from './models/DataTypeCopyModel';
|
||||
export type { DataTypeCreateModel } from './models/DataTypeCreateModel';
|
||||
export type { DataTypeModel } from './models/DataTypeModel';
|
||||
export type { DataTypeModelBaseModel } from './models/DataTypeModelBaseModel';
|
||||
export type { DataTypeMoveModel } from './models/DataTypeMoveModel';
|
||||
export type { DataTypePropertyModel } from './models/DataTypePropertyModel';
|
||||
export type { DataTypePropertyReferenceModel } from './models/DataTypePropertyReferenceModel';
|
||||
export type { DataTypeReferenceModel } from './models/DataTypeReferenceModel';
|
||||
@@ -36,12 +46,19 @@ export type { DictionaryItemModelBaseModel } from './models/DictionaryItemModelB
|
||||
export type { DictionaryItemsImportModel } from './models/DictionaryItemsImportModel';
|
||||
export type { DictionaryItemTranslationModel } from './models/DictionaryItemTranslationModel';
|
||||
export type { DictionaryItemUpdateModel } from './models/DictionaryItemUpdateModel';
|
||||
export type { DictionaryMoveModel } from './models/DictionaryMoveModel';
|
||||
export type { DictionaryOverviewModel } from './models/DictionaryOverviewModel';
|
||||
export type { DictionaryUploadModel } from './models/DictionaryUploadModel';
|
||||
export { DirectionModel } from './models/DirectionModel';
|
||||
export type { DocumentBlueprintTreeItemModel } from './models/DocumentBlueprintTreeItemModel';
|
||||
export type { DocumentModel } from './models/DocumentModel';
|
||||
export type { DocumentPropertyModel } from './models/DocumentPropertyModel';
|
||||
export type { DocumentTreeItemModel } from './models/DocumentTreeItemModel';
|
||||
export type { DocumentTypeModel } from './models/DocumentTypeModel';
|
||||
export type { DocumentTypePropertyTypeContainerModel } from './models/DocumentTypePropertyTypeContainerModel';
|
||||
export type { DocumentTypePropertyTypeModel } from './models/DocumentTypePropertyTypeModel';
|
||||
export type { DocumentTypeTreeItemModel } from './models/DocumentTypeTreeItemModel';
|
||||
export type { DocumentVariantModel } from './models/DocumentVariantModel';
|
||||
export type { EncoderFallbackModel } from './models/EncoderFallbackModel';
|
||||
export type { EncodingModel } from './models/EncodingModel';
|
||||
export type { EntityTreeItemModel } from './models/EntityTreeItemModel';
|
||||
@@ -138,6 +155,11 @@ export type { ProblemDetailsModel } from './models/ProblemDetailsModel';
|
||||
export type { ProfilingStatusModel } from './models/ProfilingStatusModel';
|
||||
export { PropertyAttributesModel } from './models/PropertyAttributesModel';
|
||||
export type { PropertyInfoModel } from './models/PropertyInfoModel';
|
||||
export type { PropertyTypeAppearanceModel } from './models/PropertyTypeAppearanceModel';
|
||||
export type { PropertyTypeContainerViewModelBaseModel } from './models/PropertyTypeContainerViewModelBaseModel';
|
||||
export type { PropertyTypeValidationModel } from './models/PropertyTypeValidationModel';
|
||||
export type { PropertyTypeViewModelBaseModel } from './models/PropertyTypeViewModelBaseModel';
|
||||
export type { PropertyViewModelBaseModel } from './models/PropertyViewModelBaseModel';
|
||||
export type { ReadOnlySpanByteModel } from './models/ReadOnlySpanByteModel';
|
||||
export type { RecycleBinItemModel } from './models/RecycleBinItemModel';
|
||||
export { RedirectStatusModel } from './models/RedirectStatusModel';
|
||||
@@ -182,6 +204,7 @@ export type { UmbracoJsonTypeInfoResolverModel } from './models/UmbracoJsonTypeI
|
||||
export type { UpgradeSettingsModel } from './models/UpgradeSettingsModel';
|
||||
export type { UserInstallModel } from './models/UserInstallModel';
|
||||
export type { UserSettingsModel } from './models/UserSettingsModel';
|
||||
export type { VariantViewModelBaseModel } from './models/VariantViewModelBaseModel';
|
||||
export type { VersionModel } from './models/VersionModel';
|
||||
|
||||
export { CultureResource } from './services/CultureResource';
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export enum ContentStateModel {
|
||||
NOT_CREATED = 'NotCreated',
|
||||
DRAFT = 'Draft',
|
||||
PUBLISHED = 'Published',
|
||||
PUBLISHED_PENDING_CHANGES = 'PublishedPendingChanges',
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export type ContentTypeCleanupModel = {
|
||||
preventCleanup?: boolean;
|
||||
keepAllVersionsNewerThanDays?: number | null;
|
||||
keepLatestVersionPerDayForDays?: number | null;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { ContentTypeCompositionTypeModel } from './ContentTypeCompositionTypeModel';
|
||||
|
||||
export type ContentTypeCompositionModel = {
|
||||
key?: string;
|
||||
compositionType?: ContentTypeCompositionTypeModel;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export enum ContentTypeCompositionTypeModel {
|
||||
COMPOSITION = 'Composition',
|
||||
INHERITANCE = 'Inheritance',
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export type ContentTypeSortModel = {
|
||||
key?: string;
|
||||
sortOrder?: number;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { ContentTypeCleanupModel } from './ContentTypeCleanupModel';
|
||||
import type { ContentTypeCompositionModel } from './ContentTypeCompositionModel';
|
||||
import type { ContentTypeSortModel } from './ContentTypeSortModel';
|
||||
import type { DocumentTypePropertyTypeContainerModel } from './DocumentTypePropertyTypeContainerModel';
|
||||
import type { DocumentTypePropertyTypeModel } from './DocumentTypePropertyTypeModel';
|
||||
|
||||
export type ContentTypeViewModelBaseDocumentTypePropertyTypeDocumentTypePropertyTypeContainerModel = {
|
||||
key?: string;
|
||||
alias?: string;
|
||||
name?: string;
|
||||
description?: string | null;
|
||||
icon?: string;
|
||||
allowedAsRoot?: boolean;
|
||||
variesByCulture?: boolean;
|
||||
variesBySegment?: boolean;
|
||||
isElement?: boolean;
|
||||
properties?: Array<DocumentTypePropertyTypeModel>;
|
||||
containers?: Array<DocumentTypePropertyTypeContainerModel>;
|
||||
allowedContentTypes?: Array<ContentTypeSortModel>;
|
||||
compositions?: Array<ContentTypeCompositionModel>;
|
||||
cleanup?: ContentTypeCleanupModel;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export type ContentUrlInfoModel = {
|
||||
culture?: string | null;
|
||||
url?: string;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { DocumentPropertyModel } from './DocumentPropertyModel';
|
||||
import type { DocumentVariantModel } from './DocumentVariantModel';
|
||||
|
||||
export type ContentViewModelBaseDocumentPropertyDocumentVariantModel = {
|
||||
key?: string;
|
||||
contentTypeKey?: string;
|
||||
properties?: Array<DocumentPropertyModel>;
|
||||
variants?: Array<DocumentVariantModel>;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export type DataTypeCopyModel = {
|
||||
targetKey?: string | null;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export type DataTypeMoveModel = {
|
||||
targetKey?: string | null;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export type DictionaryMoveModel = {
|
||||
targetKey?: string | null;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { ContentUrlInfoModel } from './ContentUrlInfoModel';
|
||||
import type { ContentViewModelBaseDocumentPropertyDocumentVariantModel } from './ContentViewModelBaseDocumentPropertyDocumentVariantModel';
|
||||
|
||||
export type DocumentModel = (ContentViewModelBaseDocumentPropertyDocumentVariantModel & {
|
||||
urls?: Array<ContentUrlInfoModel>;
|
||||
templateKey?: string | null;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { PropertyViewModelBaseModel } from './PropertyViewModelBaseModel';
|
||||
|
||||
export type DocumentPropertyModel = PropertyViewModelBaseModel;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { ContentTypeViewModelBaseDocumentTypePropertyTypeDocumentTypePropertyTypeContainerModel } from './ContentTypeViewModelBaseDocumentTypePropertyTypeDocumentTypePropertyTypeContainerModel';
|
||||
|
||||
export type DocumentTypeModel = (ContentTypeViewModelBaseDocumentTypePropertyTypeDocumentTypePropertyTypeContainerModel & {
|
||||
allowedTemplateKeys?: Array<string>;
|
||||
defaultTemplateKey?: string | null;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { PropertyTypeContainerViewModelBaseModel } from './PropertyTypeContainerViewModelBaseModel';
|
||||
|
||||
export type DocumentTypePropertyTypeContainerModel = PropertyTypeContainerViewModelBaseModel;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { PropertyTypeViewModelBaseModel } from './PropertyTypeViewModelBaseModel';
|
||||
|
||||
export type DocumentTypePropertyTypeModel = PropertyTypeViewModelBaseModel;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { ContentStateModel } from './ContentStateModel';
|
||||
import type { VariantViewModelBaseModel } from './VariantViewModelBaseModel';
|
||||
|
||||
export type DocumentVariantModel = (VariantViewModelBaseModel & {
|
||||
state?: ContentStateModel;
|
||||
publishDate?: string | null;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export type PropertyTypeAppearanceModel = {
|
||||
labelOnTop?: boolean;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export type PropertyTypeContainerViewModelBaseModel = {
|
||||
key?: string;
|
||||
parentKey?: string | null;
|
||||
name?: string | null;
|
||||
type?: string;
|
||||
sortOrder?: number;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export type PropertyTypeValidationModel = {
|
||||
mandatory?: boolean;
|
||||
mandatoryMessage?: string | null;
|
||||
regEx?: string | null;
|
||||
regExMessage?: string | null;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
import type { PropertyTypeAppearanceModel } from './PropertyTypeAppearanceModel';
|
||||
import type { PropertyTypeValidationModel } from './PropertyTypeValidationModel';
|
||||
|
||||
export type PropertyTypeViewModelBaseModel = {
|
||||
key?: string;
|
||||
containerKey?: string | null;
|
||||
alias?: string;
|
||||
name?: string;
|
||||
description?: string | null;
|
||||
dataTypeKey?: string;
|
||||
validation?: PropertyTypeValidationModel;
|
||||
appearance?: PropertyTypeAppearanceModel;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export type PropertyViewModelBaseModel = {
|
||||
culture?: string | null;
|
||||
segment?: string | null;
|
||||
alias?: string;
|
||||
value?: any;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export type VariantViewModelBaseModel = {
|
||||
culture?: string | null;
|
||||
segment?: string | null;
|
||||
name?: string;
|
||||
createDate?: string;
|
||||
updateDate?: string;
|
||||
};
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
import type { DataTypeCopyModel } from '../models/DataTypeCopyModel';
|
||||
import type { DataTypeCreateModel } from '../models/DataTypeCreateModel';
|
||||
import type { DataTypeModel } from '../models/DataTypeModel';
|
||||
import type { DataTypeMoveModel } from '../models/DataTypeMoveModel';
|
||||
import type { DataTypeReferenceModel } from '../models/DataTypeReferenceModel';
|
||||
import type { DataTypeUpdateModel } from '../models/DataTypeUpdateModel';
|
||||
import type { DocumentTypeTreeItemModel } from '../models/DocumentTypeTreeItemModel';
|
||||
@@ -108,6 +110,56 @@ export class DataTypeResource {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns any Created
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static postDataTypeByKeyCopy({
|
||||
key,
|
||||
requestBody,
|
||||
}: {
|
||||
key: string,
|
||||
requestBody?: DataTypeCopyModel,
|
||||
}): CancelablePromise<any> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'POST',
|
||||
url: '/umbraco/management/api/v1/data-type/{key}/copy',
|
||||
path: {
|
||||
'key': key,
|
||||
},
|
||||
body: requestBody,
|
||||
mediaType: 'application/json',
|
||||
errors: {
|
||||
404: `Not Found`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns any Success
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static postDataTypeByKeyMove({
|
||||
key,
|
||||
requestBody,
|
||||
}: {
|
||||
key: string,
|
||||
requestBody?: DataTypeMoveModel,
|
||||
}): CancelablePromise<any> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'POST',
|
||||
url: '/umbraco/management/api/v1/data-type/{key}/move',
|
||||
path: {
|
||||
'key': key,
|
||||
},
|
||||
body: requestBody,
|
||||
mediaType: 'application/json',
|
||||
errors: {
|
||||
404: `Not Found`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns any Success
|
||||
* @throws ApiError
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { DictionaryImportModel } from '../models/DictionaryImportModel';
|
||||
import type { DictionaryItemCreateModel } from '../models/DictionaryItemCreateModel';
|
||||
import type { DictionaryItemModel } from '../models/DictionaryItemModel';
|
||||
import type { DictionaryItemUpdateModel } from '../models/DictionaryItemUpdateModel';
|
||||
import type { DictionaryMoveModel } from '../models/DictionaryMoveModel';
|
||||
import type { DictionaryUploadModel } from '../models/DictionaryUploadModel';
|
||||
import type { DocumentTypeTreeItemModel } from '../models/DocumentTypeTreeItemModel';
|
||||
import type { FolderTreeItemModel } from '../models/FolderTreeItemModel';
|
||||
@@ -155,6 +156,32 @@ export class DictionaryResource {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns any Success
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static postDictionaryByKeyMove({
|
||||
key,
|
||||
requestBody,
|
||||
}: {
|
||||
key: string,
|
||||
requestBody?: DictionaryMoveModel,
|
||||
}): CancelablePromise<any> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'POST',
|
||||
url: '/umbraco/management/api/v1/dictionary/{key}/move',
|
||||
path: {
|
||||
'key': key,
|
||||
},
|
||||
body: requestBody,
|
||||
mediaType: 'application/json',
|
||||
errors: {
|
||||
400: `Bad Request`,
|
||||
404: `Not Found`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns any Created
|
||||
* @throws ApiError
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
import type { DocumentModel } from '../models/DocumentModel';
|
||||
import type { DocumentTreeItemModel } from '../models/DocumentTreeItemModel';
|
||||
import type { PagedDocumentTreeItemModel } from '../models/PagedDocumentTreeItemModel';
|
||||
import type { PagedRecycleBinItemModel } from '../models/PagedRecycleBinItemModel';
|
||||
@@ -11,6 +12,27 @@ import { request as __request } from '../core/request';
|
||||
|
||||
export class DocumentResource {
|
||||
|
||||
/**
|
||||
* @returns any Success
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static getDocumentByKey({
|
||||
key,
|
||||
}: {
|
||||
key: string,
|
||||
}): CancelablePromise<DocumentModel> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'GET',
|
||||
url: '/umbraco/management/api/v1/document/{key}',
|
||||
path: {
|
||||
'key': key,
|
||||
},
|
||||
errors: {
|
||||
404: `Not Found`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns PagedRecycleBinItemModel Success
|
||||
* @throws ApiError
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
import type { DocumentTypeModel } from '../models/DocumentTypeModel';
|
||||
import type { DocumentTypeTreeItemModel } from '../models/DocumentTypeTreeItemModel';
|
||||
import type { PagedDocumentTypeTreeItemModel } from '../models/PagedDocumentTypeTreeItemModel';
|
||||
|
||||
@@ -10,6 +11,27 @@ import { request as __request } from '../core/request';
|
||||
|
||||
export class DocumentTypeResource {
|
||||
|
||||
/**
|
||||
* @returns any Success
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static getDocumentTypeByKey({
|
||||
key,
|
||||
}: {
|
||||
key: string,
|
||||
}): CancelablePromise<DocumentTypeModel> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'GET',
|
||||
url: '/umbraco/management/api/v1/document-type/{key}',
|
||||
path: {
|
||||
'key': key,
|
||||
},
|
||||
errors: {
|
||||
404: `Not Found`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns PagedDocumentTypeTreeItemModel Success
|
||||
* @throws ApiError
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import {
|
||||
ContentTreeItemModel,
|
||||
DocumentTreeItemModel,
|
||||
DocumentTypeTreeItemModel,
|
||||
EntityTreeItemModel,
|
||||
FolderTreeItemModel,
|
||||
PagedEntityTreeItemModel,
|
||||
ProblemDetailsModel,
|
||||
} from '@umbraco-cms/backend-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
|
||||
// Extension Manifests
|
||||
export * from '@umbraco-cms/extensions-registry';
|
||||
@@ -67,25 +62,20 @@ export interface UserGroupDetails extends UserGroupEntity {
|
||||
permissions: Array<string>;
|
||||
}
|
||||
|
||||
/*
|
||||
// Data Types
|
||||
export interface DataTypeDetails extends FolderTreeItemModel {
|
||||
key: string; // TODO: Remove this when the backend is fixed
|
||||
propertyEditorModelAlias: string | null;
|
||||
propertyEditorUIAlias: string | null;
|
||||
data: Array<DataTypePropertyData>;
|
||||
propertyEditorAlias: string | null;
|
||||
propertyEditorUiAlias: string | null;
|
||||
data: Array<DataTypeProperty>;
|
||||
}
|
||||
|
||||
export interface DataTypePropertyData {
|
||||
export interface DataTypeProperty {
|
||||
alias: string;
|
||||
value: any;
|
||||
}
|
||||
|
||||
// Document Types
|
||||
export interface DocumentTypeDetails extends DocumentTypeTreeItemModel {
|
||||
key: string; // TODO: Remove this when the backend is fixed
|
||||
alias: string;
|
||||
properties: [];
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO: Make sure Entity Type/interface.
|
||||
export interface MemberTypeDetails extends EntityTreeItemModel {
|
||||
@@ -107,16 +97,6 @@ export interface ContentPropertyData {
|
||||
value: any;
|
||||
}
|
||||
|
||||
// Documents
|
||||
export interface DocumentDetails extends DocumentTreeItemModel {
|
||||
key: string; // TODO: Remove this when the backend is fixed
|
||||
isTrashed: boolean; // TODO: remove only temp part of refactor
|
||||
properties: Array<ContentProperty>;
|
||||
data: Array<ContentPropertyData>;
|
||||
variants: Array<any>; // TODO: define variant data
|
||||
//layout?: any; // TODO: define layout type - make it non-optional
|
||||
}
|
||||
|
||||
// Media
|
||||
export interface MediaDetails extends ContentTreeItemModel {
|
||||
key: string; // TODO: Remove this when the backend is fixed
|
||||
|
||||
@@ -5,5 +5,6 @@ export * from './string-state';
|
||||
export * from './deep-state';
|
||||
export * from './array-state';
|
||||
export * from './object-state';
|
||||
export * from './create-observable-part.method'
|
||||
export * from './append-to-frozen-array.method'
|
||||
export * from './create-observable-part.method';
|
||||
export * from './append-to-frozen-array.method';
|
||||
export * from './partial-update-frozen-array.method';
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @export
|
||||
* @method partialUpdateFrozenArray
|
||||
* @param {Observable<T>} source - RxJS Subject to use for this Observable.
|
||||
* @param {(mappable: T) => R} mappingFunction - Method to return the part for this Observable to return.
|
||||
* @param {(previousResult: R, currentResult: R) => boolean} [memoizationFunction] - Method to Compare if the data has changed. Should return true when data is different.
|
||||
* @description - Creates a RxJS Observable from RxJS Subject.
|
||||
* @example <caption>Example append new entry for a ArrayState or a part of DeepState/ObjectState it which is an array. Where the key is unique and the item will be updated if matched with existing.</caption>
|
||||
* const partialEntry = {value: 'myValue'};
|
||||
* const newDataSet = partialUpdateFrozenArray(mySubject.getValue(), partialEntry, x => x.key === 'myKey');
|
||||
* mySubject.next(newDataSet);
|
||||
*/
|
||||
export function partialUpdateFrozenArray<T>(
|
||||
data: T[],
|
||||
partialEntry: Partial<T>,
|
||||
findMethod: (entry: T) => boolean
|
||||
): T[] {
|
||||
const unFrozenDataSet = [...data];
|
||||
const indexToReplace = unFrozenDataSet.findIndex((x) => findMethod(x));
|
||||
if (indexToReplace !== -1) {
|
||||
unFrozenDataSet[indexToReplace] = { ...unFrozenDataSet[indexToReplace], ...partialEntry };
|
||||
}
|
||||
return unFrozenDataSet;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ export interface UmbDetailRepository<DetailType> {
|
||||
error?: ProblemDetailsModel;
|
||||
}>;
|
||||
|
||||
requestDetails(key: string): Promise<{
|
||||
requestByKey(key: string): Promise<{
|
||||
data?: DetailType;
|
||||
error?: ProblemDetailsModel;
|
||||
}>;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'router-slot';
|
||||
import { IRoute, RouterSlot } from 'router-slot';
|
||||
import { LitElement, PropertyValueMap } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { IRoute, RouterSlot } from 'router-slot';
|
||||
import { UmbRouterSlotChangeEvent, UmbRouterSlotInitEvent } from '@umbraco-cms/router';
|
||||
|
||||
/**
|
||||
@@ -40,12 +39,11 @@ export class UmbRouterSlotElement extends LitElement {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.#router = document.createElement('router-slot');
|
||||
this.#router = new RouterSlot();
|
||||
// Note: I decided not to use the local changestate event, because it is not fired when the route is changed from any router-slot. And for now I wanted to keep it local.
|
||||
//this.#router.addEventListener('changestate', this._onNavigationChanged);
|
||||
}
|
||||
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
if (this.#listening === false) {
|
||||
@@ -60,7 +58,6 @@ export class UmbRouterSlotElement extends LitElement {
|
||||
this.#listening = false;
|
||||
}
|
||||
|
||||
|
||||
protected firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
|
||||
super.firstUpdated(_changedProperties);
|
||||
this._routerPath = this.#router.constructAbsolutePath('') || '';
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"format": "prettier 'src/**/*.ts'",
|
||||
"format:fix": "npm run format -- --write",
|
||||
"generate:api": "openapi --input https://raw.githubusercontent.com/umbraco/Umbraco-CMS/v13/dev/src/Umbraco.Cms.Api.Management/OpenApi.json --output libs/backend-api/src --postfix Resource --useOptions",
|
||||
"generate:api-dev": "openapi --input http://localhost:9000/umbraco/swagger/v1/swagger.json --output libs/backend-api/src --postfix Resource --useOptions",
|
||||
"generate:api-dev": "openapi --input http://localhost:11000/umbraco/swagger/v1/swagger.json --output libs/backend-api/src --postfix Resource --useOptions",
|
||||
"storybook": "npm run wc-analyze && start-storybook -p 6006",
|
||||
"storybook:build": "npm run wc-analyze && build-storybook",
|
||||
"build-storybook": "npm run wc-analyze && build-storybook",
|
||||
|
||||
@@ -15,11 +15,11 @@ import {
|
||||
UmbBackofficeContext,
|
||||
UMB_BACKOFFICE_CONTEXT_TOKEN,
|
||||
} from './shared/components/backoffice-frame/backoffice.context';
|
||||
import { UmbDocumentTypeDetailStore } from './documents/document-types/document-type.detail.store';
|
||||
import { UmbDocumentTypeTreeStore } from './documents/document-types/document-type.tree.store';
|
||||
import { UmbDocumentTypeStore } from './documents/document-types/repository/document-type.store';
|
||||
import { UmbDocumentTypeTreeStore } from './documents/document-types/repository/document-type.tree.store';
|
||||
import { UmbMediaTypeDetailStore } from './media/media-types/media-type.detail.store';
|
||||
import { UmbMediaTypeTreeStore } from './media/media-types/media-type.tree.store';
|
||||
import { UmbDocumentDetailStore } from './documents/documents/repository/document.detail.store';
|
||||
import { UmbDocumentStore } from './documents/documents/repository/document.store';
|
||||
import { UmbDocumentTreeStore } from './documents/documents/repository/document.tree.store';
|
||||
import { UmbMediaDetailStore } from './media/media/repository/media.detail.store';
|
||||
import { UmbMediaTreeStore } from './media/media/repository/media.tree.store';
|
||||
@@ -33,7 +33,7 @@ import { UmbDictionaryDetailStore } from './translation/dictionary/dictionary.de
|
||||
import { UmbDictionaryTreeStore } from './translation/dictionary/dictionary.tree.store';
|
||||
import { UmbDocumentBlueprintDetailStore } from './documents/document-blueprints/document-blueprint.detail.store';
|
||||
import { UmbDocumentBlueprintTreeStore } from './documents/document-blueprints/document-blueprint.tree.store';
|
||||
import { UmbDataTypeDetailStore } from './settings/data-types/data-type.detail.store';
|
||||
import { UmbDataTypeStore } from './settings/data-types/repository/data-type.store';
|
||||
import { UmbDataTypeTreeStore } from './settings/data-types/tree/data-type.tree.store';
|
||||
import { UmbTemplateTreeStore } from './templating/templates/tree/data/template.tree.store';
|
||||
import { UmbTemplateDetailStore } from './templating/templates/workspace/data/template.detail.store';
|
||||
@@ -82,16 +82,16 @@ export class UmbBackofficeElement extends UmbLitElement {
|
||||
// TODO: find a way this is possible outside this element. It needs to be possible to register stores in extensions
|
||||
this.provideContext(UMB_CURRENT_USER_STORE_CONTEXT_TOKEN, new UmbCurrentUserStore());
|
||||
|
||||
new UmbDocumentDetailStore(this);
|
||||
new UmbDocumentStore(this);
|
||||
new UmbDocumentTreeStore(this);
|
||||
new UmbMediaDetailStore(this);
|
||||
new UmbMediaTreeStore(this);
|
||||
new UmbDataTypeDetailStore(this);
|
||||
new UmbDataTypeStore(this);
|
||||
new UmbDataTypeTreeStore(this);
|
||||
new UmbUserStore(this);
|
||||
new UmbMediaTypeDetailStore(this);
|
||||
new UmbMediaTypeTreeStore(this);
|
||||
new UmbDocumentTypeDetailStore(this);
|
||||
new UmbDocumentTypeStore(this);
|
||||
new UmbDocumentTypeTreeStore(this);
|
||||
new UmbMemberTypeDetailStore(this);
|
||||
new UmbMemberTypeTreeStore(this);
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import type { DocumentTypeDetails } from '@umbraco-cms/models';
|
||||
import { UmbContextToken } from '@umbraco-cms/context-api';
|
||||
import { ArrayState } from '@umbraco-cms/observable-api';
|
||||
import { UmbEntityDetailStore, UmbStoreBase } from '@umbraco-cms/store';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
|
||||
export const UMB_DOCUMENT_TYPE_DETAIL_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbDocumentTypeDetailStore>(
|
||||
'UmbDocumentTypeDetailStore'
|
||||
);
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @class UmbDocumentTypeDetailStore
|
||||
* @extends {UmbStoreBase}
|
||||
* @description - Details Data Store for Document Types
|
||||
*/
|
||||
export class UmbDocumentTypeDetailStore extends UmbStoreBase implements UmbEntityDetailStore<DocumentTypeDetails> {
|
||||
#data = new ArrayState<DocumentTypeDetails>([], (x) => x.key);
|
||||
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
super(host, UMB_DOCUMENT_TYPE_DETAIL_STORE_CONTEXT_TOKEN.toString());
|
||||
}
|
||||
|
||||
getScaffold(entityType: string, parentKey: string | null) {
|
||||
return {
|
||||
key: '',
|
||||
name: '',
|
||||
icon: '',
|
||||
type: '',
|
||||
hasChildren: false,
|
||||
parentKey: '',
|
||||
alias: '',
|
||||
properties: [],
|
||||
} as DocumentTypeDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description - Request a Data Type by key. The Data Type is added to the store and is returned as an Observable.
|
||||
* @param {string} key
|
||||
* @return {*} {(Observable<DocumentTypeDetails | undefined>)}
|
||||
* @memberof UmbDocumentTypesStore
|
||||
*/
|
||||
getByKey(key: string) {
|
||||
// TODO: use backend cli when available.
|
||||
fetch(`/umbraco/management/api/v1/document-type/details/${key}`)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
this.#data.append(data);
|
||||
});
|
||||
|
||||
return this.#data.getObservablePart((documentTypes) =>
|
||||
documentTypes.find((documentType) => documentType.key === key)
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: make sure UI somehow can follow the status of this action.
|
||||
/**
|
||||
* @description - Save a Data Type.
|
||||
* @param {Array<DocumentTypeDetails>} documentTypes
|
||||
* @memberof UmbDocumentTypesStore
|
||||
* @return {*} {Promise<void>}
|
||||
*/
|
||||
save(data: DocumentTypeDetails[]) {
|
||||
// fetch from server and update store
|
||||
// TODO: use Fetcher API.
|
||||
let body: string;
|
||||
|
||||
try {
|
||||
body = JSON.stringify(data);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
// TODO: use backend cli when available.
|
||||
return fetch('/umbraco/management/api/v1/document-type/save', {
|
||||
method: 'POST',
|
||||
body: body,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((data: Array<DocumentTypeDetails>) => {
|
||||
this.#data.append(data);
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: How can we avoid having this in both stores?
|
||||
/**
|
||||
* @description - Delete a Data Type.
|
||||
* @param {string[]} keys
|
||||
* @memberof UmbDocumentTypesStore
|
||||
* @return {*} {Promise<void>}
|
||||
*/
|
||||
async delete(keys: string[]) {
|
||||
// TODO: use backend cli when available.
|
||||
await fetch('/umbraco/backoffice/document-type/delete', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(keys),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
this.#data.remove(keys);
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
import { DocumentTypeResource, DocumentTreeItemModel } from '@umbraco-cms/backend-api';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
|
||||
import { UmbContextToken } from '@umbraco-cms/context-api';
|
||||
import { ArrayState } from '@umbraco-cms/observable-api';
|
||||
import { UmbStoreBase } from '@umbraco-cms/store';
|
||||
import type { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
|
||||
export const UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbDocumentTypeTreeStore>(
|
||||
'UmbDocumentTypeTreeStore'
|
||||
);
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @class UmbDocumentTypeTreeStore
|
||||
* @extends {UmbStoreBase}
|
||||
* @description - Tree Data Store for Data Types
|
||||
*/
|
||||
export class UmbDocumentTypeTreeStore extends UmbStoreBase {
|
||||
#data = new ArrayState<DocumentTreeItemModel>([], (x) => x.key);
|
||||
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
super(host, UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN.toString());
|
||||
}
|
||||
|
||||
// TODO: How can we avoid having this in both stores?
|
||||
/**
|
||||
* @description - Delete a Data Type.
|
||||
* @param {string[]} keys
|
||||
* @memberof UmbDocumentTypesStore
|
||||
* @return {*} {Promise<void>}
|
||||
*/
|
||||
async delete(keys: string[]) {
|
||||
// TODO: use backend cli when available.
|
||||
await fetch('/umbraco/backoffice/document-type/delete', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(keys),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
this.#data.remove(keys);
|
||||
}
|
||||
|
||||
getTreeRoot() {
|
||||
tryExecuteAndNotify(this._host, DocumentTypeResource.getTreeDocumentTypeRoot({})).then(({ data }) => {
|
||||
if (data) {
|
||||
// TODO: how do we handle if an item has been removed during this session(like in another tab or by another user)?
|
||||
this.#data.append(data.items);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: remove ignore when we know how to handle trashed items.
|
||||
return this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === null));
|
||||
}
|
||||
|
||||
getTreeItemChildren(key: string) {
|
||||
tryExecuteAndNotify(
|
||||
this._host,
|
||||
DocumentTypeResource.getTreeDocumentTypeChildren({
|
||||
parentKey: key,
|
||||
})
|
||||
).then(({ data }) => {
|
||||
if (data) {
|
||||
// TODO: how do we handle if an item has been removed during this session(like in another tab or by another user)?
|
||||
this.#data.append(data.items);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: remove ignore when we know how to handle trashed items.
|
||||
return this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === key));
|
||||
}
|
||||
|
||||
getTreeItems(keys: Array<string>) {
|
||||
if (keys?.length > 0) {
|
||||
tryExecuteAndNotify(
|
||||
this._host,
|
||||
DocumentTypeResource.getTreeDocumentTypeItem({
|
||||
key: keys,
|
||||
})
|
||||
).then(({ data }) => {
|
||||
if (data) {
|
||||
// TODO: how do we handle if an item has been removed during this session(like in another tab or by another user)?
|
||||
this.#data.append(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return this.#data.getObservablePart((items) => items.filter((item) => keys.includes(item.key ?? '')));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
import type { RepositoryTreeDataSource } from '../../../../../libs/repository/repository-tree-data-source.interface';
|
||||
import { DocumentTypeTreeServerDataSource } from './sources/document-type.tree.server.data';
|
||||
import { UmbDocumentTypeServerDataSource } from './sources/document-type.server.data';
|
||||
import { UmbDocumentTypeTreeStore, UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN } from './document-type.tree.store';
|
||||
import { UmbDocumentTypeStore, UMB_DOCUMENT_TYPE_STORE_CONTEXT_TOKEN } from './document-type.store';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
import { UmbContextConsumerController } from '@umbraco-cms/context-api';
|
||||
import { ProblemDetailsModel, DocumentTypeModel } from '@umbraco-cms/backend-api';
|
||||
import type { UmbTreeRepository } from 'libs/repository/tree-repository.interface';
|
||||
import { UmbDetailRepository } from '@umbraco-cms/repository';
|
||||
import { UmbNotificationService, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN } from '@umbraco-cms/notification';
|
||||
|
||||
type ItemType = DocumentTypeModel;
|
||||
|
||||
// Move to documentation / JSdoc
|
||||
/* We need to create a new instance of the repository from within the element context. We want the notifications to be displayed in the right context. */
|
||||
// element -> context -> repository -> (store) -> data source
|
||||
// All methods should be async and return a promise. Some methods might return an observable as part of the promise response.
|
||||
export class UmbDocumentTypeRepository implements UmbTreeRepository, UmbDetailRepository<ItemType> {
|
||||
#init!: Promise<unknown>;
|
||||
|
||||
#host: UmbControllerHostInterface;
|
||||
|
||||
#treeSource: RepositoryTreeDataSource;
|
||||
#treeStore?: UmbDocumentTypeTreeStore;
|
||||
|
||||
#detailDataSource: UmbDocumentTypeServerDataSource;
|
||||
#detailStore?: UmbDocumentTypeStore;
|
||||
|
||||
#notificationService?: UmbNotificationService;
|
||||
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
this.#host = host;
|
||||
|
||||
// TODO: figure out how spin up get the correct data source
|
||||
this.#treeSource = new DocumentTypeTreeServerDataSource(this.#host);
|
||||
this.#detailDataSource = new UmbDocumentTypeServerDataSource(this.#host);
|
||||
|
||||
this.#init = Promise.all([
|
||||
new UmbContextConsumerController(this.#host, UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT_TOKEN, (instance) => {
|
||||
this.#treeStore = instance;
|
||||
}),
|
||||
|
||||
new UmbContextConsumerController(this.#host, UMB_DOCUMENT_TYPE_STORE_CONTEXT_TOKEN, (instance) => {
|
||||
this.#detailStore = instance;
|
||||
}),
|
||||
|
||||
new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN, (instance) => {
|
||||
this.#notificationService = instance;
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
// TODO: Trash
|
||||
// TODO: Move
|
||||
|
||||
async requestRootTreeItems() {
|
||||
await this.#init;
|
||||
|
||||
const { data, error } = await this.#treeSource.getRootItems();
|
||||
|
||||
if (data) {
|
||||
this.#treeStore?.appendItems(data.items);
|
||||
}
|
||||
|
||||
return { data, error, asObservable: () => this.#treeStore!.rootItems };
|
||||
}
|
||||
|
||||
async requestTreeItemsOf(parentKey: string | null) {
|
||||
await this.#init;
|
||||
|
||||
if (!parentKey) {
|
||||
const error: ProblemDetailsModel = { title: 'Parent key is missing' };
|
||||
return { data: undefined, error };
|
||||
}
|
||||
|
||||
const { data, error } = await this.#treeSource.getChildrenOf(parentKey);
|
||||
|
||||
if (data) {
|
||||
this.#treeStore?.appendItems(data.items);
|
||||
}
|
||||
|
||||
return { data, error, asObservable: () => this.#treeStore!.childrenOf(parentKey) };
|
||||
}
|
||||
|
||||
async requestTreeItems(keys: Array<string>) {
|
||||
await this.#init;
|
||||
|
||||
if (!keys) {
|
||||
const error: ProblemDetailsModel = { title: 'Keys are missing' };
|
||||
return { data: undefined, error };
|
||||
}
|
||||
|
||||
const { data, error } = await this.#treeSource.getItems(keys);
|
||||
|
||||
return { data, error, asObservable: () => this.#treeStore!.items(keys) };
|
||||
}
|
||||
|
||||
async rootTreeItems() {
|
||||
await this.#init;
|
||||
return this.#treeStore!.rootItems;
|
||||
}
|
||||
|
||||
async treeItemsOf(parentKey: string | null) {
|
||||
await this.#init;
|
||||
return this.#treeStore!.childrenOf(parentKey);
|
||||
}
|
||||
|
||||
async treeItems(keys: Array<string>) {
|
||||
await this.#init;
|
||||
return this.#treeStore!.items(keys);
|
||||
}
|
||||
|
||||
// DETAILS:
|
||||
|
||||
async createDetailsScaffold(parentKey: string | null) {
|
||||
await this.#init;
|
||||
|
||||
if (!parentKey) {
|
||||
throw new Error('Parent key is missing');
|
||||
}
|
||||
|
||||
return this.#detailDataSource.createScaffold(parentKey);
|
||||
}
|
||||
|
||||
async requestByKey(key: string) {
|
||||
await this.#init;
|
||||
|
||||
// TODO: should we show a notification if the key is missing?
|
||||
// Investigate what is best for Acceptance testing, cause in that perspective a thrown error might be the best choice?
|
||||
if (!key) {
|
||||
const error: ProblemDetailsModel = { title: 'Key is missing' };
|
||||
return { error };
|
||||
}
|
||||
const { data, error } = await this.#detailDataSource.get(key);
|
||||
|
||||
if (data) {
|
||||
this.#detailStore?.append(data);
|
||||
}
|
||||
|
||||
return { data, error };
|
||||
}
|
||||
|
||||
async byKey(key: string) {
|
||||
await this.#init;
|
||||
return this.#detailStore!.byKey(key);
|
||||
}
|
||||
|
||||
// Could potentially be general methods:
|
||||
|
||||
async createDetail(template: ItemType) {
|
||||
await this.#init;
|
||||
|
||||
if (!template || !template.key) {
|
||||
throw new Error('Template is missing');
|
||||
}
|
||||
|
||||
const { error } = await this.#detailDataSource.insert(template);
|
||||
|
||||
if (!error) {
|
||||
const notification = { data: { message: `Document created` } };
|
||||
this.#notificationService?.peek('positive', notification);
|
||||
}
|
||||
|
||||
// TODO: we currently don't use the detail store for anything.
|
||||
// Consider to look up the data before fetching from the server
|
||||
this.#detailStore?.append(template);
|
||||
// TODO: Update tree store with the new item? or ask tree to request the new item?
|
||||
|
||||
return { error };
|
||||
}
|
||||
|
||||
async saveDetail(item: ItemType) {
|
||||
await this.#init;
|
||||
|
||||
if (!item || !item.key) {
|
||||
throw new Error('Document-Type is missing');
|
||||
}
|
||||
|
||||
const { error } = await this.#detailDataSource.update(item);
|
||||
|
||||
if (!error) {
|
||||
const notification = { data: { message: `Document saved` } };
|
||||
this.#notificationService?.peek('positive', notification);
|
||||
}
|
||||
|
||||
// TODO: we currently don't use the detail store for anything.
|
||||
// Consider to look up the data before fetching from the server
|
||||
// Consider notify a workspace if a template is updated in the store while someone is editing it.
|
||||
this.#detailStore?.append(item);
|
||||
this.#treeStore?.updateItem(item.key, { name: item.name });
|
||||
// TODO: would be nice to align the stores on methods/methodNames.
|
||||
|
||||
return { error };
|
||||
}
|
||||
|
||||
// General:
|
||||
|
||||
async delete(key: string) {
|
||||
await this.#init;
|
||||
|
||||
if (!key) {
|
||||
throw new Error('Document key is missing');
|
||||
}
|
||||
|
||||
const { error } = await this.#detailDataSource.delete(key);
|
||||
|
||||
if (!error) {
|
||||
const notification = { data: { message: `Document deleted` } };
|
||||
this.#notificationService?.peek('positive', notification);
|
||||
}
|
||||
|
||||
// TODO: we currently don't use the detail store for anything.
|
||||
// Consider to look up the data before fetching from the server.
|
||||
// Consider notify a workspace if a template is deleted from the store while someone is editing it.
|
||||
this.#detailStore?.remove([key]);
|
||||
this.#treeStore?.removeItem(key);
|
||||
// TODO: would be nice to align the stores on methods/methodNames.
|
||||
|
||||
return { error };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { DocumentTypeModel } 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';
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @class UmbDocumentTypeStore
|
||||
* @extends {UmbStoreBase}
|
||||
* @description - Data Store for Document Types
|
||||
*/
|
||||
export class UmbDocumentTypeStore extends UmbStoreBase {
|
||||
#data = new ArrayState<DocumentTypeModel>([], (x) => x.key);
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbDocumentTypeStore.
|
||||
* @param {UmbControllerHostInterface} host
|
||||
* @memberof UmbDocumentTypeStore
|
||||
*/
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
super(host, UmbDocumentTypeStore.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a document-type to the store
|
||||
* @param {DocumentTypeModel} document
|
||||
* @memberof UmbDocumentTypeStore
|
||||
*/
|
||||
append(document: DocumentTypeModel) {
|
||||
this.#data.append([document]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a document-type to the store
|
||||
* @param {DocumentTypeModel} document
|
||||
* @memberof UmbDocumentTypeStore
|
||||
*/
|
||||
byKey(key: DocumentTypeModel['key']) {
|
||||
return this.#data.getObservablePart((x) => x.find((y) => y.key === key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes document-types in the store with the given uniques
|
||||
* @param {string[]} uniques
|
||||
* @memberof UmbDocumentTypeStore
|
||||
*/
|
||||
remove(uniques: Array<DocumentTypeModel['key']>) {
|
||||
this.#data.remove(uniques);
|
||||
}
|
||||
}
|
||||
|
||||
export const UMB_DOCUMENT_TYPE_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbDocumentTypeStore>(
|
||||
UmbDocumentTypeStore.name
|
||||
);
|
||||
@@ -0,0 +1,93 @@
|
||||
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';
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @class UmbDocumentTypeTreeStore
|
||||
* @extends {UmbStoreBase}
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbDocumentTypeTreeStore.
|
||||
* @param {UmbControllerHostInterface} host
|
||||
* @memberof UmbDocumentTypeTreeStore
|
||||
*/
|
||||
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>(
|
||||
UmbDocumentTypeTreeStore.name
|
||||
);
|
||||
@@ -0,0 +1,13 @@
|
||||
import { UmbDocumentTypeRepository } from './document-type.repository';
|
||||
import { ManifestRepository } from 'libs/extensions-registry/repository.models';
|
||||
|
||||
export const DOCUMENT_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DocumentTypes';
|
||||
|
||||
const repository: ManifestRepository = {
|
||||
type: 'repository',
|
||||
alias: DOCUMENT_TYPE_REPOSITORY_ALIAS,
|
||||
name: 'Document Types Repository',
|
||||
class: UmbDocumentTypeRepository,
|
||||
};
|
||||
|
||||
export const manifests = [repository];
|
||||
@@ -0,0 +1,179 @@
|
||||
import { RepositoryDetailDataSource } from '@umbraco-cms/repository';
|
||||
import { DocumentTypeResource, ProblemDetailsModel, DocumentTypeModel } from '@umbraco-cms/backend-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
|
||||
|
||||
/**
|
||||
* A data source for the Document Type that fetches data from the server
|
||||
* @export
|
||||
* @class UmbDocumentTypeServerDataSource
|
||||
* @implements {RepositoryDetailDataSource}
|
||||
*/
|
||||
export class UmbDocumentTypeServerDataSource implements RepositoryDetailDataSource<DocumentTypeModel> {
|
||||
#host: UmbControllerHostInterface;
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbDocumentServerDataSource.
|
||||
* @param {UmbControllerHostInterface} host
|
||||
* @memberof UmbDocumentServerDataSource
|
||||
*/
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
this.#host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a Document with the given key from the server
|
||||
* @param {string} key
|
||||
* @return {*}
|
||||
* @memberof UmbDocumentTypeServerDataSource
|
||||
*/
|
||||
async get(key: string) {
|
||||
if (!key) {
|
||||
const error: ProblemDetailsModel = { title: 'Key is missing' };
|
||||
return { error };
|
||||
}
|
||||
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
DocumentTypeResource.getDocumentTypeByKey({
|
||||
key,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Document scaffold
|
||||
* @param {(string | null)} parentKey
|
||||
* @return {*}
|
||||
* @memberof UmbDocumentTypeServerDataSource
|
||||
*/
|
||||
async createScaffold(parentKey: string | null) {
|
||||
const data: DocumentTypeModel = {
|
||||
properties: [],
|
||||
};
|
||||
|
||||
return { data };
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new Document on the server
|
||||
* @param {Document} document
|
||||
* @return {*}
|
||||
* @memberof UmbDocumentTypeServerDataSource
|
||||
*/
|
||||
async insert(document: DocumentTypeModel) {
|
||||
if (!document.key) {
|
||||
//const error: ProblemDetails = { title: 'Document key is missing' };
|
||||
return Promise.reject();
|
||||
}
|
||||
//const payload = { key: document.key, requestBody: document };
|
||||
|
||||
let body: string;
|
||||
|
||||
try {
|
||||
body = JSON.stringify(document);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return Promise.reject();
|
||||
}
|
||||
//return tryExecuteAndNotify(this.#host, DocumentTypeResource.postDocument(payload));
|
||||
// TODO: use resources when end point is ready:
|
||||
return tryExecuteAndNotify<DocumentTypeModel>(
|
||||
this.#host,
|
||||
fetch('/umbraco/management/api/v1/document/save', {
|
||||
method: 'POST',
|
||||
body: body,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}) as any
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a Document on the server
|
||||
* @param {Document} Document
|
||||
* @return {*}
|
||||
* @memberof UmbDocumentTypeServerDataSource
|
||||
*/
|
||||
// TODO: Error mistake in this:
|
||||
async update(document: DocumentTypeModel) {
|
||||
if (!document.key) {
|
||||
const error: ProblemDetailsModel = { title: 'Document key is missing' };
|
||||
return { error };
|
||||
}
|
||||
//const payload = { key: document.key, requestBody: document };
|
||||
|
||||
let body: string;
|
||||
|
||||
try {
|
||||
body = JSON.stringify(document);
|
||||
} catch (error) {
|
||||
const myError: ProblemDetailsModel = { title: 'JSON could not parse' };
|
||||
return { error: myError };
|
||||
}
|
||||
|
||||
// TODO: use resources when end point is ready:
|
||||
return tryExecuteAndNotify<DocumentTypeModel>(
|
||||
this.#host,
|
||||
fetch('/umbraco/management/api/v1/document-type/save', {
|
||||
method: 'POST',
|
||||
body: body,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}) as any
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trash a Document on the server
|
||||
* @param {Document} Document
|
||||
* @return {*}
|
||||
* @memberof UmbDocumentTypeServerDataSource
|
||||
*/
|
||||
async trash(key: string) {
|
||||
if (!key) {
|
||||
const error: ProblemDetailsModel = { title: 'Key is missing' };
|
||||
return { error };
|
||||
}
|
||||
|
||||
// TODO: use resources when end point is ready:
|
||||
return tryExecuteAndNotify<DocumentTypeModel>(
|
||||
this.#host,
|
||||
fetch('/umbraco/management/api/v1/document-type/trash', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify([key]),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}) as any
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a Template on the server
|
||||
* @param {string} key
|
||||
* @return {*}
|
||||
* @memberof UmbDocumentTypeServerDataSource
|
||||
*/
|
||||
// TODO: Error mistake in this:
|
||||
async delete(key: string) {
|
||||
if (!key) {
|
||||
const error: ProblemDetailsModel = { title: 'Key is missing' };
|
||||
return { error };
|
||||
}
|
||||
|
||||
// TODO: use resources when end point is ready:
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
fetch('/umbraco/management/api/v1/document-type/trash', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify([key]),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import type { RepositoryTreeDataSource } from '../../../../../../libs/repository/repository-tree-data-source.interface';
|
||||
import { ProblemDetailsModel, DocumentTypeResource } from '@umbraco-cms/backend-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
|
||||
|
||||
/**
|
||||
* A data source for the Document tree that fetches data from the server
|
||||
* @export
|
||||
* @class DocumentTreeServerDataSource
|
||||
* @implements {DocumentTreeDataSource}
|
||||
*/
|
||||
export class DocumentTypeTreeServerDataSource implements RepositoryTreeDataSource {
|
||||
#host: UmbControllerHostInterface;
|
||||
|
||||
// TODO: how do we handle trashed items?
|
||||
async trashItems(keys: Array<string>) {
|
||||
// TODO: use backend cli when available.
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
fetch('/umbraco/management/api/v1/document-type/trash', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(keys),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
async moveItems(keys: Array<string>, destination: string) {
|
||||
// TODO: use backend cli when available.
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
fetch('/umbraco/management/api/v1/document-type/move', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ keys, destination }),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of DocumentTreeServerDataSource.
|
||||
* @param {UmbControllerHostInterface} host
|
||||
* @memberof DocumentTreeServerDataSource
|
||||
*/
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
this.#host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the root items for the tree from the server
|
||||
* @return {*}
|
||||
* @memberof DocumentTreeServerDataSource
|
||||
*/
|
||||
async getRootItems() {
|
||||
return tryExecuteAndNotify(this.#host, DocumentTypeResource.getTreeDocumentTypeRoot({}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the children of a given parent key from the server
|
||||
* @param {(string | null)} parentKey
|
||||
* @return {*}
|
||||
* @memberof DocumentTreeServerDataSource
|
||||
*/
|
||||
async getChildrenOf(parentKey: string | null) {
|
||||
if (!parentKey) {
|
||||
const error: ProblemDetailsModel = { title: 'Parent key is missing' };
|
||||
return { error };
|
||||
}
|
||||
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
DocumentTypeResource.getTreeDocumentTypeChildren({
|
||||
parentKey,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the items for the given keys from the server
|
||||
* @param {Array<string>} keys
|
||||
* @return {*}
|
||||
* @memberof DocumentTreeServerDataSource
|
||||
*/
|
||||
async getItems(keys: Array<string>) {
|
||||
if (keys) {
|
||||
const error: ProblemDetailsModel = { title: 'Keys are missing' };
|
||||
return { error };
|
||||
}
|
||||
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
DocumentTypeResource.getTreeDocumentTypeItem({
|
||||
key: keys,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { UMB_DOCUMENT_TYPE_DETAIL_STORE_CONTEXT_TOKEN } from '../document-type.detail.store';
|
||||
import { UMB_DOCUMENT_TYPE_STORE_CONTEXT_TOKEN } from '../repository/document-type.store';
|
||||
import type { ManifestTree, ManifestTreeItemAction } from '@umbraco-cms/models';
|
||||
|
||||
const tree: ManifestTree = {
|
||||
@@ -6,7 +6,7 @@ const tree: ManifestTree = {
|
||||
alias: 'Umb.Tree.DocumentTypes',
|
||||
name: 'Document Types Tree',
|
||||
meta: {
|
||||
storeAlias: UMB_DOCUMENT_TYPE_DETAIL_STORE_CONTEXT_TOKEN.toString(),
|
||||
storeAlias: UMB_DOCUMENT_TYPE_STORE_CONTEXT_TOKEN.toString(),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
import { UmbEntityWorkspaceManager } from '../../../shared/components/workspace/workspace-context/entity-manager-controller';
|
||||
import { UmbWorkspaceContext } from '../../../shared/components/workspace/workspace-context/workspace-context';
|
||||
import { UmbWorkspaceEntityContextInterface } from '../../../shared/components/workspace/workspace-context/workspace-entity-context.interface';
|
||||
import { UMB_DOCUMENT_TYPE_DETAIL_STORE_CONTEXT_TOKEN } from '../document-type.detail.store';
|
||||
import type { DocumentTypeDetails } from '@umbraco-cms/models';
|
||||
import { UMB_DOCUMENT_TYPE_STORE_CONTEXT_TOKEN } from '../repository/document-type.store';
|
||||
import type { DocumentTypeModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
export class UmbWorkspaceDocumentTypeContext extends UmbWorkspaceContext implements UmbWorkspaceEntityContextInterface<DocumentTypeDetails | undefined> {
|
||||
|
||||
#manager = new UmbEntityWorkspaceManager(this._host, 'document-type', UMB_DOCUMENT_TYPE_DETAIL_STORE_CONTEXT_TOKEN);
|
||||
export class UmbWorkspaceDocumentTypeContext
|
||||
extends UmbWorkspaceContext
|
||||
implements UmbWorkspaceEntityContextInterface<DocumentTypeModel | undefined>
|
||||
{
|
||||
#manager = new UmbEntityWorkspaceManager(this._host, 'document-type', UMB_DOCUMENT_TYPE_STORE_CONTEXT_TOKEN);
|
||||
|
||||
public readonly data = this.#manager.state.asObservable();
|
||||
public readonly name = this.#manager.state.getObservablePart((state) => state?.name);
|
||||
|
||||
|
||||
setName(name: string) {
|
||||
this.#manager.state.update({name: name})
|
||||
this.#manager.state.update({ name: name });
|
||||
}
|
||||
setIcon(icon: string) {
|
||||
this.#manager.state.update({icon: icon})
|
||||
this.#manager.state.update({ icon: icon });
|
||||
}
|
||||
getEntityType = this.#manager.getEntityType;
|
||||
getUnique = this.#manager.getEntityKey;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { UUIInputElement, UUIInputEvent } from '@umbraco-ui/uui';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { css, html } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { distinctUntilChanged } from 'rxjs';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import type { UmbWorkspaceEntityElement } from '../../../shared/components/workspace/workspace-entity-element.interface';
|
||||
import { UmbWorkspaceDocumentTypeContext } from './document-type-workspace.context';
|
||||
import type { DocumentTypeDetails } from '@umbraco-cms/models';
|
||||
import { UmbModalService, UMB_MODAL_SERVICE_CONTEXT_TOKEN } from 'src/core/modal';
|
||||
import type { DocumentTypeModel } from '@umbraco-cms/backend-api';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import type { UmbWorkspaceEntityElement } from 'src/backoffice/shared/components/workspace/workspace-entity-element.interface';
|
||||
import { UmbModalService, UMB_MODAL_SERVICE_CONTEXT_TOKEN } from '@umbraco-cms/modal';
|
||||
|
||||
@customElement('umb-document-type-workspace')
|
||||
export class UmbDocumentTypeWorkspaceElement extends UmbLitElement implements UmbWorkspaceEntityElement {
|
||||
@@ -46,11 +45,10 @@ export class UmbDocumentTypeWorkspaceElement extends UmbLitElement implements Um
|
||||
name: 'umb:document-dashed-line',
|
||||
};
|
||||
|
||||
|
||||
private _workspaceContext: UmbWorkspaceDocumentTypeContext = new UmbWorkspaceDocumentTypeContext(this);
|
||||
|
||||
@state()
|
||||
private _documentType?: DocumentTypeDetails;
|
||||
private _documentType?: DocumentTypeModel;
|
||||
|
||||
private _modalService?: UmbModalService;
|
||||
|
||||
@@ -61,9 +59,9 @@ export class UmbDocumentTypeWorkspaceElement extends UmbLitElement implements Um
|
||||
this._modalService = instance;
|
||||
});
|
||||
|
||||
this.observe(this._workspaceContext.data.pipe(distinctUntilChanged()), (data) => {
|
||||
// TODO: make method to identify if data is of type DocumentTypeDetails
|
||||
this._documentType = data as DocumentTypeDetails;
|
||||
this.observe(this._workspaceContext.data, (data) => {
|
||||
// TODO: make method to identify if data is of type DocumentType
|
||||
this._documentType = data as DocumentType;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import './document-type-workspace.element';
|
||||
import { Meta, Story } from '@storybook/web-components';
|
||||
import { html } from 'lit-html';
|
||||
import type { UmbDocumentTypeWorkspaceElement } from './document-type-workspace.element';
|
||||
import { data } from 'src/core/mocks/data/document-type.data';
|
||||
import { treeData } from 'src/core/mocks/data/document-type.data';
|
||||
|
||||
export default {
|
||||
title: 'Workspaces/Document Type',
|
||||
@@ -11,5 +11,5 @@ export default {
|
||||
} as Meta;
|
||||
|
||||
export const AAAOverview: Story<UmbDocumentTypeWorkspaceElement> = () =>
|
||||
html` <umb-document-type-workspace id="${data[0].key}"></umb-document-type-workspace>`;
|
||||
html` <umb-document-type-workspace id="${treeData[0].key}"></umb-document-type-workspace>`;
|
||||
AAAOverview.storyName = 'Overview';
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import { css, html } from 'lit';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { distinctUntilChanged } from 'rxjs';
|
||||
import { UmbWorkspaceDocumentTypeContext } from '../../document-type-workspace.context';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import type { DocumentTypeDetails } from '@umbraco-cms/models';
|
||||
import type { DocumentTypeModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
@customElement('umb-workspace-view-document-type-design')
|
||||
export class UmbWorkspaceViewDocumentTypeDesignElement extends UmbLitElement {
|
||||
static styles = [UUITextStyles, css``];
|
||||
|
||||
@state()
|
||||
_documentType?: DocumentTypeDetails | null;
|
||||
_documentType?: DocumentTypeModel;
|
||||
|
||||
private _workspaceContext?: UmbWorkspaceDocumentTypeContext;
|
||||
|
||||
@@ -28,7 +27,7 @@ export class UmbWorkspaceViewDocumentTypeDesignElement extends UmbLitElement {
|
||||
private _observeDocumentType() {
|
||||
if (!this._workspaceContext) return;
|
||||
|
||||
this.observe(this._workspaceContext.data.pipe(distinctUntilChanged()), (documentType) => {
|
||||
this.observe(this._workspaceContext.data, (documentType) => {
|
||||
this._documentType = documentType;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { css, html, LitElement, nothing } from 'lit';
|
||||
import { ifDefined } from 'lit-html/directives/if-defined.js';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { UmbExecutedEvent } from 'src/core/events';
|
||||
import type { UmbTableColumn, UmbTableItem } from '../../../../../../shared/components/table';
|
||||
import { UmbExecutedEvent } from 'src/core/events';
|
||||
|
||||
// TODO: this could be done more generic, but for now we just need it for the document table
|
||||
@customElement('umb-document-table-actions-column-layout')
|
||||
|
||||
@@ -14,13 +14,12 @@ import {
|
||||
UmbTableOrderedEvent,
|
||||
UmbTableSelectedEvent,
|
||||
} from '../../../../../shared/components/table';
|
||||
import type { DocumentDetails } from '@umbraco-cms/models';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import { EntityTreeItemModel } from '@umbraco-cms/backend-api';
|
||||
import { DocumentTreeItemModel, EntityTreeItemModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
import './column-layouts/document-table-actions-column-layout.element';
|
||||
|
||||
type EntityType = DocumentDetails;
|
||||
type EntityType = DocumentTreeItemModel;
|
||||
|
||||
@customElement('umb-document-table-collection-view')
|
||||
export class UmbDocumentTableCollectionViewElement extends UmbLitElement {
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
import type { RepositoryTreeDataSource } from '../../../../../libs/repository/repository-tree-data-source.interface';
|
||||
import { DocumentTreeServerDataSource } from './sources/document.tree.server.data';
|
||||
import { UmbDocumentTreeStore, UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN } from './document.tree.store';
|
||||
import { UmbDocumentDetailStore, UMB_DOCUMENT_DETAIL_STORE_CONTEXT_TOKEN } from './document.detail.store';
|
||||
import { UmbDocumentDetailServerDataSource } from './sources/document.detail.server.data';
|
||||
import { UmbDocumentStore, UMB_DOCUMENT_DETAIL_STORE_CONTEXT_TOKEN } from './document.store';
|
||||
import { UmbDocumentServerDataSource } from './sources/document.server.data';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
import { UmbContextConsumerController } from '@umbraco-cms/context-api';
|
||||
import { ProblemDetailsModel } from '@umbraco-cms/backend-api';
|
||||
import { ProblemDetailsModel, DocumentModel } from '@umbraco-cms/backend-api';
|
||||
import type { UmbTreeRepository } from 'libs/repository/tree-repository.interface';
|
||||
import { UmbDetailRepository } from '@umbraco-cms/repository';
|
||||
import type { DocumentDetails } from '@umbraco-cms/models';
|
||||
import { UmbNotificationService, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN } from '@umbraco-cms/notification';
|
||||
|
||||
type ItemDetailType = DocumentDetails;
|
||||
type ItemType = DocumentModel;
|
||||
|
||||
// Move to documentation / JSdoc
|
||||
/* We need to create a new instance of the repository from within the element context. We want the notifications to be displayed in the right context. */
|
||||
// element -> context -> repository -> (store) -> data source
|
||||
// All methods should be async and return a promise. Some methods might return an observable as part of the promise response.
|
||||
export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailRepository<ItemDetailType> {
|
||||
export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailRepository<ItemType> {
|
||||
#init!: Promise<unknown>;
|
||||
|
||||
#host: UmbControllerHostInterface;
|
||||
@@ -25,8 +24,8 @@ export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailReposi
|
||||
#treeSource: RepositoryTreeDataSource;
|
||||
#treeStore?: UmbDocumentTreeStore;
|
||||
|
||||
#detailDataSource: UmbDocumentDetailServerDataSource;
|
||||
#detailStore?: UmbDocumentDetailStore;
|
||||
#detailDataSource: UmbDocumentServerDataSource;
|
||||
#detailStore?: UmbDocumentStore;
|
||||
|
||||
#notificationService?: UmbNotificationService;
|
||||
|
||||
@@ -35,7 +34,7 @@ export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailReposi
|
||||
|
||||
// TODO: figure out how spin up get the correct data source
|
||||
this.#treeSource = new DocumentTreeServerDataSource(this.#host);
|
||||
this.#detailDataSource = new UmbDocumentDetailServerDataSource(this.#host);
|
||||
this.#detailDataSource = new UmbDocumentServerDataSource(this.#host);
|
||||
|
||||
this.#init = Promise.all([
|
||||
new UmbContextConsumerController(this.#host, UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN, (instance) => {
|
||||
@@ -124,7 +123,7 @@ export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailReposi
|
||||
return this.#detailDataSource.createScaffold(parentKey);
|
||||
}
|
||||
|
||||
async requestDetails(key: string) {
|
||||
async requestByKey(key: string) {
|
||||
await this.#init;
|
||||
|
||||
// TODO: should we show a notification if the key is missing?
|
||||
@@ -144,14 +143,14 @@ export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailReposi
|
||||
|
||||
// Could potentially be general methods:
|
||||
|
||||
async createDetail(template: ItemDetailType) {
|
||||
async createDetail(item: ItemType) {
|
||||
await this.#init;
|
||||
|
||||
if (!template || !template.key) {
|
||||
throw new Error('Template is missing');
|
||||
if (!item || !item.key) {
|
||||
throw new Error('Document is missing');
|
||||
}
|
||||
|
||||
const { error } = await this.#detailDataSource.insert(template);
|
||||
const { error } = await this.#detailDataSource.insert(item);
|
||||
|
||||
if (!error) {
|
||||
const notification = { data: { message: `Document created` } };
|
||||
@@ -160,20 +159,20 @@ export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailReposi
|
||||
|
||||
// TODO: we currently don't use the detail store for anything.
|
||||
// Consider to look up the data before fetching from the server
|
||||
this.#detailStore?.append(template);
|
||||
this.#detailStore?.append(item);
|
||||
// TODO: Update tree store with the new item? or ask tree to request the new item?
|
||||
|
||||
return { error };
|
||||
}
|
||||
|
||||
async saveDetail(document: ItemDetailType) {
|
||||
async saveDetail(item: ItemType) {
|
||||
await this.#init;
|
||||
|
||||
if (!document || !document.key) {
|
||||
throw new Error('Template is missing');
|
||||
if (!item || !item.key) {
|
||||
throw new Error('Document is missing');
|
||||
}
|
||||
|
||||
const { error } = await this.#detailDataSource.update(document);
|
||||
const { error } = await this.#detailDataSource.update(item);
|
||||
|
||||
if (!error) {
|
||||
const notification = { data: { message: `Document saved` } };
|
||||
@@ -182,10 +181,9 @@ export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailReposi
|
||||
|
||||
// TODO: we currently don't use the detail store for anything.
|
||||
// Consider to look up the data before fetching from the server
|
||||
// Consider notify a workspace if a template is updated in the store while someone is editing it.
|
||||
this.#detailStore?.append(document);
|
||||
this.#treeStore?.updateItem(document.key, { name: document.name });
|
||||
|
||||
// Consider notify a workspace if a document is updated in the store while someone is editing it.
|
||||
this.#detailStore?.append(item);
|
||||
//this.#treeStore?.updateItem(item.key, { name: item.name });// Port data to tree store.
|
||||
// TODO: would be nice to align the stores on methods/methodNames.
|
||||
|
||||
return { error };
|
||||
@@ -209,7 +207,7 @@ export class UmbDocumentRepository implements UmbTreeRepository, UmbDetailReposi
|
||||
|
||||
// TODO: we currently don't use the detail store for anything.
|
||||
// Consider to look up the data before fetching from the server.
|
||||
// Consider notify a workspace if a template is deleted from the store while someone is editing it.
|
||||
// Consider notify a workspace if a document is deleted from the store while someone is editing it.
|
||||
this.#detailStore?.remove([key]);
|
||||
this.#treeStore?.removeItem(key);
|
||||
// TODO: would be nice to align the stores on methods/methodNames.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { DocumentDetails } from '@umbraco-cms/models';
|
||||
import { DocumentModel } 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';
|
||||
@@ -10,9 +10,8 @@ import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
* @extends {UmbStoreBase}
|
||||
* @description - Data Store for Template Details
|
||||
*/
|
||||
export class UmbDocumentDetailStore extends UmbStoreBase {
|
||||
|
||||
#data = new ArrayState<DocumentDetails>([], (x) => x.key);
|
||||
export class UmbDocumentStore extends UmbStoreBase {
|
||||
#data = new ArrayState<DocumentModel>([], (x) => x.key);
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbDocumentDetailStore.
|
||||
@@ -20,7 +19,7 @@ export class UmbDocumentDetailStore extends UmbStoreBase {
|
||||
* @memberof UmbDocumentDetailStore
|
||||
*/
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
super(host, UmbDocumentDetailStore.name);
|
||||
super(host, UmbDocumentStore.name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,20 +27,27 @@ export class UmbDocumentDetailStore extends UmbStoreBase {
|
||||
* @param {DocumentDetails} document
|
||||
* @memberof UmbDocumentDetailStore
|
||||
*/
|
||||
append(document: DocumentDetails) {
|
||||
append(document: DocumentModel) {
|
||||
this.#data.append([document]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a document to the store
|
||||
* @param {DocumentModel} document
|
||||
* @memberof UmbDocumentStore
|
||||
*/
|
||||
byKey(key: DocumentModel['key']) {
|
||||
return this.#data.getObservablePart((x) => x.find((y) => y.key === key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes documents in the store with the given uniques
|
||||
* @param {string[]} uniques
|
||||
* @memberof UmbDocumentDetailStore
|
||||
*/
|
||||
remove(uniques: string[]) {
|
||||
remove(uniques: Array<DocumentModel['key']>) {
|
||||
this.#data.remove(uniques);
|
||||
}
|
||||
}
|
||||
|
||||
export const UMB_DOCUMENT_DETAIL_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbDocumentDetailStore>(
|
||||
UmbDocumentDetailStore.name
|
||||
);
|
||||
export const UMB_DOCUMENT_DETAIL_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbDocumentStore>(UmbDocumentStore.name);
|
||||
@@ -1,22 +1,21 @@
|
||||
import { RepositoryDetailDataSource } from '@umbraco-cms/repository';
|
||||
import { ProblemDetailsModel } from '@umbraco-cms/backend-api';
|
||||
import { DocumentResource, ProblemDetailsModel, DocumentModel } from '@umbraco-cms/backend-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
|
||||
import type { DataSourceResponse, DocumentDetails } from '@umbraco-cms/models';
|
||||
|
||||
/**
|
||||
* A data source for the Template detail that fetches data from the server
|
||||
* A data source for the Document that fetches data from the server
|
||||
* @export
|
||||
* @class UmbTemplateDetailServerDataSource
|
||||
* @implements {TemplateDetailDataSource}
|
||||
* @class UmbDocumentServerDataSource
|
||||
* @implements {RepositoryDetailDataSource}
|
||||
*/
|
||||
export class UmbDocumentDetailServerDataSource implements RepositoryDetailDataSource<DocumentDetails> {
|
||||
export class UmbDocumentServerDataSource implements RepositoryDetailDataSource<DocumentModel> {
|
||||
#host: UmbControllerHostInterface;
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbDocumentDetailServerDataSource.
|
||||
* Creates an instance of UmbDocumentServerDataSource.
|
||||
* @param {UmbControllerHostInterface} host
|
||||
* @memberof UmbDocumentDetailServerDataSource
|
||||
* @memberof UmbDocumentServerDataSource
|
||||
*/
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
this.#host = host;
|
||||
@@ -26,7 +25,7 @@ export class UmbDocumentDetailServerDataSource implements RepositoryDetailDataSo
|
||||
* Fetches a Document with the given key from the server
|
||||
* @param {string} key
|
||||
* @return {*}
|
||||
* @memberof UmbDocumentDetailServerDataSource
|
||||
* @memberof UmbDocumentServerDataSource
|
||||
*/
|
||||
async get(key: string) {
|
||||
if (!key) {
|
||||
@@ -36,10 +35,9 @@ export class UmbDocumentDetailServerDataSource implements RepositoryDetailDataSo
|
||||
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
// TODO: use backend cli when available.
|
||||
fetch(`/umbraco/management/api/v1/document/details/${key}`)
|
||||
.then((res) => res.json())
|
||||
.then((res) => res[0] || undefined)
|
||||
DocumentResource.getDocumentByKey({
|
||||
key,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -47,37 +45,13 @@ export class UmbDocumentDetailServerDataSource implements RepositoryDetailDataSo
|
||||
* Creates a new Document scaffold
|
||||
* @param {(string | null)} parentKey
|
||||
* @return {*}
|
||||
* @memberof UmbDocumentDetailServerDataSource
|
||||
* @memberof UmbDocumentServerDataSource
|
||||
*/
|
||||
async createScaffold(parentKey: string | null) {
|
||||
const data: DocumentDetails = {
|
||||
key: '',
|
||||
name: '',
|
||||
icon: '',
|
||||
type: '',
|
||||
hasChildren: false,
|
||||
parentKey: parentKey ?? '',
|
||||
isTrashed: false,
|
||||
properties: [
|
||||
{
|
||||
alias: '',
|
||||
label: '',
|
||||
description: '',
|
||||
dataTypeKey: '',
|
||||
},
|
||||
],
|
||||
data: [
|
||||
{
|
||||
alias: '',
|
||||
value: '',
|
||||
},
|
||||
],
|
||||
variants: [
|
||||
{
|
||||
name: '',
|
||||
},
|
||||
],
|
||||
} as DocumentDetails;
|
||||
const data: DocumentModel = {
|
||||
properties: [],
|
||||
variants: [],
|
||||
};
|
||||
|
||||
return { data };
|
||||
}
|
||||
@@ -86,9 +60,9 @@ export class UmbDocumentDetailServerDataSource implements RepositoryDetailDataSo
|
||||
* Inserts a new Document on the server
|
||||
* @param {Document} document
|
||||
* @return {*}
|
||||
* @memberof UmbDocumentDetailServerDataSource
|
||||
* @memberof UmbDocumentServerDataSource
|
||||
*/
|
||||
async insert(document: DocumentDetails) {
|
||||
async insert(document: DocumentModel) {
|
||||
if (!document.key) {
|
||||
//const error: ProblemDetails = { title: 'Document key is missing' };
|
||||
return Promise.reject();
|
||||
@@ -104,7 +78,8 @@ export class UmbDocumentDetailServerDataSource implements RepositoryDetailDataSo
|
||||
return Promise.reject();
|
||||
}
|
||||
//return tryExecuteAndNotify(this.#host, DocumentResource.postDocument(payload));
|
||||
return tryExecuteAndNotify<DocumentDetails>(
|
||||
// TODO: use resources when end point is ready:
|
||||
return tryExecuteAndNotify<DocumentModel>(
|
||||
this.#host,
|
||||
fetch('/umbraco/management/api/v1/document/save', {
|
||||
method: 'POST',
|
||||
@@ -120,10 +95,10 @@ export class UmbDocumentDetailServerDataSource implements RepositoryDetailDataSo
|
||||
* Updates a Document on the server
|
||||
* @param {Document} Document
|
||||
* @return {*}
|
||||
* @memberof UmbDocumentDetailServerDataSource
|
||||
* @memberof UmbDocumentServerDataSource
|
||||
*/
|
||||
// TODO: Error mistake in this:
|
||||
async update(document: DocumentDetails) {
|
||||
async update(document: DocumentModel) {
|
||||
if (!document.key) {
|
||||
const error: ProblemDetailsModel = { title: 'Document key is missing' };
|
||||
return { error };
|
||||
@@ -139,7 +114,8 @@ export class UmbDocumentDetailServerDataSource implements RepositoryDetailDataSo
|
||||
return { error: myError };
|
||||
}
|
||||
|
||||
return tryExecuteAndNotify<DocumentDetails>(
|
||||
// TODO: use resources when end point is ready:
|
||||
return tryExecuteAndNotify<DocumentModel>(
|
||||
this.#host,
|
||||
fetch('/umbraco/management/api/v1/document/save', {
|
||||
method: 'POST',
|
||||
@@ -155,7 +131,7 @@ export class UmbDocumentDetailServerDataSource implements RepositoryDetailDataSo
|
||||
* Trash a Document on the server
|
||||
* @param {Document} Document
|
||||
* @return {*}
|
||||
* @memberof UmbDocumentDetailServerDataSource
|
||||
* @memberof UmbDocumentServerDataSource
|
||||
*/
|
||||
async trash(key: string) {
|
||||
if (!key) {
|
||||
@@ -163,7 +139,8 @@ export class UmbDocumentDetailServerDataSource implements RepositoryDetailDataSo
|
||||
return { error };
|
||||
}
|
||||
|
||||
return tryExecuteAndNotify<DocumentDetails>(
|
||||
// TODO: use resources when end point is ready:
|
||||
return tryExecuteAndNotify<DocumentModel>(
|
||||
this.#host,
|
||||
fetch('/umbraco/management/api/v1/document/trash', {
|
||||
method: 'POST',
|
||||
@@ -176,10 +153,10 @@ export class UmbDocumentDetailServerDataSource implements RepositoryDetailDataSo
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a Template on the server
|
||||
* Deletes a Document on the server
|
||||
* @param {string} key
|
||||
* @return {*}
|
||||
* @memberof UmbTemplateDetailServerDataSource
|
||||
* @memberof UmbDocumentServerDataSource
|
||||
*/
|
||||
// TODO: Error mistake in this:
|
||||
async delete(key: string) {
|
||||
@@ -188,6 +165,7 @@ export class UmbDocumentDetailServerDataSource implements RepositoryDetailDataSo
|
||||
return { error };
|
||||
}
|
||||
|
||||
// TODO: use resources when end point is ready:
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
fetch('/umbraco/management/api/v1/document/trash', {
|
||||
@@ -1,29 +1,103 @@
|
||||
import { UmbWorkspaceContext } from '../../../shared/components/workspace/workspace-context/workspace-context';
|
||||
import { UmbDocumentRepository } from '../repository/document.repository';
|
||||
import type { UmbWorkspaceEntityContextInterface } from '../../../shared/components/workspace/workspace-context/workspace-entity-context.interface';
|
||||
import type { DocumentDetails } from '@umbraco-cms/models';
|
||||
import { appendToFrozenArray, ObjectState } from '@umbraco-cms/observable-api';
|
||||
import { UmbDocumentTypeRepository } from '../../document-types/repository/document-type.repository';
|
||||
import type { DocumentModel, DocumentTypeModel } from '@umbraco-cms/backend-api';
|
||||
import {
|
||||
partialUpdateFrozenArray,
|
||||
ObjectState,
|
||||
ArrayState,
|
||||
UmbObserverController,
|
||||
appendToFrozenArray,
|
||||
} from '@umbraco-cms/observable-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
|
||||
// TODO: should this contex be called DocumentDraft instead of workspace? or should the draft be part of this?
|
||||
// TODO: should this context be called DocumentDraft instead of workspace? or should the draft be part of this?
|
||||
|
||||
type EntityType = DocumentDetails;
|
||||
type EntityType = DocumentModel;
|
||||
export class UmbDocumentWorkspaceContext
|
||||
extends UmbWorkspaceContext
|
||||
implements UmbWorkspaceEntityContextInterface<EntityType | undefined>
|
||||
{
|
||||
#isNew = false;
|
||||
#host: UmbControllerHostInterface;
|
||||
#templateDetailRepo: UmbDocumentRepository;
|
||||
#documentRepository: UmbDocumentRepository;
|
||||
#documentTypeRepository: UmbDocumentTypeRepository;
|
||||
//#dataTypeRepository: UmbDataTypeRepository;
|
||||
|
||||
#data = new ObjectState<EntityType | undefined>(undefined);
|
||||
data = this.#data.asObservable();
|
||||
name = this.#data.getObservablePart((data) => data?.name);
|
||||
documentTypeKey = this.#data.getObservablePart((data) => data?.contentTypeKey);
|
||||
|
||||
#documentTypes = new ArrayState<DocumentTypeModel>([], (x) => x.key);
|
||||
documentTypes = this.#documentTypes.asObservable();
|
||||
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
super(host);
|
||||
this.#host = host;
|
||||
this.#templateDetailRepo = new UmbDocumentRepository(this.#host);
|
||||
this.#documentRepository = new UmbDocumentRepository(this.#host);
|
||||
this.#documentTypeRepository = new UmbDocumentTypeRepository(this.#host);
|
||||
//this.#dataTypeRepository = new UmbDataTypeRepository(this.#host);
|
||||
|
||||
new UmbObserverController(this._host, this.documentTypeKey, (key) => this.loadDocumentType(key));
|
||||
}
|
||||
|
||||
async load(entityKey: string) {
|
||||
const { data } = await this.#documentRepository.requestByKey(entityKey);
|
||||
if (data) {
|
||||
this.#isNew = false;
|
||||
this.#data.next(data);
|
||||
}
|
||||
}
|
||||
|
||||
async createScaffold(parentKey: string | null) {
|
||||
const { data } = await this.#documentRepository.createDetailsScaffold(parentKey);
|
||||
if (!data) return;
|
||||
this.#isNew = true;
|
||||
this.#data.next(data);
|
||||
}
|
||||
|
||||
async loadDocumentType(key?: string) {
|
||||
if (!key) return;
|
||||
|
||||
const { data } = await this.#documentTypeRepository.requestByKey(key);
|
||||
if (!data) return;
|
||||
|
||||
// Load inherited and composed types:
|
||||
await data?.compositions?.forEach(async (composition) => {
|
||||
if (composition.key) {
|
||||
this.loadDocumentType(composition.key);
|
||||
}
|
||||
});
|
||||
|
||||
new UmbObserverController(this._host, await this.#documentTypeRepository.byKey(key), (data) => {
|
||||
if (data) {
|
||||
this.#documentTypes.appendOne(data);
|
||||
this.loadDataTypeOfDocumentType(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async loadDataTypeOfDocumentType(documentType?: DocumentTypeModel) {
|
||||
if (!documentType) return;
|
||||
|
||||
// Load inherited and composed types:
|
||||
await documentType?.properties?.forEach(async (property) => {
|
||||
if (property.dataTypeKey) {
|
||||
this.loadDataType(property.dataTypeKey);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async loadDataType(key?: string) {
|
||||
if (!key) return;
|
||||
|
||||
//const { data } = await this.#dataTypeRepository.requestDetails(key);
|
||||
|
||||
/*new UmbObserverController(this._host, await this.#documentTypeRepository.byKey(key), (data) => {
|
||||
if (data) {
|
||||
this.#documentTypes.appendOne(data);
|
||||
}
|
||||
});*/
|
||||
}
|
||||
|
||||
getData() {
|
||||
@@ -44,8 +118,14 @@ export class UmbDocumentWorkspaceContext
|
||||
return 'document';
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.#data.update({ name });
|
||||
setName(name: string, culture?: string | null, segment?: string | null) {
|
||||
const variants = this.#data.getValue()?.variants || [];
|
||||
const newVariants = partialUpdateFrozenArray(
|
||||
variants,
|
||||
{ name },
|
||||
(v) => v.culture == culture && v.segment == segment
|
||||
);
|
||||
this.#data.update({ variants: newVariants });
|
||||
}
|
||||
/*
|
||||
getEntityType = this.#manager.getEntityType;
|
||||
@@ -68,48 +148,43 @@ export class UmbDocumentWorkspaceContext
|
||||
this.#draft.next(data)
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
*/
|
||||
propertiesOf(culture: string | null, segment: string | null) {
|
||||
return this.#data.getObservablePart((data) =>
|
||||
data?.properties?.filter((p) => (culture === p.culture || null) && (segment === p.segment || null))
|
||||
);
|
||||
}
|
||||
|
||||
propertyStructure() {
|
||||
// TODO: handle composition of document types.
|
||||
return this.#documentTypes.getObservablePart((data) => data[0]?.properties);
|
||||
}
|
||||
|
||||
setPropertyValue(alias: string, value: unknown) {
|
||||
const entry = { alias: alias, value: value };
|
||||
|
||||
const currentData = this.#data.value;
|
||||
if (currentData) {
|
||||
const newDataSet = appendToFrozenArray(currentData.data, entry, (x) => x.alias);
|
||||
|
||||
this.#data.update({ data: newDataSet });
|
||||
// TODO: make a partial update method for array of data, (idea/concept, use if this case is getting common)
|
||||
const newDataSet = appendToFrozenArray(currentData.properties || [], entry, (x) => x.alias);
|
||||
this.#data.update({ properties: newDataSet });
|
||||
}
|
||||
}
|
||||
|
||||
async load(entityKey: string) {
|
||||
const { data } = await this.#templateDetailRepo.requestDetails(entityKey);
|
||||
if (data) {
|
||||
this.#isNew = false;
|
||||
this.#data.next(data);
|
||||
}
|
||||
}
|
||||
|
||||
async createScaffold(parentKey: string | null) {
|
||||
const { data } = await this.#templateDetailRepo.createDetailsScaffold(parentKey);
|
||||
if (!data) return;
|
||||
this.#isNew = true;
|
||||
this.#data.next(data);
|
||||
}
|
||||
|
||||
async save() {
|
||||
if (!this.#data.value) return;
|
||||
if (this.#isNew) {
|
||||
await this.#templateDetailRepo.createDetail(this.#data.value);
|
||||
await this.#documentRepository.createDetail(this.#data.value);
|
||||
} else {
|
||||
await this.#templateDetailRepo.saveDetail(this.#data.value);
|
||||
await this.#documentRepository.saveDetail(this.#data.value);
|
||||
}
|
||||
// If it went well, then its not new anymore?.
|
||||
this.#isNew = false;
|
||||
}
|
||||
|
||||
async delete(key: string) {
|
||||
await this.#templateDetailRepo.delete(key);
|
||||
await this.#documentRepository.delete(key);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import './document-workspace.element';
|
||||
import { Meta, Story } from '@storybook/web-components';
|
||||
import { html } from 'lit-html';
|
||||
import { data as documentNodes } from '../../../../core/mocks/data/document.data';
|
||||
import type { UmbDocumentWorkspaceElement } from './document-workspace.element';
|
||||
import { data as documentNodes } from 'src/core/mocks/data/document.data';
|
||||
|
||||
export default {
|
||||
title: 'Workspaces/Document',
|
||||
|
||||
@@ -25,8 +25,7 @@ const workspaceViews: Array<ManifestWorkspaceView> = [
|
||||
type: 'workspaceView',
|
||||
alias: 'Umb.WorkspaceView.Document.Edit',
|
||||
name: 'Document Workspace Edit View',
|
||||
loader: () =>
|
||||
import('../../../shared/components/workspace/workspace-content/views/edit/workspace-view-content-edit.element'),
|
||||
loader: () => import('./views/workspace-view-document-edit.element'),
|
||||
weight: 200,
|
||||
meta: {
|
||||
workspaces: ['Umb.Workspace.Document'],
|
||||
@@ -52,6 +51,8 @@ const workspaceViews: Array<ManifestWorkspaceView> = [
|
||||
];
|
||||
|
||||
const workspaceViewCollections: Array<ManifestWorkspaceViewCollection> = [
|
||||
/*
|
||||
// TODO: Reenable this:
|
||||
{
|
||||
type: 'workspaceViewCollection',
|
||||
alias: 'Umb.WorkspaceView.Document.Collection',
|
||||
@@ -66,6 +67,7 @@ const workspaceViewCollections: Array<ManifestWorkspaceViewCollection> = [
|
||||
repositoryAlias: DOCUMENT_REPOSITORY_ALIAS,
|
||||
},
|
||||
},
|
||||
*/
|
||||
];
|
||||
|
||||
const workspaceActions: Array<ManifestWorkspaceAction> = [
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import { css, html } from 'lit';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
import { UmbDocumentWorkspaceContext } from '../document-workspace.context';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import { DocumentPropertyModel, DocumentTypePropertyTypeModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
@customElement('umb-workspace-view-document-edit')
|
||||
export class UmbWorkspaceViewDocumentEditElement extends UmbLitElement {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: var(--uui-size-layout-1);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@state()
|
||||
_propertyData: DocumentPropertyModel[] = [];
|
||||
|
||||
@state()
|
||||
_propertyStructures: DocumentTypePropertyTypeModel[] = [];
|
||||
|
||||
private _workspaceContext?: UmbDocumentWorkspaceContext;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// TODO: Figure out how to get the magic string for the workspace context.
|
||||
this.consumeContext<UmbDocumentWorkspaceContext>('umbWorkspaceContext', (workspaceContext) => {
|
||||
this._workspaceContext = workspaceContext;
|
||||
this._observeContent();
|
||||
});
|
||||
}
|
||||
|
||||
private _observeContent() {
|
||||
if (!this._workspaceContext) return;
|
||||
|
||||
/*
|
||||
TODO: Property-Context: This observer gets all changes, We need to fix this. it should be simpler.
|
||||
An idea to optimize this would be for this to only care about layout, meaning to property data should be watched here.
|
||||
As the properties could handle their own data on their own?
|
||||
|
||||
Should use a Observable for example: this._workspaceContext.properties
|
||||
*/
|
||||
this.observe(
|
||||
this._workspaceContext.propertiesOf(null, null),
|
||||
(properties) => {
|
||||
this._propertyData = properties || [];
|
||||
//this._data = content?.data || [];
|
||||
|
||||
/*
|
||||
Maybe we should not give the value(Data), but the umb-content-property should get the context and observe its own data.
|
||||
This would become a more specific Observer therefor better performance?.. Note to self: Debate with Mads how he sees this perspective.
|
||||
*/
|
||||
},
|
||||
'observeWorkspaceContextData'
|
||||
);
|
||||
this.observe(
|
||||
this._workspaceContext.propertyStructure(),
|
||||
(propertyStructure) => {
|
||||
this._propertyStructures = propertyStructure || [];
|
||||
},
|
||||
'observeWorkspaceContextData'
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<uui-box>
|
||||
${repeat(
|
||||
this._propertyStructures,
|
||||
(property) => property.alias,
|
||||
(property) =>
|
||||
html`<umb-content-property
|
||||
.property=${property}
|
||||
.value=${this._propertyData.find((x) => x.alias === property.alias)?.value}></umb-content-property> `
|
||||
)}
|
||||
</uui-box>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbWorkspaceViewDocumentEditElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-workspace-view-document-edit': UmbWorkspaceViewDocumentEditElement;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { DataTypeDetails, MediaTypeDetails } from '@umbraco-cms/models';
|
||||
import type { MediaTypeDetails } from '@umbraco-cms/models';
|
||||
import { UmbContextToken } from '@umbraco-cms/context-api';
|
||||
import { ArrayState } from '@umbraco-cms/observable-api';
|
||||
import { UmbEntityDetailStore, UmbStoreBase } from '@umbraco-cms/store';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
|
||||
|
||||
export const UMB_MEDIA_TYPE_DETAIL_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbMediaTypeDetailStore>('UmbMediaTypeDetailStore');
|
||||
|
||||
export const UMB_MEDIA_TYPE_DETAIL_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbMediaTypeDetailStore>(
|
||||
'UmbMediaTypeDetailStore'
|
||||
);
|
||||
|
||||
/**
|
||||
* @export
|
||||
@@ -15,25 +15,20 @@ export const UMB_MEDIA_TYPE_DETAIL_STORE_CONTEXT_TOKEN = new UmbContextToken<Umb
|
||||
* @description - Details Data Store for Media Types
|
||||
*/
|
||||
export class UmbMediaTypeDetailStore extends UmbStoreBase implements UmbEntityDetailStore<MediaTypeDetails> {
|
||||
|
||||
|
||||
private _data = new ArrayState<MediaTypeDetails>([], (x) => x.key);
|
||||
|
||||
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
super(host, UMB_MEDIA_TYPE_DETAIL_STORE_CONTEXT_TOKEN.toString());
|
||||
}
|
||||
|
||||
|
||||
getScaffold(entityType: string, parentKey: string | null) {
|
||||
return {
|
||||
} as MediaTypeDetails;
|
||||
return {} as MediaTypeDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description - Request a Data Type by key. The Data Type is added to the store and is returned as an Observable.
|
||||
* @param {string} key
|
||||
* @return {*} {(Observable<DataTypeDetails | undefined>)}
|
||||
* @return {*} {(Observable<DataTypeModel | undefined>)}
|
||||
* @memberof UmbMediaTypesStore
|
||||
*/
|
||||
getByKey(key: string) {
|
||||
|
||||
@@ -121,7 +121,7 @@ export class UmbMediaRepository implements UmbTreeRepository, UmbDetailRepositor
|
||||
return this.#detailDataSource.createScaffold(parentKey);
|
||||
}
|
||||
|
||||
async requestDetails(key: string) {
|
||||
async requestByKey(key: string) {
|
||||
await this.#init;
|
||||
|
||||
// TODO: should we show a notification if the key is missing?
|
||||
|
||||
@@ -52,7 +52,7 @@ export class UmbMediaWorkspaceContext
|
||||
}
|
||||
|
||||
async load(entityKey: string) {
|
||||
const { data } = await this.#detailRepository.requestDetails(entityKey);
|
||||
const { data } = await this.#detailRepository.requestByKey(entityKey);
|
||||
if (data) {
|
||||
this.#isNew = false;
|
||||
this.#data.next(data);
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
import type { DataTypeDetails } from '@umbraco-cms/models';
|
||||
import { UmbContextToken } from '@umbraco-cms/context-api';
|
||||
import { ArrayState } from '@umbraco-cms/observable-api';
|
||||
import { UmbEntityDetailStore, UmbStoreBase } from '@umbraco-cms/store';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
|
||||
|
||||
export const UMB_DATA_TYPE_DETAIL_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbDataTypeDetailStore>('UmbDataTypeDetailStore');
|
||||
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @class UmbDataTypeDetailStore
|
||||
* @extends {UmbStoreBase}
|
||||
* @description - Details Data Store for Data Types
|
||||
*/
|
||||
export class UmbDataTypeDetailStore extends UmbStoreBase implements UmbEntityDetailStore<DataTypeDetails> {
|
||||
|
||||
|
||||
#data = new ArrayState<DataTypeDetails>([], (x) => x.key);
|
||||
|
||||
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
super(host, UMB_DATA_TYPE_DETAIL_STORE_CONTEXT_TOKEN.toString());
|
||||
}
|
||||
|
||||
|
||||
getScaffold(entityType: string, parentKey: string | null) {
|
||||
return {
|
||||
key: '',
|
||||
name: '',
|
||||
icon: '',
|
||||
type: 'data-type',
|
||||
hasChildren: false,
|
||||
parentKey: '',
|
||||
propertyEditorModelAlias: '',
|
||||
propertyEditorUIAlias: '',
|
||||
data: [],
|
||||
} as DataTypeDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description - Request a Data Type by key. The Data Type is added to the store and is returned as an Observable.
|
||||
* @param {string} key
|
||||
* @return {*} {(Observable<DataTypeDetails | undefined>)}
|
||||
* @memberof UmbDataTypesStore
|
||||
*/
|
||||
getByKey(key: string) {
|
||||
// TODO: use backend cli when available.
|
||||
fetch(`/umbraco/backoffice/data-type/details/${key}`)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
this.#data.append(data);
|
||||
});
|
||||
|
||||
|
||||
return this.#data.getObservablePart((documents) =>
|
||||
documents.find((document) => document.key === key)
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: make sure UI somehow can follow the status of this action.
|
||||
/**
|
||||
* @description - Save a Data Type.
|
||||
* @param {Array<DataTypeDetails>} dataTypes
|
||||
* @memberof UmbDataTypesStore
|
||||
* @return {*} {Promise<void>}
|
||||
*/
|
||||
save(data: DataTypeDetails[]) {
|
||||
// fetch from server and update store
|
||||
// TODO: use Fetcher API.
|
||||
let body: string;
|
||||
|
||||
try {
|
||||
body = JSON.stringify(data);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
// TODO: use backend cli when available.
|
||||
return fetch('/umbraco/management/api/v1/data-type/save', {
|
||||
method: 'POST',
|
||||
body: body,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((data: Array<DataTypeDetails>) => {
|
||||
this.#data.append(data);
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: How can we avoid having this in both stores?
|
||||
/**
|
||||
* @description - Delete a Data Type.
|
||||
* @param {string[]} keys
|
||||
* @memberof UmbDataTypesStore
|
||||
* @return {*} {Promise<void>}
|
||||
*/
|
||||
async delete(keys: string[]) {
|
||||
// TODO: use backend cli when available.
|
||||
await fetch('/umbraco/backoffice/data-type/delete', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(keys),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
this.#data.remove(keys);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
import type { RepositoryTreeDataSource } from '../../../../../libs/repository/repository-tree-data-source.interface';
|
||||
import { UmbDataTypeTreeStore, UMB_DATA_TYPE_TREE_STORE_CONTEXT_TOKEN } from './data-type.tree.store';
|
||||
import { UmbDataTypeServerDataSource } from './sources/data-type.server.data';
|
||||
import { UmbDataTypeStore, UMB_DATA_TYPE_STORE_CONTEXT_TOKEN } from './data-type.store';
|
||||
import { DataTypeTreeServerDataSource } from './sources/data-type.tree.server.data';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
import { UmbContextConsumerController } from '@umbraco-cms/context-api';
|
||||
import { ProblemDetailsModel, DataTypeModel } from '@umbraco-cms/backend-api';
|
||||
import type { UmbTreeRepository } from 'libs/repository/tree-repository.interface';
|
||||
import { UmbDetailRepository } from '@umbraco-cms/repository';
|
||||
import { UmbNotificationService, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN } from '@umbraco-cms/notification';
|
||||
|
||||
type ItemType = DataTypeModel;
|
||||
|
||||
// Move to documentation / JSdoc
|
||||
/* We need to create a new instance of the repository from within the element context. We want the notifications to be displayed in the right context. */
|
||||
// element -> context -> repository -> (store) -> data source
|
||||
// All methods should be async and return a promise. Some methods might return an observable as part of the promise response.
|
||||
export class UmbDataTypeRepository implements UmbTreeRepository, UmbDetailRepository<ItemType> {
|
||||
#init!: Promise<unknown>;
|
||||
|
||||
#host: UmbControllerHostInterface;
|
||||
|
||||
#treeSource: RepositoryTreeDataSource;
|
||||
#treeStore?: UmbDataTypeTreeStore;
|
||||
|
||||
#detailDataSource: UmbDataTypeServerDataSource;
|
||||
#detailStore?: UmbDataTypeStore;
|
||||
|
||||
#notificationService?: UmbNotificationService;
|
||||
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
this.#host = host;
|
||||
|
||||
// TODO: figure out how spin up get the correct data source
|
||||
this.#treeSource = new DataTypeTreeServerDataSource(this.#host);
|
||||
this.#detailDataSource = new UmbDataTypeServerDataSource(this.#host);
|
||||
|
||||
this.#init = Promise.all([
|
||||
new UmbContextConsumerController(this.#host, UMB_DATA_TYPE_TREE_STORE_CONTEXT_TOKEN, (instance) => {
|
||||
this.#treeStore = instance;
|
||||
}),
|
||||
|
||||
new UmbContextConsumerController(this.#host, UMB_DATA_TYPE_STORE_CONTEXT_TOKEN, (instance) => {
|
||||
this.#detailStore = instance;
|
||||
}),
|
||||
|
||||
new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN, (instance) => {
|
||||
this.#notificationService = instance;
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
// TODO: Trash
|
||||
// TODO: Move
|
||||
|
||||
async requestRootTreeItems() {
|
||||
await this.#init;
|
||||
|
||||
const { data, error } = await this.#treeSource.getRootItems();
|
||||
|
||||
if (data) {
|
||||
this.#treeStore?.appendItems(data.items);
|
||||
}
|
||||
|
||||
return { data, error, asObservable: () => this.#treeStore!.rootItems };
|
||||
}
|
||||
|
||||
async requestTreeItemsOf(parentKey: string | null) {
|
||||
await this.#init;
|
||||
|
||||
if (!parentKey) {
|
||||
const error: ProblemDetailsModel = { title: 'Parent key is missing' };
|
||||
return { data: undefined, error };
|
||||
}
|
||||
|
||||
const { data, error } = await this.#treeSource.getChildrenOf(parentKey);
|
||||
|
||||
if (data) {
|
||||
this.#treeStore?.appendItems(data.items);
|
||||
}
|
||||
|
||||
return { data, error, asObservable: () => this.#treeStore!.childrenOf(parentKey) };
|
||||
}
|
||||
|
||||
async requestTreeItems(keys: Array<string>) {
|
||||
await this.#init;
|
||||
|
||||
if (!keys) {
|
||||
const error: ProblemDetailsModel = { title: 'Keys are missing' };
|
||||
return { data: undefined, error };
|
||||
}
|
||||
|
||||
const { data, error } = await this.#treeSource.getItems(keys);
|
||||
|
||||
return { data, error, asObservable: () => this.#treeStore!.items(keys) };
|
||||
}
|
||||
|
||||
async rootTreeItems() {
|
||||
await this.#init;
|
||||
return this.#treeStore!.rootItems;
|
||||
}
|
||||
|
||||
async treeItemsOf(parentKey: string | null) {
|
||||
await this.#init;
|
||||
return this.#treeStore!.childrenOf(parentKey);
|
||||
}
|
||||
|
||||
async treeItems(keys: Array<string>) {
|
||||
await this.#init;
|
||||
return this.#treeStore!.items(keys);
|
||||
}
|
||||
|
||||
// DETAILS:
|
||||
|
||||
async createDetailsScaffold(parentKey: string | null) {
|
||||
await this.#init;
|
||||
|
||||
if (!parentKey) {
|
||||
throw new Error('Parent key is missing');
|
||||
}
|
||||
|
||||
return this.#detailDataSource.createScaffold(parentKey);
|
||||
}
|
||||
|
||||
async requestByKey(key: string) {
|
||||
await this.#init;
|
||||
|
||||
// TODO: should we show a notification if the key is missing?
|
||||
// Investigate what is best for Acceptance testing, cause in that perspective a thrown error might be the best choice?
|
||||
if (!key) {
|
||||
const error: ProblemDetailsModel = { title: 'Key is missing' };
|
||||
return { error };
|
||||
}
|
||||
const { data, error } = await this.#detailDataSource.get(key);
|
||||
|
||||
if (data) {
|
||||
this.#detailStore?.append(data);
|
||||
}
|
||||
|
||||
return { data, error };
|
||||
}
|
||||
|
||||
async byKey(key: string) {
|
||||
await this.#init;
|
||||
return this.#detailStore!.byKey(key);
|
||||
}
|
||||
|
||||
// Could potentially be general methods:
|
||||
|
||||
async createDetail(template: ItemType) {
|
||||
await this.#init;
|
||||
|
||||
if (!template || !template.key) {
|
||||
throw new Error('Template is missing');
|
||||
}
|
||||
|
||||
const { error } = await this.#detailDataSource.insert(template);
|
||||
|
||||
if (!error) {
|
||||
const notification = { data: { message: `Document created` } };
|
||||
this.#notificationService?.peek('positive', notification);
|
||||
}
|
||||
|
||||
// TODO: we currently don't use the detail store for anything.
|
||||
// Consider to look up the data before fetching from the server
|
||||
this.#detailStore?.append(template);
|
||||
// TODO: Update tree store with the new item? or ask tree to request the new item?
|
||||
|
||||
return { error };
|
||||
}
|
||||
|
||||
async saveDetail(item: ItemType) {
|
||||
await this.#init;
|
||||
|
||||
if (!item || !item.key) {
|
||||
throw new Error('Document-Type is missing');
|
||||
}
|
||||
|
||||
const { error } = await this.#detailDataSource.update(item);
|
||||
|
||||
if (!error) {
|
||||
const notification = { data: { message: `Document saved` } };
|
||||
this.#notificationService?.peek('positive', notification);
|
||||
}
|
||||
|
||||
// TODO: we currently don't use the detail store for anything.
|
||||
// Consider to look up the data before fetching from the server
|
||||
// Consider notify a workspace if a template is updated in the store while someone is editing it.
|
||||
this.#detailStore?.append(item);
|
||||
this.#treeStore?.updateItem(item.key, { name: item.name });
|
||||
// TODO: would be nice to align the stores on methods/methodNames.
|
||||
|
||||
return { error };
|
||||
}
|
||||
|
||||
// General:
|
||||
|
||||
async delete(key: string) {
|
||||
await this.#init;
|
||||
|
||||
if (!key) {
|
||||
throw new Error('Document key is missing');
|
||||
}
|
||||
|
||||
const { error } = await this.#detailDataSource.delete(key);
|
||||
|
||||
if (!error) {
|
||||
const notification = { data: { message: `Document deleted` } };
|
||||
this.#notificationService?.peek('positive', notification);
|
||||
}
|
||||
|
||||
// TODO: we currently don't use the detail store for anything.
|
||||
// Consider to look up the data before fetching from the server.
|
||||
// Consider notify a workspace if a template is deleted from the store while someone is editing it.
|
||||
this.#detailStore?.remove([key]);
|
||||
this.#treeStore?.removeItem(key);
|
||||
// TODO: would be nice to align the stores on methods/methodNames.
|
||||
|
||||
return { error };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import type { DataTypeModel } 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';
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @class UmbDataTypeStore
|
||||
* @extends {UmbStoreBase}
|
||||
* @description - Data Store for Template Details
|
||||
*/
|
||||
export class UmbDataTypeStore extends UmbStoreBase {
|
||||
#data = new ArrayState<DataTypeModel>([], (x) => x.key);
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbDataTypeStore.
|
||||
* @param {UmbControllerHostInterface} host
|
||||
* @memberof UmbDataTypeStore
|
||||
*/
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
super(host, UmbDataTypeStore.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a data-type to the store
|
||||
* @param {DataTypeModel} dataType
|
||||
* @memberof UmbDataTypeStore
|
||||
*/
|
||||
append(dataType: DataTypeModel) {
|
||||
this.#data.append([dataType]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a data-type to the store
|
||||
* @param {key} DataTypeModel key.
|
||||
* @memberof UmbDataTypeStore
|
||||
*/
|
||||
byKey(key: DataTypeModel['key']) {
|
||||
return this.#data.getObservablePart((x) => x.find((y) => y.key === key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes data-types in the store with the given uniques
|
||||
* @param {string[]} uniques
|
||||
* @memberof UmbDataTypeStore
|
||||
*/
|
||||
remove(uniques: Array<DataTypeModel['key']>) {
|
||||
this.#data.remove(uniques);
|
||||
}
|
||||
}
|
||||
|
||||
export const UMB_DATA_TYPE_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbDataTypeStore>(UmbDataTypeStore.name);
|
||||
@@ -0,0 +1,93 @@
|
||||
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';
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @class UmbDataTypeTreeStore
|
||||
* @extends {UmbStoreBase}
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbDataTypeTreeStore.
|
||||
* @param {UmbControllerHostInterface} host
|
||||
* @memberof UmbDataTypeTreeStore
|
||||
*/
|
||||
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>(
|
||||
UmbDataTypeTreeStore.name
|
||||
);
|
||||
@@ -0,0 +1,152 @@
|
||||
import { RepositoryDetailDataSource } from '@umbraco-cms/repository';
|
||||
import {
|
||||
ProblemDetailsModel,
|
||||
DataTypeResource,
|
||||
DataTypeModel,
|
||||
DataTypeCreateModel,
|
||||
DataTypeUpdateModel,
|
||||
} from '@umbraco-cms/backend-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
|
||||
|
||||
/**
|
||||
* A data source for the Data Type that fetches data from the server
|
||||
* @export
|
||||
* @class UmbDataTypeServerDataSource
|
||||
* @implements {RepositoryDetailDataSource}
|
||||
*/
|
||||
export class UmbDataTypeServerDataSource implements RepositoryDetailDataSource<DataTypeModel> {
|
||||
#host: UmbControllerHostInterface;
|
||||
|
||||
/**
|
||||
* Creates an instance of UmbDataTypeServerDataSource.
|
||||
* @param {UmbControllerHostInterface} host
|
||||
* @memberof UmbDataTypeServerDataSource
|
||||
*/
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
this.#host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a Data Type with the given key from the server
|
||||
* @param {string} key
|
||||
* @return {*}
|
||||
* @memberof UmbDataTypeServerDataSource
|
||||
*/
|
||||
async get(key: string) {
|
||||
if (!key) {
|
||||
const error: ProblemDetailsModel = { title: 'Key is missing' };
|
||||
return { error };
|
||||
}
|
||||
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
DataTypeResource.getDataTypeByKey({
|
||||
key,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Data Type scaffold
|
||||
* @param {(string | null)} parentKey
|
||||
* @return {*}
|
||||
* @memberof UmbDataTypeServerDataSource
|
||||
*/
|
||||
async createScaffold(parentKey: string | null) {
|
||||
const data: DataTypeModel = {
|
||||
parentKey: parentKey,
|
||||
};
|
||||
|
||||
return { data };
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new Data Type on the server
|
||||
* @param {Document} dataType
|
||||
* @return {*}
|
||||
* @memberof UmbDataTypeServerDataSource
|
||||
*/
|
||||
async insert(dataType: DataTypeModel) {
|
||||
if (!dataType.key) {
|
||||
const error: ProblemDetailsModel = { title: 'DataType key is missing' };
|
||||
return { error };
|
||||
}
|
||||
const requestBody: DataTypeCreateModel = { ...dataType };
|
||||
|
||||
// TODO: use resources when end point is ready:
|
||||
return tryExecuteAndNotify<DataTypeModel>(
|
||||
this.#host,
|
||||
DataTypeResource.postDataType({
|
||||
requestBody,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a DataType on the server
|
||||
* @param {DataTypeModel} DataType
|
||||
* @return {*}
|
||||
* @memberof UmbDataTypeServerDataSource
|
||||
*/
|
||||
// TODO: Error mistake in this:
|
||||
async update(dataType: DataTypeModel) {
|
||||
if (!dataType.key) {
|
||||
const error: ProblemDetailsModel = { title: 'DataType key is missing' };
|
||||
return { error };
|
||||
}
|
||||
|
||||
const requestBody: DataTypeUpdateModel = { ...dataType };
|
||||
|
||||
// TODO: use resources when end point is ready:
|
||||
return tryExecuteAndNotify<DataTypeModel>(
|
||||
this.#host,
|
||||
DataTypeResource.putDataTypeByKey({
|
||||
key: dataType.key,
|
||||
requestBody,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trash a Document on the server
|
||||
* @param {Document} Document
|
||||
* @return {*}
|
||||
* @memberof UmbDataTypeServerDataSource
|
||||
*/
|
||||
async trash(key: string) {
|
||||
if (!key) {
|
||||
const error: ProblemDetailsModel = { title: 'DataType key is missing' };
|
||||
return { error };
|
||||
}
|
||||
|
||||
// TODO: use resources when end point is ready:
|
||||
return tryExecuteAndNotify<DataTypeModel>(
|
||||
this.#host,
|
||||
DataTypeResource.deleteDataTypeByKey({
|
||||
key,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a Data Type on the server
|
||||
* @param {string} key
|
||||
* @return {*}
|
||||
* @memberof UmbDataTypeServerDataSource
|
||||
*/
|
||||
async delete(key: string) {
|
||||
if (!key) {
|
||||
const error: ProblemDetailsModel = { title: 'DataType key is missing' };
|
||||
return { error };
|
||||
}
|
||||
|
||||
// TODO: use resources when end point is ready:
|
||||
return tryExecuteAndNotify<DataTypeModel>(
|
||||
this.#host,
|
||||
DataTypeResource.deleteDataTypeByKey({
|
||||
key,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
import type { RepositoryTreeDataSource } from '../../../../../../libs/repository/repository-tree-data-source.interface';
|
||||
import { ProblemDetailsModel, DataTypeResource } from '@umbraco-cms/backend-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
|
||||
|
||||
/**
|
||||
* A data source for the Document tree that fetches data from the server
|
||||
* @export
|
||||
* @class DocumentTreeServerDataSource
|
||||
* @implements {DocumentTreeDataSource}
|
||||
*/
|
||||
export class DataTypeTreeServerDataSource implements RepositoryTreeDataSource {
|
||||
#host: UmbControllerHostInterface;
|
||||
|
||||
// TODO: how do we handle trashed items?
|
||||
async trashItems(keys: Array<string>) {
|
||||
if (!keys) {
|
||||
const error: ProblemDetailsModel = { title: 'DataType keys is missing' };
|
||||
return { error };
|
||||
}
|
||||
|
||||
// TODO: use resources when end point is ready:
|
||||
/*
|
||||
return tryExecuteAndNotify<DataType>(
|
||||
this.#host,
|
||||
DataTypeResource.deleteDataTypeByKey({
|
||||
key: keys,
|
||||
})
|
||||
);
|
||||
*/
|
||||
return Promise.resolve({ error: null, data: null });
|
||||
}
|
||||
|
||||
async moveItems(keys: Array<string>, destination: string) {
|
||||
// TODO: use backend cli when available.
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
fetch('/umbraco/management/api/v1/data-type/move', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ keys, destination }),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of DocumentTreeServerDataSource.
|
||||
* @param {UmbControllerHostInterface} host
|
||||
* @memberof DocumentTreeServerDataSource
|
||||
*/
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
this.#host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the root items for the tree from the server
|
||||
* @return {*}
|
||||
* @memberof DocumentTreeServerDataSource
|
||||
*/
|
||||
async getRootItems() {
|
||||
return tryExecuteAndNotify(this.#host, DataTypeResource.getTreeDataTypeRoot({}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the children of a given parent key from the server
|
||||
* @param {(string | null)} parentKey
|
||||
* @return {*}
|
||||
* @memberof DocumentTreeServerDataSource
|
||||
*/
|
||||
async getChildrenOf(parentKey: string | null) {
|
||||
if (!parentKey) {
|
||||
const error: ProblemDetailsModel = { title: 'Parent key is missing' };
|
||||
return { error };
|
||||
}
|
||||
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
DataTypeResource.getTreeDataTypeChildren({
|
||||
parentKey,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the items for the given keys from the server
|
||||
* @param {Array<string>} keys
|
||||
* @return {*}
|
||||
* @memberof DocumentTreeServerDataSource
|
||||
*/
|
||||
async getItems(keys: Array<string>) {
|
||||
if (keys) {
|
||||
const error: ProblemDetailsModel = { title: 'Keys are missing' };
|
||||
return { error };
|
||||
}
|
||||
|
||||
return tryExecuteAndNotify(
|
||||
this.#host,
|
||||
DataTypeResource.getTreeDataTypeItem({
|
||||
key: keys,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@ import { UUITextStyles } from '@umbraco-ui/uui-css';
|
||||
import { css, html } from 'lit';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
import { UmbModalService, UMB_MODAL_SERVICE_CONTEXT_TOKEN } from '../../../../../../core/modal';
|
||||
import { UMB_DATA_TYPE_DETAIL_STORE_CONTEXT_TOKEN } from '../../../data-type.detail.store';
|
||||
import type { UmbDataTypeDetailStore } from '../../../data-type.detail.store';
|
||||
import UmbTreeItemActionElement from '../../../../../shared/components/tree/action/tree-item-action.element';
|
||||
|
||||
@customElement('umb-tree-action-data-type-delete')
|
||||
@@ -11,7 +9,7 @@ export default class UmbTreeActionDataTypeDeleteElement extends UmbTreeItemActio
|
||||
static styles = [UUITextStyles, css``];
|
||||
|
||||
private _modalService?: UmbModalService;
|
||||
private _dataTypeStore?: UmbDataTypeDetailStore;
|
||||
//private _dataTypeStore?: UmbDataTypeStore;
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
@@ -19,10 +17,6 @@ export default class UmbTreeActionDataTypeDeleteElement extends UmbTreeItemActio
|
||||
this.consumeContext(UMB_MODAL_SERVICE_CONTEXT_TOKEN, (modalService) => {
|
||||
this._modalService = modalService;
|
||||
});
|
||||
|
||||
this.consumeContext(UMB_DATA_TYPE_DETAIL_STORE_CONTEXT_TOKEN, (dataTypeStore) => {
|
||||
this._dataTypeStore = dataTypeStore;
|
||||
});
|
||||
}
|
||||
|
||||
private _handleLabelClick() {
|
||||
@@ -34,10 +28,13 @@ export default class UmbTreeActionDataTypeDeleteElement extends UmbTreeItemActio
|
||||
});
|
||||
|
||||
modalHandler?.onClose().then(({ confirmed }: any) => {
|
||||
//TODO: Generally no one should talk to stores directly.
|
||||
/*
|
||||
if (confirmed && this._treeContextMenuService && this._dataTypeStore && this._activeTreeItem) {
|
||||
this._dataTypeStore?.delete([this._activeTreeItem.key]);
|
||||
this._treeContextMenuService.close();
|
||||
}
|
||||
*/
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,51 +1,95 @@
|
||||
import { UmbWorkspaceContext } from '../../../shared/components/workspace/workspace-context/workspace-context';
|
||||
import { UmbWorkspaceEntityContextInterface } from '../../../shared/components/workspace/workspace-context/workspace-entity-context.interface';
|
||||
import { UmbEntityWorkspaceManager } from '../../../shared/components/workspace/workspace-context/entity-manager-controller';
|
||||
import { UMB_DATA_TYPE_DETAIL_STORE_CONTEXT_TOKEN } from '../data-type.detail.store';
|
||||
import type { DataTypeDetails } from '@umbraco-cms/models';
|
||||
import { appendToFrozenArray } from '@umbraco-cms/observable-api';
|
||||
import { UmbDataTypeRepository } from '../repository/data-type.repository';
|
||||
import type { DataTypeModel } from '@umbraco-cms/backend-api';
|
||||
import { appendToFrozenArray, ObjectState } from '@umbraco-cms/observable-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
|
||||
export class UmbWorkspaceDataTypeContext extends UmbWorkspaceContext implements UmbWorkspaceEntityContextInterface<DataTypeDetails | undefined> {
|
||||
type EntityType = DataTypeModel;
|
||||
|
||||
#manager = new UmbEntityWorkspaceManager(this._host, 'data-type', UMB_DATA_TYPE_DETAIL_STORE_CONTEXT_TOKEN);
|
||||
export class UmbWorkspaceDataTypeContext
|
||||
extends UmbWorkspaceContext
|
||||
implements UmbWorkspaceEntityContextInterface<EntityType | undefined>
|
||||
{
|
||||
#isNew = false;
|
||||
#host: UmbControllerHostInterface;
|
||||
#dataTypeRepository: UmbDataTypeRepository;
|
||||
|
||||
#data = new ObjectState<EntityType | undefined>(undefined);
|
||||
data = this.#data.asObservable();
|
||||
name = this.#data.getObservablePart((data) => data?.name);
|
||||
key = this.#data.getObservablePart((data) => data?.key);
|
||||
|
||||
|
||||
|
||||
|
||||
public readonly data = this.#manager.state.asObservable();
|
||||
public readonly name = this.#manager.state.getObservablePart((state) => state?.name);
|
||||
|
||||
setName(name: string) {
|
||||
this.#manager.state.update({name: name});
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
super(host);
|
||||
this.#host = host;
|
||||
this.#dataTypeRepository = new UmbDataTypeRepository(this.#host);
|
||||
}
|
||||
setPropertyEditorModelAlias(alias?: string) {
|
||||
this.#manager.state.update({propertyEditorModelAlias: alias});
|
||||
}
|
||||
setPropertyEditorUIAlias(alias?: string) {
|
||||
this.#manager.state.update({propertyEditorUIAlias: alias});
|
||||
}
|
||||
getEntityType = this.#manager.getEntityType;
|
||||
getUnique = this.#manager.getEntityKey;
|
||||
getEntityKey = this.#manager.getEntityKey;
|
||||
getStore = this.#manager.getStore;
|
||||
getData = this.#manager.getData;
|
||||
load = this.#manager.load;
|
||||
create = this.#manager.create;
|
||||
save = this.#manager.save;
|
||||
destroy = this.#manager.destroy;
|
||||
|
||||
|
||||
// This could eventually be moved out as well?
|
||||
setPropertyValue(alias: string, value: unknown) {
|
||||
|
||||
const entry = {alias: alias, value: value};
|
||||
|
||||
const currentData = this.#manager.getData();
|
||||
if (currentData) {
|
||||
const newDataSet = appendToFrozenArray(currentData.data, entry, x => x.alias);
|
||||
|
||||
this.#manager.state.update({data: newDataSet});
|
||||
async load(entityKey: string) {
|
||||
const { data } = await this.#dataTypeRepository.requestByKey(entityKey);
|
||||
if (data) {
|
||||
this.#isNew = false;
|
||||
this.#data.next(data);
|
||||
}
|
||||
}
|
||||
|
||||
async createScaffold(parentKey: string | null) {
|
||||
const { data } = await this.#dataTypeRepository.createDetailsScaffold(parentKey);
|
||||
if (!data) return;
|
||||
this.#isNew = true;
|
||||
this.#data.next(data);
|
||||
}
|
||||
|
||||
getData() {
|
||||
return this.#data.getValue();
|
||||
}
|
||||
getEntityKey() {
|
||||
return this.getData()?.key || '';
|
||||
}
|
||||
getEntityType() {
|
||||
return 'data-type';
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.#data.update({ name });
|
||||
}
|
||||
|
||||
setPropertyEditorAlias(alias?: string) {
|
||||
this.#data.update({ propertyEditorAlias: alias });
|
||||
}
|
||||
setPropertyEditorUiAlias(alias?: string) {
|
||||
this.#data.update({ propertyEditorUiAlias: alias });
|
||||
}
|
||||
|
||||
// TODO: its not called a property in the model, but we do consider this way in our front-end
|
||||
setPropertyValue(alias: string, value: unknown) {
|
||||
const entry = { alias: alias, value: value };
|
||||
|
||||
const currentData = this.#data.value;
|
||||
if (currentData) {
|
||||
// TODO: make a partial update method for array of data, (idea/concept, use if this case is getting common)
|
||||
const newDataSet = appendToFrozenArray(currentData.data || [], entry, (x) => x.alias);
|
||||
this.#data.update({ data: newDataSet });
|
||||
}
|
||||
}
|
||||
|
||||
async save() {
|
||||
if (!this.#data.value) return;
|
||||
if (this.#isNew) {
|
||||
await this.#dataTypeRepository.createDetail(this.#data.value);
|
||||
} else {
|
||||
await this.#dataTypeRepository.saveDetail(this.#data.value);
|
||||
}
|
||||
// If it went well, then its not new anymore?.
|
||||
this.#isNew = false;
|
||||
}
|
||||
|
||||
async delete(key: string) {
|
||||
await this.#dataTypeRepository.delete(key);
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
this.#data.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,10 +33,11 @@ export class UmbDataTypeWorkspaceElement extends UmbLitElement {
|
||||
|
||||
public load(value: string) {
|
||||
this._workspaceContext?.load(value);
|
||||
//this._unique = entityKey;
|
||||
}
|
||||
|
||||
public create(parentKey: string | null) {
|
||||
this._workspaceContext?.create(parentKey);
|
||||
this._workspaceContext.createScaffold(parentKey);
|
||||
}
|
||||
|
||||
@state()
|
||||
@@ -45,9 +46,9 @@ export class UmbDataTypeWorkspaceElement extends UmbLitElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.provideContext('umbWorkspaceContext', this._workspaceContext);
|
||||
this.observe(this._workspaceContext.data.pipe(distinctUntilChanged()), (dataType) => {
|
||||
if (dataType && dataType.name !== this._dataTypeName) {
|
||||
this._dataTypeName = dataType.name ?? '';
|
||||
this.observe(this._workspaceContext.name, (dataTypeName) => {
|
||||
if (dataTypeName !== this._dataTypeName) {
|
||||
this._dataTypeName = dataTypeName ?? '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { customElement, state } from 'lit/decorators.js';
|
||||
import { UmbModalService, UMB_MODAL_SERVICE_CONTEXT_TOKEN } from '../../../../../../core/modal';
|
||||
import { UmbWorkspaceDataTypeContext } from '../../data-type-workspace.context';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import type { DataTypeDetails } from '@umbraco-cms/models';
|
||||
import type { DataTypeModel } from '@umbraco-cms/backend-api';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/extensions-api';
|
||||
|
||||
import '../../../../../shared/property-editors/shared/property-editor-config/property-editor-config.element';
|
||||
@@ -23,7 +23,7 @@ export class UmbDataTypeWorkspaceViewEditElement extends UmbLitElement {
|
||||
];
|
||||
|
||||
@state()
|
||||
_dataType?: DataTypeDetails;
|
||||
_dataType?: DataTypeModel;
|
||||
|
||||
@state()
|
||||
private _propertyEditorUIIcon = '';
|
||||
@@ -32,10 +32,10 @@ export class UmbDataTypeWorkspaceViewEditElement extends UmbLitElement {
|
||||
private _propertyEditorUIName = '';
|
||||
|
||||
@state()
|
||||
private _propertyEditorUIAlias = '';
|
||||
private _propertyEditorUiAlias = '';
|
||||
|
||||
@state()
|
||||
private _propertyEditorModelAlias = '';
|
||||
private _propertyEditorAlias = '';
|
||||
|
||||
@state()
|
||||
private _data: Array<any> = [];
|
||||
@@ -66,33 +66,33 @@ export class UmbDataTypeWorkspaceViewEditElement extends UmbLitElement {
|
||||
if (!dataType) return;
|
||||
|
||||
// TODO: handle if model is not of the type wanted.
|
||||
this._dataType = dataType as DataTypeDetails;
|
||||
this._dataType = dataType;
|
||||
|
||||
if (this._dataType.propertyEditorUIAlias !== this._propertyEditorUIAlias) {
|
||||
this._observePropertyEditorUI(this._dataType.propertyEditorUIAlias || undefined);
|
||||
if (this._dataType.propertyEditorUiAlias !== this._propertyEditorUiAlias) {
|
||||
this._observePropertyEditorUI(this._dataType.propertyEditorUiAlias || undefined);
|
||||
}
|
||||
|
||||
if (this._dataType.data !== this._data) {
|
||||
if (this._dataType.data && this._dataType.data !== this._data) {
|
||||
this._data = this._dataType.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _observePropertyEditorUI(propertyEditorUIAlias?: string) {
|
||||
if (!propertyEditorUIAlias) return;
|
||||
private _observePropertyEditorUI(propertyEditorUiAlias?: string) {
|
||||
if (!propertyEditorUiAlias) return;
|
||||
|
||||
this.observe(
|
||||
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUI', propertyEditorUIAlias),
|
||||
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUI', propertyEditorUiAlias),
|
||||
(propertyEditorUI) => {
|
||||
// TODO: show error. We have stored a PropertyEditorUIAlias and can't find the PropertyEditorUI in the registry.
|
||||
if (!propertyEditorUI) return;
|
||||
|
||||
this._propertyEditorUIName = propertyEditorUI?.meta.label ?? propertyEditorUI?.name ?? '';
|
||||
this._propertyEditorUIAlias = propertyEditorUI?.alias ?? '';
|
||||
this._propertyEditorUiAlias = propertyEditorUI?.alias ?? '';
|
||||
this._propertyEditorUIIcon = propertyEditorUI?.meta.icon ?? '';
|
||||
this._propertyEditorModelAlias = propertyEditorUI?.meta.propertyEditorModel ?? '';
|
||||
this._propertyEditorAlias = propertyEditorUI?.meta.propertyEditorModel ?? '';
|
||||
|
||||
this._workspaceContext?.setPropertyEditorModelAlias(this._propertyEditorModelAlias);
|
||||
this._workspaceContext?.setPropertyEditorAlias(this._propertyEditorAlias);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -101,7 +101,7 @@ export class UmbDataTypeWorkspaceViewEditElement extends UmbLitElement {
|
||||
if (!this._dataType) return;
|
||||
|
||||
const modalHandler = this._modalService?.propertyEditorUIPicker({
|
||||
selection: this._propertyEditorUIAlias ? [this._propertyEditorUIAlias] : [],
|
||||
selection: this._propertyEditorUiAlias ? [this._propertyEditorUiAlias] : [],
|
||||
});
|
||||
|
||||
modalHandler?.onClose().then(({ selection } = {}) => {
|
||||
@@ -110,10 +110,10 @@ export class UmbDataTypeWorkspaceViewEditElement extends UmbLitElement {
|
||||
});
|
||||
}
|
||||
|
||||
private _selectPropertyEditorUI(propertyEditorUIAlias: string | undefined) {
|
||||
if (!this._dataType || this._dataType.propertyEditorUIAlias === propertyEditorUIAlias) return;
|
||||
this._workspaceContext?.setPropertyEditorUIAlias(propertyEditorUIAlias);
|
||||
this._observePropertyEditorUI(propertyEditorUIAlias);
|
||||
private _selectPropertyEditorUI(propertyEditorUiAlias: string | undefined) {
|
||||
if (!this._dataType || this._dataType.propertyEditorUiAlias === propertyEditorUiAlias) return;
|
||||
this._workspaceContext?.setPropertyEditorUiAlias(propertyEditorUiAlias);
|
||||
this._observePropertyEditorUI(propertyEditorUiAlias);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -126,14 +126,14 @@ export class UmbDataTypeWorkspaceViewEditElement extends UmbLitElement {
|
||||
private _renderPropertyEditorUI() {
|
||||
return html`
|
||||
<umb-workspace-property-layout label="Property Editor" description="Select a property editor">
|
||||
${this._propertyEditorUIAlias
|
||||
${this._propertyEditorUiAlias
|
||||
? html`
|
||||
<!-- TODO: border is a bit weird attribute name. Maybe single or standalone would be better? -->
|
||||
<umb-ref-property-editor-ui
|
||||
slot="editor"
|
||||
name=${this._propertyEditorUIName}
|
||||
alias=${this._propertyEditorUIAlias}
|
||||
property-editor-model-alias=${this._propertyEditorModelAlias}
|
||||
alias=${this._propertyEditorUiAlias}
|
||||
property-editor-model-alias=${this._propertyEditorAlias}
|
||||
border>
|
||||
<uui-icon name="${this._propertyEditorUIIcon}" slot="icon"></uui-icon>
|
||||
<uui-action-bar slot="actions">
|
||||
@@ -155,11 +155,11 @@ export class UmbDataTypeWorkspaceViewEditElement extends UmbLitElement {
|
||||
|
||||
private _renderConfig() {
|
||||
return html`
|
||||
${this._propertyEditorModelAlias && this._propertyEditorUIAlias
|
||||
${this._propertyEditorAlias && this._propertyEditorUiAlias
|
||||
? html`
|
||||
<uui-box headline="Config">
|
||||
<umb-property-editor-config
|
||||
property-editor-ui-alias="${this._propertyEditorUIAlias}"
|
||||
property-editor-ui-alias="${this._propertyEditorUiAlias}"
|
||||
.data="${this._data}"></umb-property-editor-config>
|
||||
</uui-box>
|
||||
`
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { css, html } from 'lit';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { distinctUntilChanged } from 'rxjs';
|
||||
import { UmbWorkspaceDataTypeContext } from '../../data-type-workspace.context';
|
||||
import type { DataTypeDetails } from '@umbraco-cms/models';
|
||||
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import { DataTypeModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
@customElement('umb-workspace-view-data-type-info')
|
||||
export class UmbWorkspaceViewDataTypeInfoElement extends UmbLitElement {
|
||||
static styles = [UUITextStyles, css``];
|
||||
|
||||
@state()
|
||||
_dataType?: DataTypeDetails;
|
||||
_dataType?: DataTypeModel;
|
||||
|
||||
private _workspaceContext?: UmbWorkspaceDataTypeContext;
|
||||
|
||||
@@ -28,12 +28,9 @@ export class UmbWorkspaceViewDataTypeInfoElement extends UmbLitElement {
|
||||
private _observeDataType() {
|
||||
if (!this._workspaceContext) return;
|
||||
|
||||
this.observe(this._workspaceContext.data.pipe(distinctUntilChanged()), (dataType) => {
|
||||
this.observe(this._workspaceContext.data, (dataType) => {
|
||||
if (!dataType) return;
|
||||
|
||||
// TODO: handle if model is not of the type wanted.
|
||||
// TODO: Make method to identify wether data is of type DataTypeDetails
|
||||
this._dataType = dataType as DataTypeDetails;
|
||||
this._dataType = dataType;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -48,11 +45,11 @@ export class UmbWorkspaceViewDataTypeInfoElement extends UmbLitElement {
|
||||
<div slot="editor">${this._dataType?.key}</div>
|
||||
</umb-workspace-property-layout>
|
||||
<umb-workspace-property-layout label="Property Editor Alias">
|
||||
<div slot="editor">${this._dataType?.propertyEditorModelAlias}</div>
|
||||
<div slot="editor">${this._dataType?.propertyEditorAlias}</div>
|
||||
</umb-workspace-property-layout>
|
||||
|
||||
<umb-workspace-property-layout label="Property Editor UI Alias">
|
||||
<div slot="editor">${this._dataType?.propertyEditorUIAlias}</div>
|
||||
<div slot="editor">${this._dataType?.propertyEditorUiAlias}</div>
|
||||
</umb-workspace-property-layout>
|
||||
</uui-box>
|
||||
`;
|
||||
|
||||
@@ -73,10 +73,11 @@ export class UmbLanguageStore extends UmbStoreBase {
|
||||
}
|
||||
|
||||
async delete(isoCodes: Array<string>) {
|
||||
// TODO: revisit this. It looks a bit weird with the nested tryExecuteAndNotify
|
||||
const queue = isoCodes.map((isoCode) =>
|
||||
tryExecuteAndNotify(
|
||||
this._host,
|
||||
LanguageResource.deleteLanguageByIsoCode({ isoCode }).then(() => isoCode)
|
||||
tryExecuteAndNotify(this._host, LanguageResource.deleteLanguageByIsoCode({ isoCode })).then(() => isoCode)
|
||||
)
|
||||
);
|
||||
const results = await Promise.all(queue);
|
||||
|
||||
@@ -2,11 +2,8 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { css, html } from 'lit';
|
||||
import { ifDefined } from 'lit-html/directives/if-defined.js';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
|
||||
import { UMB_DATA_TYPE_DETAIL_STORE_CONTEXT_TOKEN } from '../../../settings/data-types/data-type.detail.store';
|
||||
import type { UmbDataTypeDetailStore } from '../../../settings/data-types/data-type.detail.store';
|
||||
import type { ContentProperty, DataTypeDetails, DataTypePropertyData } from '@umbraco-cms/models';
|
||||
|
||||
import { UmbDataTypeRepository } from '../../../settings/data-types/repository/data-type.repository';
|
||||
import type { DataTypeModel, DataTypePropertyModel, DocumentTypePropertyTypeModel } from '@umbraco-cms/backend-api';
|
||||
import '../workspace-property/workspace-property.element';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import { UmbObserverController } from '@umbraco-cms/observable-api';
|
||||
@@ -23,12 +20,13 @@ export class UmbContentPropertyElement extends UmbLitElement {
|
||||
];
|
||||
|
||||
// TODO: Consider if we just need to get the DataType Key?..
|
||||
private _property?: ContentProperty;
|
||||
// TODO: consider if we should make a base type of the DocumentTypePropertyType, which could become the ContentProperty. A shared common type for all properties.
|
||||
private _property?: DocumentTypePropertyTypeModel;
|
||||
@property({ type: Object, attribute: false })
|
||||
public get property(): ContentProperty | undefined {
|
||||
public get property(): DocumentTypePropertyTypeModel | undefined {
|
||||
return this._property;
|
||||
}
|
||||
public set property(value: ContentProperty | undefined) {
|
||||
public set property(value: DocumentTypePropertyTypeModel | undefined) {
|
||||
const oldProperty = this._property;
|
||||
this._property = value;
|
||||
if (this._property?.dataTypeKey !== oldProperty?.dataTypeKey) {
|
||||
@@ -40,31 +38,22 @@ export class UmbContentPropertyElement extends UmbLitElement {
|
||||
value?: object | string;
|
||||
|
||||
@state()
|
||||
private _propertyEditorUIAlias?: string;
|
||||
private _propertyEditorUiAlias?: string;
|
||||
|
||||
@state()
|
||||
private _dataTypeData: DataTypePropertyData[] = [];
|
||||
private _dataTypeData: DataTypePropertyModel[] = [];
|
||||
|
||||
private _dataTypeStore?: UmbDataTypeDetailStore;
|
||||
private _dataTypeObserver?: UmbObserverController<DataTypeDetails | null>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.consumeContext(UMB_DATA_TYPE_DETAIL_STORE_CONTEXT_TOKEN, (instance) => {
|
||||
this._dataTypeStore = instance;
|
||||
this._observeDataType(this._property?.dataTypeKey);
|
||||
});
|
||||
}
|
||||
|
||||
private _observeDataType(dataTypeKey?: string) {
|
||||
if (!this._dataTypeStore) return;
|
||||
private _dataTypeRepository: UmbDataTypeRepository = new UmbDataTypeRepository(this);
|
||||
private _dataTypeObserver?: UmbObserverController<DataTypeModel | null>;
|
||||
|
||||
private async _observeDataType(dataTypeKey?: string) {
|
||||
this._dataTypeObserver?.destroy();
|
||||
if (dataTypeKey) {
|
||||
this._dataTypeObserver = this.observe(this._dataTypeStore.getByKey(dataTypeKey), (dataType) => {
|
||||
// We do not need to have await here, this is only to ensure that the data is loaded before we try to observe it, and thereby update the DOM with it.
|
||||
await this._dataTypeRepository.requestByKey(dataTypeKey);
|
||||
this._dataTypeObserver = this.observe(await this._dataTypeRepository.byKey(dataTypeKey), (dataType) => {
|
||||
this._dataTypeData = dataType?.data || [];
|
||||
this._propertyEditorUIAlias = dataType?.propertyEditorUIAlias || undefined;
|
||||
this._propertyEditorUiAlias = dataType?.propertyEditorUiAlias || undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -72,9 +61,9 @@ export class UmbContentPropertyElement extends UmbLitElement {
|
||||
render() {
|
||||
return html`<umb-workspace-property
|
||||
alias=${ifDefined(this._property?.alias)}
|
||||
label=${ifDefined(this._property?.label)}
|
||||
description=${ifDefined(this._property?.description)}
|
||||
property-editor-ui-alias="${ifDefined(this._propertyEditorUIAlias)}"
|
||||
label=${ifDefined(this._property?.name)}
|
||||
description=${ifDefined(this._property?.description || undefined)}
|
||||
property-editor-ui-alias=${ifDefined(this._propertyEditorUiAlias)}
|
||||
.value=${this.value}
|
||||
.config=${this._dataTypeData}></umb-workspace-property>`;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export class UmbRefPropertyEditorUIElement extends UUIRefNodeElement {
|
||||
* @default ''
|
||||
*/
|
||||
@property({ type: String, attribute: 'property-editor-model-alias' })
|
||||
propertyEditorModelAlias = '';
|
||||
propertyEditorAlias = '';
|
||||
|
||||
protected renderDetail() {
|
||||
const details: string[] = [];
|
||||
@@ -39,8 +39,8 @@ export class UmbRefPropertyEditorUIElement extends UUIRefNodeElement {
|
||||
details.push(this.alias);
|
||||
}
|
||||
|
||||
if (this.propertyEditorModelAlias !== '') {
|
||||
details.push(this.propertyEditorModelAlias);
|
||||
if (this.propertyEditorAlias !== '') {
|
||||
details.push(this.propertyEditorAlias);
|
||||
} else {
|
||||
details.push('Property Editor Missing');
|
||||
}
|
||||
|
||||
@@ -50,23 +50,23 @@ export class UmbVariantSelectorElement extends UmbLitElement {
|
||||
super();
|
||||
|
||||
// TODO: Figure out how to get the magic string for the workspace context.
|
||||
this.consumeContext<UmbWorkspaceEntityContextInterface<ContentTreeItemModel>>(
|
||||
'umbWorkspaceContext',
|
||||
(instance) => {
|
||||
this._workspaceContext = instance;
|
||||
this._observeWorkspace();
|
||||
}
|
||||
);
|
||||
this.consumeContext<UmbWorkspaceEntityContextInterface<ContentTreeItemModel>>('umbWorkspaceContext', (instance) => {
|
||||
this._workspaceContext = instance;
|
||||
this._observeWorkspace();
|
||||
});
|
||||
}
|
||||
|
||||
private async _observeWorkspace() {
|
||||
if (!this._workspaceContext) return;
|
||||
|
||||
/*
|
||||
// TODO: update this with nre repository and document types.
|
||||
this.observe(this._workspaceContext.data, (data) => {
|
||||
if(data) {
|
||||
this._content = data;
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO. find a way where we don't have to do this for all workspaces.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UmbWorkspaceEntityContextInterface } from '../workspace/workspace-context/workspace-entity-context.interface';
|
||||
import type { DataTypeDetails } from '@umbraco-cms/models';
|
||||
import type { DataTypeModel } from '@umbraco-cms/backend-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
import { ObjectState } from '@umbraco-cms/observable-api';
|
||||
import { UmbContextConsumerController, UmbContextProviderController } from '@umbraco-cms/context-api';
|
||||
@@ -10,7 +10,7 @@ export type WorkspacePropertyData<ValueType> = {
|
||||
label?: string;
|
||||
description?: string;
|
||||
value?: ValueType | null;
|
||||
config?: DataTypeDetails['data']; // This could potentially then come from hardcoded JS object and not the DataType store.
|
||||
config?: DataTypeModel['data']; // This could potentially then come from hardcoded JS object and not the DataType store.
|
||||
};
|
||||
|
||||
export class UmbWorkspacePropertyContext<ValueType = unknown> {
|
||||
@@ -28,9 +28,13 @@ export class UmbWorkspacePropertyContext<ValueType = unknown> {
|
||||
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
// TODO: Figure out how to get the magic string in a better way.
|
||||
new UmbContextConsumerController<UmbWorkspaceEntityContextInterface>(host, 'umbWorkspaceContext', (workspaceContext) => {
|
||||
this._workspaceContext = workspaceContext;
|
||||
});
|
||||
new UmbContextConsumerController<UmbWorkspaceEntityContextInterface>(
|
||||
host,
|
||||
'umbWorkspaceContext',
|
||||
(workspaceContext) => {
|
||||
this._workspaceContext = workspaceContext;
|
||||
}
|
||||
);
|
||||
|
||||
this._providerController = new UmbContextProviderController(host, 'umbPropertyContext', this);
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@ import { css, html } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { ifDefined } from 'lit-html/directives/if-defined.js';
|
||||
import { UmbWorkspacePropertyContext } from './workspace-property.context';
|
||||
import { createExtensionElement , umbExtensionsRegistry } from '@umbraco-cms/extensions-api';
|
||||
import type { DataTypePropertyData, ManifestPropertyEditorUI, ManifestTypes } from '@umbraco-cms/models';
|
||||
import { createExtensionElement, umbExtensionsRegistry } from '@umbraco-cms/extensions-api';
|
||||
import type { ManifestPropertyEditorUI, ManifestTypes } from '@umbraco-cms/models';
|
||||
|
||||
import '../../property-actions/shared/property-action-menu/property-action-menu.element';
|
||||
import '../../../../backoffice/shared/components/workspace/workspace-property-layout/workspace-property-layout.element';
|
||||
import { UmbObserverController } from '@umbraco-cms/observable-api';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import { DataTypePropertyModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
/**
|
||||
* @element umb-workspace-property
|
||||
@@ -94,11 +95,11 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
||||
* @attr
|
||||
* @default ''
|
||||
*/
|
||||
private _propertyEditorUIAlias = '';
|
||||
private _propertyEditorUiAlias = '';
|
||||
@property({ type: String, attribute: 'property-editor-ui-alias' })
|
||||
public set propertyEditorUIAlias(value: string) {
|
||||
if (this._propertyEditorUIAlias === value) return;
|
||||
this._propertyEditorUIAlias = value;
|
||||
public set propertyEditorUiAlias(value: string) {
|
||||
if (this._propertyEditorUiAlias === value) return;
|
||||
this._propertyEditorUiAlias = value;
|
||||
this._observePropertyEditorUI();
|
||||
}
|
||||
|
||||
@@ -122,7 +123,7 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
||||
* @default ''
|
||||
*/
|
||||
@property({ type: Object, attribute: false })
|
||||
public set config(value: DataTypePropertyData[]) {
|
||||
public set config(value: DataTypePropertyModel[]) {
|
||||
this._propertyContext.setConfig(value);
|
||||
}
|
||||
|
||||
@@ -158,7 +159,7 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
||||
private _observePropertyEditorUI() {
|
||||
this.propertyEditorUIObserver?.destroy();
|
||||
this.propertyEditorUIObserver = this.observe(
|
||||
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUI', this._propertyEditorUIAlias),
|
||||
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUI', this._propertyEditorUiAlias),
|
||||
(manifest) => {
|
||||
this._gotEditorUI(manifest);
|
||||
}
|
||||
@@ -167,7 +168,7 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
||||
|
||||
private _gotEditorUI(manifest?: ManifestPropertyEditorUI | null) {
|
||||
if (!manifest) {
|
||||
// TODO: if propertyEditorUIAlias didn't exist in store, we should do some nice fail UI.
|
||||
// TODO: if propertyEditorUiAlias didn't exist in store, we should do some nice fail UI.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -217,11 +218,11 @@ export class UmbWorkspacePropertyElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
private _renderPropertyActionMenu() {
|
||||
return html`${this._propertyEditorUIAlias
|
||||
return html`${this._propertyEditorUiAlias
|
||||
? html`<umb-property-action-menu
|
||||
slot="property-action-menu"
|
||||
id="property-action-menu"
|
||||
.propertyEditorUIAlias="${this._propertyEditorUIAlias}"
|
||||
.propertyEditorUiAlias="${this._propertyEditorUiAlias}"
|
||||
.value="${this.value}"></umb-property-action-menu>`
|
||||
: ''}`;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
UMB_COLLECTION_CONTEXT_TOKEN,
|
||||
} from '../../../../../../shared/collection/collection.context';
|
||||
|
||||
import '../../../../../../shared/components/content-property/content-property.element';
|
||||
import '../../../../../../shared/collection/dashboards/dashboard-collection.element';
|
||||
import type { UmbWorkspaceEntityContextInterface } from '../../../workspace-context/workspace-entity-context.interface';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
|
||||
@@ -3,9 +3,8 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
import type { UmbWorkspaceEntityContextInterface } from '../../../workspace-context/workspace-entity-context.interface';
|
||||
import type { ContentProperty, ContentPropertyData, DocumentDetails, MediaDetails } from '@umbraco-cms/models';
|
||||
import type { ContentProperty, ContentPropertyData, MediaTypeDetails } from '@umbraco-cms/models';
|
||||
|
||||
import '../../../../content-property/content-property.element';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
|
||||
@customElement('umb-workspace-view-content-edit')
|
||||
@@ -26,17 +25,16 @@ export class UmbWorkspaceViewContentEditElement extends UmbLitElement {
|
||||
@state()
|
||||
_data: ContentPropertyData[] = [];
|
||||
|
||||
private _workspaceContext?: UmbWorkspaceEntityContextInterface<DocumentDetails | MediaDetails>;
|
||||
private _workspaceContext?: UmbWorkspaceEntityContextInterface<MediaTypeDetails>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// TODO: Figure out how to get the magic string for the workspace context.
|
||||
this.consumeContext<UmbWorkspaceEntityContextInterface<DocumentDetails | MediaDetails>>(
|
||||
this.consumeContext<UmbWorkspaceEntityContextInterface<MediaTypeDetails>>(
|
||||
'umbWorkspaceContext',
|
||||
(workspaceContext) => {
|
||||
this._workspaceContext = workspaceContext;
|
||||
console.log("workspaceContext", workspaceContext)
|
||||
this._observeContent();
|
||||
}
|
||||
);
|
||||
@@ -52,17 +50,22 @@ export class UmbWorkspaceViewContentEditElement extends UmbLitElement {
|
||||
|
||||
Should use a Observable for example: this._workspaceContext.properties
|
||||
*/
|
||||
this.observe(this._workspaceContext.data, (content) => {
|
||||
|
||||
this._properties = content?.properties || [];
|
||||
this._data = content?.data || [];
|
||||
console.log("content", content)
|
||||
/*
|
||||
// TODO: broken for now, as we need to transfer into the repository way:
|
||||
this.observe(
|
||||
this._workspaceContext.data,
|
||||
(content) => {
|
||||
// TODO: Should be adapted to new models, maybe a shared 'Content' solution is not the right thing here.
|
||||
this._properties = content?.properties || [];
|
||||
console.log('content', content);
|
||||
|
||||
/*
|
||||
Maybe we should not give the value(Data), but the umb-content-property should get the context and observe its own data.
|
||||
This would become a more specific Observer therefor better performance?.. Note to self: Debate with Mads how he sees this perspective.
|
||||
*/
|
||||
}, 'observeWorkspaceContextData');
|
||||
//Maybe we should not give the value(Data), but the umb-content-property should get the context and observe its own data.
|
||||
//This would become a more specific Observer therefor better performance?.. Note to self: Debate with Mads how he sees this perspective.
|
||||
},
|
||||
'observeWorkspaceContextData'
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -72,9 +75,7 @@ export class UmbWorkspaceViewContentEditElement extends UmbLitElement {
|
||||
this._properties,
|
||||
(property) => property.alias,
|
||||
(property) =>
|
||||
html`<umb-content-property
|
||||
.property=${property}
|
||||
.value=${this._data.find((data) => data.alias === property.alias)?.value}></umb-content-property> `
|
||||
html`<umb-content-property .property=${property} .value=${property.label}></umb-content-property> `
|
||||
)}
|
||||
</uui-box>
|
||||
`;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { css, html } from 'lit';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { UmbWorkspaceEntityContextInterface } from '../../../workspace-context/workspace-entity-context.interface';
|
||||
import type { DocumentDetails, MediaDetails } from '@umbraco-cms/models';
|
||||
import type { DocumentModel } from '@umbraco-cms/backend-api';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
|
||||
@customElement('umb-workspace-view-content-info')
|
||||
@@ -20,27 +20,27 @@ export class UmbWorkspaceViewContentInfoElement extends UmbLitElement {
|
||||
@state()
|
||||
private _nodeName = '';
|
||||
|
||||
private _workspaceContext?: UmbWorkspaceEntityContextInterface<DocumentDetails | MediaDetails>;
|
||||
private _workspaceContext?: UmbWorkspaceEntityContextInterface<DocumentModel>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// TODO: Figure out how to get the magic string for the workspace context.
|
||||
this.consumeContext<UmbWorkspaceEntityContextInterface<DocumentDetails | MediaDetails>>(
|
||||
'umbWorkspaceContext',
|
||||
(nodeContext) => {
|
||||
this._workspaceContext = nodeContext;
|
||||
this._observeContent();
|
||||
}
|
||||
);
|
||||
this.consumeContext<UmbWorkspaceEntityContextInterface<DocumentModel>>('umbWorkspaceContext', (nodeContext) => {
|
||||
this._workspaceContext = nodeContext;
|
||||
this._observeContent();
|
||||
});
|
||||
}
|
||||
|
||||
private _observeContent() {
|
||||
if (!this._workspaceContext) return;
|
||||
|
||||
this._nodeName = 'TBD, with variants this is not as simple.';
|
||||
/*
|
||||
this.observe(this._workspaceContext.name, (name) => {
|
||||
this._nodeName = name || '';
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import type { Observable } from "rxjs";
|
||||
|
||||
export interface UmbWorkspaceContextInterface<T = unknown> {
|
||||
|
||||
readonly data: Observable<T>;
|
||||
|
||||
|
||||
//readonly data: Observable<T>;
|
||||
//getUnique(): string | undefined;
|
||||
|
||||
getEntityType(): string;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { Observable } from 'rxjs';
|
||||
import { UmbWorkspaceContextInterface } from './workspace-context.interface';
|
||||
|
||||
export interface UmbWorkspaceEntityContextInterface<T = unknown> extends UmbWorkspaceContextInterface<T> {
|
||||
readonly name: Observable<string | undefined>;
|
||||
//readonly name: Observable<string | undefined>;
|
||||
|
||||
getEntityKey(): string | undefined; // COnsider if this should go away now that we have getUnique()
|
||||
getEntityType(): string;
|
||||
|
||||
@@ -46,7 +46,7 @@ export class UmbPropertyActionMenuElement extends UmbLitElement {
|
||||
public value?: string;
|
||||
|
||||
@property()
|
||||
set propertyEditorUIAlias(alias: string) {
|
||||
set propertyEditorUiAlias(alias: string) {
|
||||
this._observeActions(alias);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,15 +22,15 @@ export class UmbPropertyEditorConfigElement extends UmbLitElement {
|
||||
* @attr
|
||||
* @default ''
|
||||
*/
|
||||
private _propertyEditorUIAlias = '';
|
||||
private _propertyEditorUiAlias = '';
|
||||
@property({ type: String, attribute: 'property-editor-ui-alias' })
|
||||
public get propertyEditorUIAlias(): string {
|
||||
return this._propertyEditorUIAlias;
|
||||
public get propertyEditorUiAlias(): string {
|
||||
return this._propertyEditorUiAlias;
|
||||
}
|
||||
public set propertyEditorUIAlias(value: string) {
|
||||
const oldVal = this._propertyEditorUIAlias;
|
||||
this._propertyEditorUIAlias = value;
|
||||
this.requestUpdate('propertyEditorUIAlias', oldVal);
|
||||
public set propertyEditorUiAlias(value: string) {
|
||||
const oldVal = this._propertyEditorUiAlias;
|
||||
this._propertyEditorUiAlias = value;
|
||||
this.requestUpdate('propertyEditorUiAlias', oldVal);
|
||||
this._observePropertyEditorUIConfig();
|
||||
}
|
||||
|
||||
@@ -56,10 +56,10 @@ export class UmbPropertyEditorConfigElement extends UmbLitElement {
|
||||
private _propertyEditorUIConfigProperties: Array<PropertyEditorConfigProperty> = [];
|
||||
|
||||
private _observePropertyEditorUIConfig() {
|
||||
if (!this._propertyEditorUIAlias) return;
|
||||
if (!this._propertyEditorUiAlias) return;
|
||||
|
||||
this.observe(
|
||||
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUI', this.propertyEditorUIAlias),
|
||||
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorUI', this.propertyEditorUiAlias),
|
||||
(manifest) => {
|
||||
this._observePropertyEditorModelConfig(manifest?.meta.propertyEditorModel);
|
||||
this._propertyEditorUIConfigProperties = manifest?.meta.config?.properties || [];
|
||||
@@ -70,18 +70,15 @@ export class UmbPropertyEditorConfigElement extends UmbLitElement {
|
||||
);
|
||||
}
|
||||
|
||||
private _observePropertyEditorModelConfig(propertyEditorModelAlias?: string) {
|
||||
if (!propertyEditorModelAlias) return;
|
||||
private _observePropertyEditorModelConfig(propertyEditorAlias?: string) {
|
||||
if (!propertyEditorAlias) return;
|
||||
|
||||
this.observe(
|
||||
umbExtensionsRegistry.getByTypeAndAlias('propertyEditorModel', propertyEditorModelAlias),
|
||||
(manifest) => {
|
||||
this._propertyEditorModelConfigProperties = manifest?.meta.config?.properties || [];
|
||||
this._propertyEditorModelConfigDefaultData = manifest?.meta.config?.defaultData || [];
|
||||
this._mergeConfigProperties();
|
||||
this._mergeConfigDefaultData();
|
||||
}
|
||||
);
|
||||
this.observe(umbExtensionsRegistry.getByTypeAndAlias('propertyEditorModel', propertyEditorAlias), (manifest) => {
|
||||
this._propertyEditorModelConfigProperties = manifest?.meta.config?.properties || [];
|
||||
this._propertyEditorModelConfigDefaultData = manifest?.meta.config?.defaultData || [];
|
||||
this._mergeConfigProperties();
|
||||
this._mergeConfigDefaultData();
|
||||
});
|
||||
}
|
||||
|
||||
private _mergeConfigProperties() {
|
||||
|
||||
@@ -2,9 +2,9 @@ import { html } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import '../../../components/input-checkbox-list/input-checkbox-list.element';
|
||||
import { UmbInputCheckboxListElement } from '../../../components/input-checkbox-list/input-checkbox-list.element';
|
||||
import type { UmbInputCheckboxListElement } from '../../../components/input-checkbox-list/input-checkbox-list.element';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import type { DataTypePropertyData } from '@umbraco-cms/models';
|
||||
import type { DataTypePropertyModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
/**
|
||||
* @element umb-property-editor-ui-checkbox-list
|
||||
@@ -23,7 +23,7 @@ export class UmbPropertyEditorUICheckboxListElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
@property({ type: Array, attribute: false })
|
||||
public set config(config: Array<DataTypePropertyData>) {
|
||||
public set config(config: Array<DataTypePropertyModel>) {
|
||||
const listData = config.find((x) => x.alias === 'itemList');
|
||||
|
||||
if (!listData) return;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { html } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { ifDefined } from 'lit/directives/if-defined';
|
||||
import { UUIColorSwatchesEvent } from '@umbraco-ui/uui';
|
||||
import '../../../../shared/components/color-picker/color-picker.element';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import type { DataTypePropertyData } from '@umbraco-cms/models';
|
||||
import type { UmbColorPickerElement } from 'src/backoffice/shared/components/color-picker/color-picker.element';
|
||||
import type { DataTypePropertyModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
/**
|
||||
* @element umb-property-editor-ui-color-picker
|
||||
@@ -24,7 +23,7 @@ export class UmbPropertyEditorUIColorPickerElement extends UmbLitElement {
|
||||
private _colorSwatches: string[] = [];
|
||||
|
||||
@property({ type: Array, attribute: false })
|
||||
public set config(config: Array<DataTypePropertyData>) {
|
||||
public set config(config: Array<DataTypePropertyModel>) {
|
||||
const includeLabels = config.find((x) => x.alias === 'includeLabels');
|
||||
if (includeLabels) this._includeLabels = includeLabels.value;
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { html } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { UmbInputDocumentPickerElement } from '../../../components/input-document-picker/input-document-picker.element';
|
||||
import type { UmbInputDocumentPickerElement } from '../../../components/input-document-picker/input-document-picker.element';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import type { DataTypePropertyData } from '@umbraco-cms/models';
|
||||
import '../../../components/input-document-picker/input-document-picker.element';
|
||||
import type { DataTypePropertyModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
@customElement('umb-property-editor-ui-document-picker')
|
||||
export class UmbPropertyEditorUIContentPickerElement extends UmbLitElement {
|
||||
@@ -17,7 +18,7 @@ export class UmbPropertyEditorUIContentPickerElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
@property({ type: Array, attribute: false })
|
||||
public set config(config: Array<DataTypePropertyData>) {
|
||||
public set config(config: Array<DataTypePropertyModel>) {
|
||||
const validationLimit = config.find((x) => x.alias === 'validationLimit');
|
||||
|
||||
this._limitMin = (validationLimit?.value as any).min;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { UUIColorPickerChangeEvent } from '@umbraco-ui/uui';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import '../../../components/eye-dropper/eye-dropper.element';
|
||||
import type { DataTypePropertyData } from '@umbraco-cms/models';
|
||||
import type { DataTypePropertyModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
/**
|
||||
* @element umb-property-editor-ui-eye-dropper
|
||||
@@ -23,7 +23,7 @@ export class UmbPropertyEditorUIEyeDropperElement extends UmbLitElement {
|
||||
private _swatches: string[] = [];
|
||||
|
||||
@property({ type: Array, attribute: false })
|
||||
public set config(config: Array<DataTypePropertyData>) {
|
||||
public set config(config: Array<DataTypePropertyModel>) {
|
||||
const showAlpha = config.find((x) => x.alias === 'showAlpha');
|
||||
if (showAlpha) this._opacity = showAlpha.value;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { html } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { UmbInputMediaPickerElement } from '../../../../../backoffice/shared/components/input-media-picker/input-media-picker.element';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import type { DataTypePropertyData } from '@umbraco-cms/models';
|
||||
import type { DataTypePropertyModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
/**
|
||||
* @element umb-property-editor-ui-media-picker
|
||||
@@ -20,7 +20,7 @@ export class UmbPropertyEditorUIMediaPickerElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
@property({ type: Array, attribute: false })
|
||||
public set config(config: Array<DataTypePropertyData>) {
|
||||
public set config(config: Array<DataTypePropertyModel>) {
|
||||
const validationLimit = config.find((x) => x.alias === 'validationLimit');
|
||||
if (!validationLimit) return;
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import UmbInputMultipleTextStringItemElement from '../input-multiple-text-string
|
||||
import { UmbInputEvent, UmbChangeEvent, UmbDeleteEvent } from '../../../../../../core/events';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
|
||||
import '../input-multiple-text-string-item/input-multiple-text-string-item.element';
|
||||
|
||||
export type MultipleTextStringValue = Array<MultipleTextStringValueItem>;
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import UmbInputMultipleTextStringElement, {
|
||||
import { UmbChangeEvent } from 'src/core/events/change.event';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
|
||||
import './input-multiple-text-string/input-multiple-text-string.element';
|
||||
|
||||
export type MultipleTextStringConfigData = Array<{
|
||||
alias: 'minNumber' | 'maxNumber';
|
||||
|
||||
@@ -122,7 +122,7 @@ export class UmbTemplateRepository implements UmbTreeRepository, UmbDetailReposi
|
||||
return this.#detailDataSource.createScaffold();
|
||||
}
|
||||
|
||||
async requestDetails(key: string) {
|
||||
async requestByKey(key: string) {
|
||||
await this.#init;
|
||||
|
||||
// TODO: should we show a notification if the key is missing?
|
||||
|
||||
@@ -39,7 +39,7 @@ export class UmbTemplateDetailServerDataSource implements TemplateDetailDataSour
|
||||
* @memberof UmbTemplateDetailServerDataSource
|
||||
*/
|
||||
async createScaffold() {
|
||||
let error = undefined;
|
||||
const error = undefined;
|
||||
const data: TemplateModel = {
|
||||
key: uuid(),
|
||||
name: '',
|
||||
@@ -47,13 +47,17 @@ export class UmbTemplateDetailServerDataSource implements TemplateDetailDataSour
|
||||
content: '',
|
||||
};
|
||||
|
||||
// TODO: update when backend is updated so we don't have to do two calls
|
||||
/*
|
||||
// TODO: Revisit template models, masterTemplateAlias is not here anymore?
|
||||
const { data: scaffoldData, error: scaffoldError } = await tryExecuteAndNotify(
|
||||
this.#host,
|
||||
TemplateResource.getTemplateScaffold()
|
||||
);
|
||||
*/
|
||||
|
||||
error = scaffoldError;
|
||||
data.content = scaffoldData?.content || '';
|
||||
//error = scaffoldError;
|
||||
//data.content = scaffoldData?.content || '';
|
||||
|
||||
return { data, error };
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ export class UmbUserGroupWorkspaceElement extends UmbLitElement implements UmbWo
|
||||
this._observeUsers();
|
||||
});
|
||||
|
||||
this.observe(this._workspaceContext.data.pipe(distinctUntilChanged()), (userGroup) => {
|
||||
this.observe(this._workspaceContext.data, (userGroup) => {
|
||||
this._userGroup = userGroup;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -15,22 +15,18 @@ export const UMB_USER_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbUserStore>('U
|
||||
* @description - Data Store for Users
|
||||
*/
|
||||
export class UmbUserStore extends UmbStoreBase implements UmbEntityDetailStore<UserDetails> {
|
||||
|
||||
|
||||
#users = new ArrayState<UserDetails>([], x => x.key);
|
||||
#users = new ArrayState<UserDetails>([], (x) => x.key);
|
||||
public users = this.#users.asObservable();
|
||||
|
||||
#totalUsers = new NumberState(0);
|
||||
public readonly totalUsers = this.#totalUsers.asObservable();
|
||||
|
||||
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
super(host, UMB_USER_STORE_CONTEXT_TOKEN.toString());
|
||||
}
|
||||
|
||||
|
||||
getScaffold(entityType: string, parentKey: string | null) {
|
||||
return {
|
||||
return {
|
||||
key: '',
|
||||
name: '',
|
||||
icon: '',
|
||||
@@ -49,7 +45,6 @@ export class UmbUserStore extends UmbStoreBase implements UmbEntityDetailStore<U
|
||||
} as UserDetails;
|
||||
}
|
||||
|
||||
|
||||
getAll() {
|
||||
// TODO: use Fetcher API.
|
||||
// TODO: only fetch if the data type is not in the store?
|
||||
@@ -66,7 +61,7 @@ export class UmbUserStore extends UmbStoreBase implements UmbEntityDetailStore<U
|
||||
/**
|
||||
* @description - Request a User by key. The User is added to the store and is returned as an Observable.
|
||||
* @param {string} key
|
||||
* @return {*} {(Observable<DataTypeDetails | null>)}
|
||||
* @return {*} {(Observable<DataTypeModel | null>)}
|
||||
* @memberof UmbDataTypeStore
|
||||
*/
|
||||
getByKey(key: string) {
|
||||
@@ -78,10 +73,11 @@ export class UmbUserStore extends UmbStoreBase implements UmbEntityDetailStore<U
|
||||
this.#users.appendOne(data);
|
||||
});
|
||||
|
||||
return this.#users.getObservablePart((users: Array<UmbUserStoreItemType>) => users.find((user: UmbUserStoreItemType) => user.key === key));
|
||||
return this.#users.getObservablePart((users: Array<UmbUserStoreItemType>) =>
|
||||
users.find((user: UmbUserStoreItemType) => user.key === key)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description - Request Users by keys.
|
||||
* @param {string} key
|
||||
@@ -96,7 +92,9 @@ export class UmbUserStore extends UmbStoreBase implements UmbEntityDetailStore<U
|
||||
this.#users.append(data);
|
||||
});
|
||||
|
||||
return this.#users.getObservablePart((users: Array<UmbUserStoreItemType>) => users.filter((user: UmbUserStoreItemType) => keys.includes(user.key)));
|
||||
return this.#users.getObservablePart((users: Array<UmbUserStoreItemType>) =>
|
||||
users.filter((user: UmbUserStoreItemType) => keys.includes(user.key))
|
||||
);
|
||||
}
|
||||
|
||||
getByName(name: string) {
|
||||
@@ -110,7 +108,9 @@ export class UmbUserStore extends UmbStoreBase implements UmbEntityDetailStore<U
|
||||
this.#users.append(data);
|
||||
});
|
||||
|
||||
return this.#users.getObservablePart((users: Array<UmbUserStoreItemType>) => users.filter((user: UmbUserStoreItemType) => user.name.toLocaleLowerCase().includes(name)));
|
||||
return this.#users.getObservablePart((users: Array<UmbUserStoreItemType>) =>
|
||||
users.filter((user: UmbUserStoreItemType) => user.name.toLocaleLowerCase().includes(name))
|
||||
);
|
||||
}
|
||||
|
||||
async enableUsers(userKeys: Array<string>) {
|
||||
@@ -243,12 +243,7 @@ export class UmbUserStore extends UmbStoreBase implements UmbEntityDetailStore<U
|
||||
}
|
||||
}
|
||||
|
||||
async invite(
|
||||
name: string,
|
||||
email: string,
|
||||
message: string,
|
||||
userGroups: Array<string>
|
||||
) {
|
||||
async invite(name: string, email: string, message: string, userGroups: Array<string>) {
|
||||
// TODO: use Fetcher API.
|
||||
try {
|
||||
const res = await fetch('/umbraco/backoffice/users/invite', {
|
||||
|
||||
@@ -88,7 +88,6 @@ export class UmbUserWorkspaceElement extends UmbLitElement implements UmbWorkspa
|
||||
|
||||
private _languages = []; //TODO Add languages
|
||||
|
||||
|
||||
private _workspaceContext: UmbWorkspaceUserContext = new UmbWorkspaceUserContext(this);
|
||||
|
||||
@state()
|
||||
@@ -105,7 +104,7 @@ export class UmbUserWorkspaceElement extends UmbLitElement implements UmbWorkspa
|
||||
this._observeCurrentUser();
|
||||
});
|
||||
|
||||
this.observe(this._workspaceContext.data.pipe(distinctUntilChanged()), (user) => {
|
||||
this.observe(this._workspaceContext.data, (user) => {
|
||||
this._user = user;
|
||||
if (user && user.name !== this._userName) {
|
||||
this._userName = user.name;
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import { UmbEntityData } from './entity.data';
|
||||
import { createFolderTreeItem } from './utils';
|
||||
import type { FolderTreeItemModel } from '@umbraco-cms/backend-api';
|
||||
import type { DataTypeDetails } from '@umbraco-cms/models';
|
||||
import type { FolderTreeItemModel, DataTypeModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
export const data: Array<DataTypeDetails> = [
|
||||
export const data: Array<DataTypeModel> = [
|
||||
{
|
||||
key: '0cc0eba1-9960-42c9-bf9b-60e150b429ae',
|
||||
parentKey: null,
|
||||
name: 'Textstring',
|
||||
propertyEditorAlias: 'Umbraco.TextBox',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.TextBox',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Text',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-textBox',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.TextBox',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.TextBox',
|
||||
propertyEditorAlias: 'Umbraco.TextBox',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.TextBox',
|
||||
data: [
|
||||
{
|
||||
alias: 'maxChars',
|
||||
@@ -24,41 +26,26 @@ export const data: Array<DataTypeDetails> = [
|
||||
},
|
||||
{
|
||||
name: 'Text Area',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-textArea',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.TextArea',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.TextArea',
|
||||
propertyEditorAlias: 'Umbraco.TextArea',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.TextArea',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'My JS Property Editor',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-custom',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.JSON',
|
||||
propertyEditorUIAlias: 'My.PropertyEditorUI.Custom',
|
||||
propertyEditorAlias: 'Umbraco.JSON',
|
||||
propertyEditorUiAlias: 'My.PropertyEditorUI.Custom',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Color Picker',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-colorPicker',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.ColorPicker',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.ColorPicker',
|
||||
propertyEditorAlias: 'Umbraco.ColorPicker',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.ColorPicker',
|
||||
data: [
|
||||
{
|
||||
alias: 'includeLabels',
|
||||
@@ -72,15 +59,10 @@ export const data: Array<DataTypeDetails> = [
|
||||
},
|
||||
{
|
||||
name: 'Content Picker',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-contentPicker',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.ContentPicker',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.DocumentPicker',
|
||||
propertyEditorAlias: 'Umbraco.ContentPicker',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.DocumentPicker',
|
||||
data: [
|
||||
{
|
||||
alias: 'validationLimit',
|
||||
@@ -90,15 +72,10 @@ export const data: Array<DataTypeDetails> = [
|
||||
},
|
||||
{
|
||||
name: 'Eye Dropper',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-eyeDropper',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.ColorPicker.EyeDropper',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.EyeDropper',
|
||||
propertyEditorAlias: 'Umbraco.ColorPicker.EyeDropper',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.EyeDropper',
|
||||
data: [
|
||||
{
|
||||
alias: 'palette',
|
||||
@@ -129,67 +106,42 @@ export const data: Array<DataTypeDetails> = [
|
||||
},
|
||||
{
|
||||
name: 'Multi URL Picker',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-multiUrlPicker',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.MultiUrlPicker',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.MultiUrlPicker',
|
||||
propertyEditorAlias: 'Umbraco.MultiUrlPicker',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.MultiUrlPicker',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Multi Node Tree Picker',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-multiNodeTreePicker',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.MultiNodeTreePicker',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.TreePicker',
|
||||
propertyEditorAlias: 'Umbraco.MultiNodeTreePicker',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.TreePicker',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Date Picker',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-datePicker',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.DateTime',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.DatePicker',
|
||||
propertyEditorAlias: 'Umbraco.DateTime',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.DatePicker',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Email',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-email',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.EmailAddress',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.Email',
|
||||
propertyEditorAlias: 'Umbraco.EmailAddress',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.Email',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Multiple Text String',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-multipleTextString',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.MultipleTextString',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.MultipleTextString',
|
||||
propertyEditorAlias: 'Umbraco.MultipleTextString',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.MultipleTextString',
|
||||
data: [
|
||||
{
|
||||
alias: 'minNumber',
|
||||
@@ -203,93 +155,58 @@ export const data: Array<DataTypeDetails> = [
|
||||
},
|
||||
{
|
||||
name: 'Dropdown',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-dropdown',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.DropDown.Flexible',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.Dropdown',
|
||||
propertyEditorAlias: 'Umbraco.DropDown.Flexible',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.Dropdown',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Slider',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-slider',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.Slider',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.Slider',
|
||||
propertyEditorAlias: 'Umbraco.Slider',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.Slider',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Toggle',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-toggle',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.TrueFalse',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.Toggle',
|
||||
propertyEditorAlias: 'Umbraco.TrueFalse',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.Toggle',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Tags',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-tags',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.Tags',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.Tags',
|
||||
propertyEditorAlias: 'Umbraco.Tags',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.Tags',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Markdown Editor',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-markdownEditor',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.MarkdownEditor',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.MarkdownEditor',
|
||||
propertyEditorAlias: 'Umbraco.MarkdownEditor',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.MarkdownEditor',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Radio Button List',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-radioButtonList',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.RadioButtonList',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.RadioButtonList',
|
||||
propertyEditorAlias: 'Umbraco.RadioButtonList',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.RadioButtonList',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Checkbox List',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-checkboxList',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.CheckboxList',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.CheckboxList',
|
||||
propertyEditorAlias: 'Umbraco.CheckboxList',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.CheckboxList',
|
||||
data: [
|
||||
{
|
||||
alias: 'itemList',
|
||||
@@ -302,223 +219,138 @@ export const data: Array<DataTypeDetails> = [
|
||||
},
|
||||
{
|
||||
name: 'Block List',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-blockList',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.BlockList',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.BlockList',
|
||||
propertyEditorAlias: 'Umbraco.BlockList',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.BlockList',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Media Picker',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-mediaPicker',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.MediaPicker3',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.MediaPicker',
|
||||
propertyEditorAlias: 'Umbraco.MediaPicker3',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.MediaPicker',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Image Cropper',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-imageCropper',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.ImageCropper',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.ImageCropper',
|
||||
propertyEditorAlias: 'Umbraco.ImageCropper',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.ImageCropper',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Upload Field',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-uploadField',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.UploadField',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.UploadField',
|
||||
propertyEditorAlias: 'Umbraco.UploadField',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.UploadField',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Block Grid',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-blockGrid',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.BlockGrid',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.BlockGrid',
|
||||
propertyEditorAlias: 'Umbraco.BlockGrid',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.BlockGrid',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Collection View',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-collectionView',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.ListView',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.CollectionView',
|
||||
propertyEditorAlias: 'Umbraco.ListView',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.CollectionView',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Icon Picker',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-iconPicker',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.IconPicker',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.IconPicker',
|
||||
propertyEditorAlias: 'Umbraco.IconPicker',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.IconPicker',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Number Range',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-numberRange',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.JSON',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.NumberRange',
|
||||
propertyEditorAlias: 'Umbraco.JSON',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.NumberRange',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Order Direction',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-orderDirection',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.JSON',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.OrderDirection',
|
||||
propertyEditorAlias: 'Umbraco.JSON',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.OrderDirection',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Overlay Size',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-overlaySize',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.JSON',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.OverlaySize',
|
||||
propertyEditorAlias: 'Umbraco.JSON',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.OverlaySize',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Rich Text Editor',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-richTextEditor',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.TinyMCE',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.TinyMCE',
|
||||
propertyEditorAlias: 'Umbraco.TinyMCE',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.TinyMCE',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Label',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-label',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.Label',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.Label',
|
||||
propertyEditorAlias: 'Umbraco.Label',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.Label',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Integer',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-integer',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.Integer',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.Integer',
|
||||
propertyEditorAlias: 'Umbraco.Integer',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.Integer',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Decimal',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-decimal',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.Decimal',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.Decimal',
|
||||
propertyEditorAlias: 'Umbraco.Decimal',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.Decimal',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'User Picker',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-userPicker',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.UserPicker',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.UserPicker',
|
||||
propertyEditorAlias: 'Umbraco.UserPicker',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.UserPicker',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Member Picker',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-memberPicker',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.MemberPicker',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.MemberPicker',
|
||||
propertyEditorAlias: 'Umbraco.MemberPicker',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.MemberPicker',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: 'Member Group Picker',
|
||||
type: 'data-type',
|
||||
icon: 'umb:autofill',
|
||||
hasChildren: false,
|
||||
key: 'dt-memberGroupPicker',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
propertyEditorModelAlias: 'Umbraco.MemberGroupPicker',
|
||||
propertyEditorUIAlias: 'Umb.PropertyEditorUI.MemberGroupPicker',
|
||||
propertyEditorAlias: 'Umbraco.MemberGroupPicker',
|
||||
propertyEditorUiAlias: 'Umb.PropertyEditorUI.MemberGroupPicker',
|
||||
data: [],
|
||||
},
|
||||
];
|
||||
@@ -527,7 +359,7 @@ export const data: Array<DataTypeDetails> = [
|
||||
// TODO: all properties are optional in the server schema. I don't think this is correct.
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
class UmbDataTypeData extends UmbEntityData<DataTypeDetails> {
|
||||
class UmbDataTypeData extends UmbEntityData<DataTypeModel> {
|
||||
constructor() {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,708 @@
|
||||
import { UmbEntityData } from './entity.data';
|
||||
import { createDocumentTypeTreeItem } from './utils';
|
||||
import type { DocumentTypeTreeItemModel } from '@umbraco-cms/backend-api';
|
||||
import type { DocumentTypeDetails } from '@umbraco-cms/models';
|
||||
import {
|
||||
DocumentTypeTreeItemModel,
|
||||
DocumentTypeModel,
|
||||
ContentTypeCompositionTypeModel,
|
||||
} from '@umbraco-cms/backend-api';
|
||||
|
||||
export const data: Array<DocumentTypeDetails> = [
|
||||
export const data: Array<DocumentTypeModel> = [
|
||||
{
|
||||
allowedTemplateKeys: [],
|
||||
defaultTemplateKey: null,
|
||||
key: 'all-property-editors-document-type-key',
|
||||
alias: 'blogPost',
|
||||
name: 'Blog Post',
|
||||
description: null,
|
||||
icon: 'icon-item-arrangement',
|
||||
allowedAsRoot: true,
|
||||
variesByCulture: true,
|
||||
variesBySegment: false,
|
||||
isElement: false,
|
||||
properties: [
|
||||
{
|
||||
key: '2',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'colorPicker',
|
||||
name: 'Color Picker',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-colorPicker',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'contentPicker',
|
||||
name: 'Content Picker',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-contentPicker',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'eyeDropper',
|
||||
name: 'Eye Dropper',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-eyeDropper',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'multiUrlPicker',
|
||||
name: 'Multi URL Picker',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-multiUrlPicker',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '6',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'multiNodeTreePicker',
|
||||
name: 'Multi Node Tree Picker',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-multiNodeTreePicker',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '7',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'datePicker',
|
||||
name: 'Date Picker',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-datePicker',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '8',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'email',
|
||||
name: 'Email',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-email',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '9',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'textBox',
|
||||
name: 'Text Box',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-textBox',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '19',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'dropdown',
|
||||
name: 'Dropdown',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-dropdown',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '11',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'textArea',
|
||||
name: 'Text Area',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-textArea',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '12',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'slider',
|
||||
name: 'Slider',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-slider',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '13',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'toggle',
|
||||
name: 'Toggle',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-toggle',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '14',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'tags',
|
||||
name: 'Tags',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-tags',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '15',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'markdownEditor',
|
||||
name: 'MarkdownEditor',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-markdownEditor',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '16',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'radioButtonList',
|
||||
name: 'Radio Button List',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-radioButtonList',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '17',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'checkboxList',
|
||||
name: 'Checkbox List',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-checkboxList',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '18',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'blockList',
|
||||
name: 'Block List',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-blockList',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '19',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'mediaPicker',
|
||||
name: 'Media Picker',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-mediaPicker',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '20',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'imageCropper',
|
||||
name: 'Image Cropper',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-imageCropper',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '21',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'uploadField',
|
||||
name: 'Upload Field',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-uploadField',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '22',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'blockGrid',
|
||||
name: 'Block Grid',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-blockGrid',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '23',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'blockGrid',
|
||||
name: 'Icon Picker',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-iconPicker',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '24',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'numberRange',
|
||||
name: 'Number Range',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-numberRange',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '25',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'orderDirection',
|
||||
name: 'Order Direction',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-orderDirection',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '26',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'overlaySize',
|
||||
name: 'Overlay Size',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-overlaySize',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '27',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'label',
|
||||
name: 'Label',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-label',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '28',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'integer',
|
||||
name: 'Integer',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-integer',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '29',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'decimal',
|
||||
name: 'Decimal',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-decimal',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '30',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'memberPicker',
|
||||
name: 'Member Picker',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-memberPicker',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '31',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'memberGroupPicker',
|
||||
name: 'Member Group Picker',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-memberGroupPicker',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '32',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'userPicker',
|
||||
name: 'User Picker',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-userPicker',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
containers: [
|
||||
{
|
||||
key: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
parentKey: null,
|
||||
name: 'Content',
|
||||
type: 'Group',
|
||||
sortOrder: 0,
|
||||
},
|
||||
],
|
||||
allowedContentTypes: [],
|
||||
compositions: [],
|
||||
cleanup: {
|
||||
preventCleanup: false,
|
||||
keepAllVersionsNewerThanDays: null,
|
||||
keepLatestVersionPerDayForDays: null,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
allowedTemplateKeys: [],
|
||||
defaultTemplateKey: null,
|
||||
key: '29643452-cff9-47f2-98cd-7de4b6807681',
|
||||
alias: 'blogPost',
|
||||
name: 'Blog Post',
|
||||
description: null,
|
||||
icon: 'icon-item-arrangement',
|
||||
allowedAsRoot: true,
|
||||
variesByCulture: true,
|
||||
variesBySegment: false,
|
||||
isElement: false,
|
||||
properties: [
|
||||
{
|
||||
key: '5b4ca208-134e-4865-b423-06e5e97adf3c',
|
||||
containerKey: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
alias: 'blogPostText',
|
||||
name: 'Blog Post Text',
|
||||
description: null,
|
||||
dataTypeKey: '0cc0eba1-9960-42c9-bf9b-60e150b429ae',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'ef7096b6-7c9e-49ba-8d49-395111e65ea2',
|
||||
containerKey: '227d6ed2-e118-4494-b8f2-deb69854a56a',
|
||||
alias: 'blogTextStringUnderMasterTab',
|
||||
name: 'Blog text string under master tab',
|
||||
description: null,
|
||||
dataTypeKey: '0cc0eba1-9960-42c9-bf9b-60e150b429ae',
|
||||
validation: {
|
||||
mandatory: false,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'e010c429-b298-499a-9bfe-79687af8972a',
|
||||
containerKey: '22177c49-ecba-4f2e-b7fa-3f2c04d02cfb',
|
||||
alias: 'blogTextStringUnderGroupUnderMasterTab',
|
||||
name: 'Blog text string under group under master tab',
|
||||
description: null,
|
||||
dataTypeKey: '0cc0eba1-9960-42c9-bf9b-60e150b429ae',
|
||||
validation: {
|
||||
mandatory: false,
|
||||
mandatoryMessage: null,
|
||||
regEx: null,
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '1a22749a-c7d2-44bb-b36b-c977c2ced6ef',
|
||||
containerKey: '2c943997-b685-432d-a6c5-601d8e7a298a',
|
||||
alias: 'localBlogTabString',
|
||||
name: 'Local Blog Tab String',
|
||||
description: null,
|
||||
dataTypeKey: '0cc0eba1-9960-42c9-bf9b-60e150b429ae',
|
||||
validation: {
|
||||
mandatory: true,
|
||||
mandatoryMessage: null,
|
||||
regEx: '^[0-9]*$',
|
||||
regExMessage: null,
|
||||
},
|
||||
appearance: {
|
||||
labelOnTop: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
containers: [
|
||||
{
|
||||
key: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
|
||||
parentKey: null,
|
||||
name: 'Content',
|
||||
type: 'Group',
|
||||
sortOrder: 0,
|
||||
},
|
||||
{
|
||||
key: '227d6ed2-e118-4494-b8f2-deb69854a56a',
|
||||
parentKey: null,
|
||||
name: 'Master Tab',
|
||||
type: 'Tab',
|
||||
sortOrder: 0,
|
||||
},
|
||||
{
|
||||
key: '22177c49-ecba-4f2e-b7fa-3f2c04d02cfb',
|
||||
parentKey: '227d6ed2-e118-4494-b8f2-deb69854a56a',
|
||||
name: 'Blog Group under master tab',
|
||||
type: 'Group',
|
||||
sortOrder: 0,
|
||||
},
|
||||
{
|
||||
key: '2c943997-b685-432d-a6c5-601d8e7a298a',
|
||||
parentKey: null,
|
||||
name: 'Local blog tab',
|
||||
type: 'Tab',
|
||||
sortOrder: 1,
|
||||
},
|
||||
],
|
||||
allowedContentTypes: [
|
||||
{
|
||||
key: '29643452-cff9-47f2-98cd-7de4b6807681',
|
||||
sortOrder: 0,
|
||||
},
|
||||
],
|
||||
compositions: [
|
||||
{
|
||||
key: '5035d7d9-0a63-415c-9e75-ee2cf931db92',
|
||||
compositionType: ContentTypeCompositionTypeModel.INHERITANCE,
|
||||
},
|
||||
{
|
||||
key: '8f68ba66-6fb2-4778-83b8-6ab4ca3a7c5d',
|
||||
compositionType: ContentTypeCompositionTypeModel.COMPOSITION,
|
||||
},
|
||||
],
|
||||
cleanup: {
|
||||
preventCleanup: false,
|
||||
keepAllVersionsNewerThanDays: null,
|
||||
keepLatestVersionPerDayForDays: null,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const treeData: Array<DocumentTypeTreeItemModel> = [
|
||||
{
|
||||
name: 'Document Type 1',
|
||||
type: 'document-type',
|
||||
@@ -11,11 +710,7 @@ export const data: Array<DocumentTypeDetails> = [
|
||||
key: 'd81c7957-153c-4b5a-aa6f-b434a4964624',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
isElement: false,
|
||||
icon: '',
|
||||
alias: 'documentType1',
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
name: 'Document Type 2',
|
||||
@@ -24,11 +719,7 @@ export const data: Array<DocumentTypeDetails> = [
|
||||
key: 'a99e4018-3ffc-486b-aa76-eecea9593d17',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
isFolder: false,
|
||||
isElement: false,
|
||||
icon: '',
|
||||
alias: 'documentType2',
|
||||
properties: [],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -36,23 +727,25 @@ export const data: Array<DocumentTypeDetails> = [
|
||||
// TODO: all properties are optional in the server schema. I don't think this is correct.
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
class UmbDocumentTypeData extends UmbEntityData<DocumentTypeDetails> {
|
||||
class UmbDocumentTypeData extends UmbEntityData<DocumentTypeTreeItemModel> {
|
||||
private treeData = treeData;
|
||||
|
||||
constructor() {
|
||||
super(data);
|
||||
}
|
||||
|
||||
getTreeRoot(): Array<DocumentTypeTreeItemModel> {
|
||||
const rootItems = this.data.filter((item) => item.parentKey === null);
|
||||
const rootItems = this.treeData.filter((item) => item.parentKey === null);
|
||||
return rootItems.map((item) => createDocumentTypeTreeItem(item));
|
||||
}
|
||||
|
||||
getTreeItemChildren(key: string): Array<DocumentTypeTreeItemModel> {
|
||||
const childItems = this.data.filter((item) => item.parentKey === key);
|
||||
const childItems = this.treeData.filter((item) => item.parentKey === key);
|
||||
return childItems.map((item) => createDocumentTypeTreeItem(item));
|
||||
}
|
||||
|
||||
getTreeItem(keys: Array<string>): Array<DocumentTypeTreeItemModel> {
|
||||
const items = this.data.filter((item) => keys.includes(item.key ?? ''));
|
||||
const items = this.treeData.filter((item) => keys.includes(item.key ?? ''));
|
||||
return items.map((item) => createDocumentTypeTreeItem(item));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +1,15 @@
|
||||
import { UmbEntityData } from './entity.data';
|
||||
import { createDocumentTreeItem } from './utils';
|
||||
import { DocumentTreeItemModel, PagedDocumentTreeItemModel } from '@umbraco-cms/backend-api';
|
||||
import type { DocumentDetails } from '@umbraco-cms/models';
|
||||
import {
|
||||
ContentStateModel,
|
||||
DocumentModel,
|
||||
DocumentTreeItemModel,
|
||||
PagedDocumentTreeItemModel,
|
||||
} from '@umbraco-cms/backend-api';
|
||||
|
||||
export const data: Array<DocumentDetails> = [
|
||||
{
|
||||
name: 'Multiple Text String',
|
||||
type: 'document',
|
||||
icon: 'favorite',
|
||||
hasChildren: false,
|
||||
key: '6f31e382-458c-4f96-95ea-cc26c51009d4',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
noAccess: false,
|
||||
isProtected: false,
|
||||
isPublished: false,
|
||||
isEdited: false,
|
||||
isTrashed: false,
|
||||
properties: [
|
||||
{
|
||||
alias: 'multipleTextString',
|
||||
label: 'Multiple Text String',
|
||||
description: '',
|
||||
dataTypeKey: 'dt-multipleTextString',
|
||||
},
|
||||
],
|
||||
data: [
|
||||
{
|
||||
alias: 'multipleTextString',
|
||||
value: [
|
||||
{
|
||||
value: 'Value 1',
|
||||
},
|
||||
{
|
||||
value: 'Value 2',
|
||||
},
|
||||
{
|
||||
value: 'Value 3',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
variants: [],
|
||||
},
|
||||
{
|
||||
/*
|
||||
|
||||
{
|
||||
name: 'All Property Editors',
|
||||
type: 'document',
|
||||
icon: 'favorite',
|
||||
@@ -247,179 +213,201 @@ export const data: Array<DocumentDetails> = [
|
||||
data: [],
|
||||
variants: [],
|
||||
},
|
||||
|
||||
*/
|
||||
|
||||
export const data: Array<DocumentModel> = [
|
||||
{
|
||||
name: 'Document 1',
|
||||
type: 'document',
|
||||
icon: 'document',
|
||||
hasChildren: false,
|
||||
key: '74e4008a-ea4f-4793-b924-15e02fd380d1',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
noAccess: false,
|
||||
isProtected: false,
|
||||
isPublished: false,
|
||||
isEdited: false,
|
||||
isTrashed: false,
|
||||
urls: [
|
||||
{
|
||||
culture: 'en-US',
|
||||
url: '/',
|
||||
},
|
||||
],
|
||||
templateKey: null,
|
||||
key: 'all-property-editors-document-key',
|
||||
contentTypeKey: 'all-property-editors-document-type-key',
|
||||
properties: [
|
||||
// TODO: is 'properties' the correct name for this? The property comes from the doc type, and this only holds the values.
|
||||
{
|
||||
alias: 'myHeadline',
|
||||
label: 'Headline',
|
||||
description: 'Text string property',
|
||||
dataTypeKey: 'dt-textBox',
|
||||
},
|
||||
{
|
||||
alias: 'myDescription',
|
||||
label: 'Description',
|
||||
description: 'Textarea property',
|
||||
dataTypeKey: 'dt-textArea',
|
||||
culture: null,
|
||||
segment: null,
|
||||
alias: 'email',
|
||||
value: 'mail@umbraco.com',
|
||||
},
|
||||
],
|
||||
data: [
|
||||
variants: [
|
||||
{
|
||||
alias: 'myHeadline',
|
||||
value: 'The daily life at Umbraco HQ',
|
||||
},
|
||||
{
|
||||
alias: 'myDescription',
|
||||
value: 'Every day, a rabbit in a military costume greets me at the front door',
|
||||
state: ContentStateModel.PUBLISHED,
|
||||
publishDate: '2023-02-06T15:31:51.354764',
|
||||
culture: 'en-us',
|
||||
segment: null,
|
||||
name: 'Blog post A',
|
||||
createDate: '2023-02-06T15:31:46.876902',
|
||||
updateDate: '2023-02-06T15:31:51.354764',
|
||||
},
|
||||
],
|
||||
variants: [{ name: 'fake data' }],
|
||||
/*
|
||||
// Concept for node layout, separation of design from config and data.
|
||||
layout: [
|
||||
{
|
||||
type: 'group',
|
||||
children: [
|
||||
{
|
||||
type: 'property',
|
||||
alias: 'myHeadline'
|
||||
},
|
||||
{
|
||||
type: 'property',
|
||||
alias: 'myDescription'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
*/
|
||||
},
|
||||
{
|
||||
name: 'Document 2',
|
||||
type: 'document',
|
||||
icon: 'favorite',
|
||||
hasChildren: false,
|
||||
key: '74e4008a-ea4f-4793-b924-15e02fd380d2',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
noAccess: false,
|
||||
isProtected: false,
|
||||
isPublished: false,
|
||||
isEdited: false,
|
||||
isTrashed: false,
|
||||
urls: [
|
||||
{
|
||||
culture: 'en-US',
|
||||
url: '/',
|
||||
},
|
||||
],
|
||||
templateKey: null,
|
||||
key: 'c05da24d-7740-447b-9cdc-bd8ce2172e38',
|
||||
contentTypeKey: '29643452-cff9-47f2-98cd-7de4b6807681',
|
||||
properties: [
|
||||
{
|
||||
alias: 'myHeadline',
|
||||
label: 'Text string label',
|
||||
description: 'this is a text string property',
|
||||
dataTypeKey: 'dt-textBox',
|
||||
culture: null,
|
||||
segment: null,
|
||||
alias: 'masterText',
|
||||
value: 'i have a master text',
|
||||
},
|
||||
{
|
||||
alias: 'myDescription',
|
||||
label: 'Textarea label',
|
||||
description: 'This is the a textarea property',
|
||||
dataTypeKey: 'dt-textArea',
|
||||
culture: null,
|
||||
segment: null,
|
||||
alias: 'pageTitle',
|
||||
value: 'with a page title',
|
||||
},
|
||||
{
|
||||
alias: 'myExternalEditor',
|
||||
label: 'My JS Property Editor',
|
||||
description: 'This is the a external property',
|
||||
dataTypeKey: 'dt-custom',
|
||||
culture: null,
|
||||
segment: null,
|
||||
alias: 'blogPostText',
|
||||
value: 'My first blog post',
|
||||
},
|
||||
{
|
||||
alias: 'myContentPicker',
|
||||
label: 'Content Picker',
|
||||
description: 'This is a content picker',
|
||||
dataTypeKey: 'dt-contentPicker',
|
||||
culture: 'en-us',
|
||||
segment: null,
|
||||
alias: 'blogTextStringUnderMasterTab',
|
||||
value: 'in the master tab',
|
||||
},
|
||||
{
|
||||
culture: 'en-us',
|
||||
segment: null,
|
||||
alias: 'blogTextStringUnderGroupUnderMasterTab',
|
||||
value: 'which is under another group in the tab',
|
||||
},
|
||||
{
|
||||
culture: null,
|
||||
segment: null,
|
||||
alias: 'localBlogTabString',
|
||||
value: '1234567',
|
||||
},
|
||||
],
|
||||
data: [
|
||||
variants: [
|
||||
{
|
||||
alias: 'myHeadline',
|
||||
value: 'Is it all just fun and curling and scary rabbits?',
|
||||
},
|
||||
{
|
||||
alias: 'myDescription',
|
||||
value:
|
||||
"So no, there's not confetti every day. And no, there's not champagne every week or a crazy rabbit running around 🐰",
|
||||
},
|
||||
{
|
||||
alias: 'myExternalEditor',
|
||||
value: 'Tex lkasdfkljdfsa 1',
|
||||
},
|
||||
{
|
||||
alias: 'myContextExampleEditor',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
alias: 'myContentPicker',
|
||||
value: '',
|
||||
state: ContentStateModel.PUBLISHED,
|
||||
publishDate: '2023-02-06T15:31:51.354764',
|
||||
culture: 'en-us',
|
||||
segment: null,
|
||||
name: 'Blog post A',
|
||||
createDate: '2023-02-06T15:31:46.876902',
|
||||
updateDate: '2023-02-06T15:31:51.354764',
|
||||
},
|
||||
],
|
||||
variants: [{ name: 'Variant 1' }],
|
||||
},
|
||||
{
|
||||
name: 'Document 3',
|
||||
urls: [],
|
||||
templateKey: null,
|
||||
key: 'fd56a0b5-01a0-4da2-b428-52773bfa9cc4',
|
||||
contentTypeKey: '29643452-cff9-47f2-98cd-7de4b6807681',
|
||||
properties: [
|
||||
{
|
||||
culture: null,
|
||||
segment: null,
|
||||
alias: 'masterText',
|
||||
value: 'i have a master text B',
|
||||
},
|
||||
{
|
||||
culture: null,
|
||||
segment: null,
|
||||
alias: 'pageTitle',
|
||||
value: 'with a page title B',
|
||||
},
|
||||
{
|
||||
culture: null,
|
||||
segment: null,
|
||||
alias: 'blogPostText',
|
||||
value: 'My first blog post B',
|
||||
},
|
||||
{
|
||||
culture: 'en-us',
|
||||
segment: null,
|
||||
alias: 'blogTextStringUnderMasterTab',
|
||||
value: 'in the master tab B',
|
||||
},
|
||||
{
|
||||
culture: 'en-us',
|
||||
segment: null,
|
||||
alias: 'blogTextStringUnderGroupUnderMasterTab',
|
||||
value: 'which is under another group in the tab B',
|
||||
},
|
||||
{
|
||||
culture: null,
|
||||
segment: null,
|
||||
alias: 'localBlogTabString',
|
||||
value: '1234567890',
|
||||
},
|
||||
],
|
||||
variants: [
|
||||
{
|
||||
state: ContentStateModel.DRAFT,
|
||||
publishDate: '2023-02-06T15:32:24.957009',
|
||||
culture: 'en-us',
|
||||
segment: null,
|
||||
name: 'Blog post B',
|
||||
createDate: '2023-02-06T15:32:05.350038',
|
||||
updateDate: '2023-02-06T15:32:24.957009',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// TODO: make tree data:
|
||||
export const treeData: Array<DocumentTreeItemModel> = [
|
||||
{
|
||||
isProtected: false,
|
||||
isPublished: true,
|
||||
isEdited: false,
|
||||
noAccess: false,
|
||||
isTrashed: false,
|
||||
key: 'all-property-editors-document-key',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
name: 'All property editors',
|
||||
type: 'document',
|
||||
icon: 'document',
|
||||
icon: 'icon-item-arrangement',
|
||||
hasChildren: false,
|
||||
},
|
||||
{
|
||||
isProtected: false,
|
||||
isPublished: true,
|
||||
isEdited: false,
|
||||
noAccess: false,
|
||||
isTrashed: false,
|
||||
key: 'c05da24d-7740-447b-9cdc-bd8ce2172e38',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
name: 'Blog post A',
|
||||
type: 'document',
|
||||
icon: 'icon-item-arrangement',
|
||||
hasChildren: true,
|
||||
key: 'cdd30288-2d1c-41b4-89a9-61647b4a10d5',
|
||||
isContainer: false,
|
||||
parentKey: null,
|
||||
noAccess: false,
|
||||
isProtected: false,
|
||||
isPublished: false,
|
||||
isEdited: false,
|
||||
isTrashed: false,
|
||||
properties: [
|
||||
{
|
||||
alias: 'myDescription',
|
||||
label: 'Description',
|
||||
description: 'Textarea property',
|
||||
dataTypeKey: 'dt-textArea',
|
||||
},
|
||||
],
|
||||
data: [
|
||||
{
|
||||
alias: 'myDescription',
|
||||
value: 'Every day, a rabbit in a military costume greets me at the front door',
|
||||
},
|
||||
],
|
||||
variants: [],
|
||||
},
|
||||
{
|
||||
name: 'Document 4',
|
||||
type: 'document',
|
||||
icon: 'document',
|
||||
hasChildren: false,
|
||||
key: 'f6f7a5b2-e7c0-463a-97bc-6cb5b9bcf447',
|
||||
isContainer: false,
|
||||
parentKey: 'cdd30288-2d1c-41b4-89a9-61647b4a10d5',
|
||||
noAccess: false,
|
||||
isProtected: false,
|
||||
isPublished: false,
|
||||
isEdited: false,
|
||||
noAccess: false,
|
||||
isTrashed: false,
|
||||
properties: [
|
||||
{
|
||||
alias: 'myDescription',
|
||||
label: 'Description',
|
||||
description: 'Textarea property',
|
||||
dataTypeKey: 'dt-textArea',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
variants: [],
|
||||
key: 'fd56a0b5-01a0-4da2-b428-52773bfa9cc4',
|
||||
isContainer: false,
|
||||
parentKey: 'c05da24d-7740-447b-9cdc-bd8ce2172e38',
|
||||
name: 'Blog post B',
|
||||
type: 'document',
|
||||
icon: 'icon-item-arrangement',
|
||||
hasChildren: false,
|
||||
},
|
||||
{
|
||||
name: 'Document 5',
|
||||
@@ -434,9 +422,6 @@ export const data: Array<DocumentDetails> = [
|
||||
isPublished: false,
|
||||
isEdited: false,
|
||||
isTrashed: false,
|
||||
properties: [],
|
||||
data: [],
|
||||
variants: [],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -444,27 +429,29 @@ export const data: Array<DocumentDetails> = [
|
||||
// TODO: all properties are optional in the server schema. I don't think this is correct.
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
class UmbDocumentData extends UmbEntityData<DocumentDetails> {
|
||||
class UmbDocumentData extends UmbEntityData<DocumentModel> {
|
||||
private treeData = treeData;
|
||||
|
||||
constructor() {
|
||||
super(data);
|
||||
}
|
||||
|
||||
getTreeRoot(): PagedDocumentTreeItemModel {
|
||||
const items = this.data.filter((item) => item.parentKey === null);
|
||||
const items = this.treeData.filter((item) => item.parentKey === null);
|
||||
const treeItems = items.map((item) => createDocumentTreeItem(item));
|
||||
const total = items.length;
|
||||
return { items: treeItems, total };
|
||||
}
|
||||
|
||||
getTreeItemChildren(key: string): PagedDocumentTreeItemModel {
|
||||
const items = this.data.filter((item) => item.parentKey === key);
|
||||
const items = this.treeData.filter((item) => item.parentKey === key);
|
||||
const treeItems = items.map((item) => createDocumentTreeItem(item));
|
||||
const total = items.length;
|
||||
return { items: treeItems, total };
|
||||
}
|
||||
|
||||
getTreeItem(keys: Array<string>): Array<DocumentTreeItemModel> {
|
||||
const items = this.data.filter((item) => keys.includes(item.key ?? ''));
|
||||
const items = this.treeData.filter((item) => keys.includes(item.key ?? ''));
|
||||
return items.map((item) => createDocumentTreeItem(item));
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user