Merge branch 'main' into feature/partial-view-editor

This commit is contained in:
Julia Gru
2023-05-01 09:16:22 +02:00
411 changed files with 8010 additions and 9339 deletions

View File

@@ -22,15 +22,13 @@ export interface OnCancel {
}
export class CancelablePromise<T> implements Promise<T> {
readonly [Symbol.toStringTag]!: string;
private _isResolved: boolean;
private _isRejected: boolean;
private _isCancelled: boolean;
private readonly _cancelHandlers: (() => void)[];
private readonly _promise: Promise<T>;
private _resolve?: (value: T | PromiseLike<T>) => void;
private _reject?: (reason?: any) => void;
#isResolved: boolean;
#isRejected: boolean;
#isCancelled: boolean;
readonly #cancelHandlers: (() => void)[];
readonly #promise: Promise<T>;
#resolve?: (value: T | PromiseLike<T>) => void;
#reject?: (reason?: any) => void;
constructor(
executor: (
@@ -39,78 +37,82 @@ export class CancelablePromise<T> implements Promise<T> {
onCancel: OnCancel
) => void
) {
this._isResolved = false;
this._isRejected = false;
this._isCancelled = false;
this._cancelHandlers = [];
this._promise = new Promise<T>((resolve, reject) => {
this._resolve = resolve;
this._reject = reject;
this.#isResolved = false;
this.#isRejected = false;
this.#isCancelled = false;
this.#cancelHandlers = [];
this.#promise = new Promise<T>((resolve, reject) => {
this.#resolve = resolve;
this.#reject = reject;
const onResolve = (value: T | PromiseLike<T>): void => {
if (this._isResolved || this._isRejected || this._isCancelled) {
if (this.#isResolved || this.#isRejected || this.#isCancelled) {
return;
}
this._isResolved = true;
this._resolve?.(value);
this.#isResolved = true;
this.#resolve?.(value);
};
const onReject = (reason?: any): void => {
if (this._isResolved || this._isRejected || this._isCancelled) {
if (this.#isResolved || this.#isRejected || this.#isCancelled) {
return;
}
this._isRejected = true;
this._reject?.(reason);
this.#isRejected = true;
this.#reject?.(reason);
};
const onCancel = (cancelHandler: () => void): void => {
if (this._isResolved || this._isRejected || this._isCancelled) {
if (this.#isResolved || this.#isRejected || this.#isCancelled) {
return;
}
this._cancelHandlers.push(cancelHandler);
this.#cancelHandlers.push(cancelHandler);
};
Object.defineProperty(onCancel, 'isResolved', {
get: (): boolean => this._isResolved,
get: (): boolean => this.#isResolved,
});
Object.defineProperty(onCancel, 'isRejected', {
get: (): boolean => this._isRejected,
get: (): boolean => this.#isRejected,
});
Object.defineProperty(onCancel, 'isCancelled', {
get: (): boolean => this._isCancelled,
get: (): boolean => this.#isCancelled,
});
return executor(onResolve, onReject, onCancel as OnCancel);
});
}
get [Symbol.toStringTag]() {
return "Cancellable Promise";
}
public then<TResult1 = T, TResult2 = never>(
onFulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
): Promise<TResult1 | TResult2> {
return this._promise.then(onFulfilled, onRejected);
return this.#promise.then(onFulfilled, onRejected);
}
public catch<TResult = never>(
onRejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
): Promise<T | TResult> {
return this._promise.catch(onRejected);
return this.#promise.catch(onRejected);
}
public finally(onFinally?: (() => void) | null): Promise<T> {
return this._promise.finally(onFinally);
return this.#promise.finally(onFinally);
}
public cancel(): void {
if (this._isResolved || this._isRejected || this._isCancelled) {
if (this.#isResolved || this.#isRejected || this.#isCancelled) {
return;
}
this._isCancelled = true;
if (this._cancelHandlers.length) {
this.#isCancelled = true;
if (this.#cancelHandlers.length) {
try {
for (const cancelHandler of this._cancelHandlers) {
for (const cancelHandler of this.#cancelHandlers) {
cancelHandler();
}
} catch (error) {
@@ -118,11 +120,11 @@ export class CancelablePromise<T> implements Promise<T> {
return;
}
}
this._cancelHandlers.length = 0;
this._reject?.(new CancelError('Request aborted'));
this.#cancelHandlers.length = 0;
this.#reject?.(new CancelError('Request aborted'));
}
public get isCancelled(): boolean {
return this._isCancelled;
return this.#isCancelled;
}
}

View File

@@ -20,7 +20,7 @@ export type OpenAPIConfig = {
export const OpenAPI: OpenAPIConfig = {
BASE: '',
VERSION: '1.0',
VERSION: 'Latest',
WITH_CREDENTIALS: false,
CREDENTIALS: 'include',
TOKEN: undefined,

View File

@@ -177,7 +177,7 @@ const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Pr
};
const getRequestBody = (options: ApiRequestOptions): any => {
if (options.body) {
if (options.body !== undefined) {
if (options.mediaType?.includes('/json')) {
return JSON.stringify(options.body)
} else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) {
@@ -231,7 +231,8 @@ const getResponseBody = async (response: Response): Promise<any> => {
try {
const contentType = response.headers.get('Content-Type');
if (contentType) {
const isJSON = contentType.toLowerCase().startsWith('application/json');
const jsonTypes = ['application/json', 'application/problem+json']
const isJSON = jsonTypes.some(type => contentType.toLowerCase().startsWith(type));
if (isJSON) {
return await response.json();
} else {

View File

@@ -23,6 +23,7 @@ export type { ContentTypeResponseModelBaseMediaTypePropertyTypeResponseModelMedi
export type { ContentTypeSortModel } from './models/ContentTypeSortModel';
export type { ContentUrlInfoModel } from './models/ContentUrlInfoModel';
export type { CopyDataTypeRequestModel } from './models/CopyDataTypeRequestModel';
export type { CopyDocumentRequestModel } from './models/CopyDocumentRequestModel';
export type { CreateContentRequestModelBaseDocumentValueModelDocumentVariantRequestModel } from './models/CreateContentRequestModelBaseDocumentValueModelDocumentVariantRequestModel';
export type { CreateContentRequestModelBaseMediaValueModelMediaVariantRequestModel } from './models/CreateContentRequestModelBaseMediaValueModelMediaVariantRequestModel';
export type { CreateDataTypeRequestModel } from './models/CreateDataTypeRequestModel';
@@ -98,6 +99,7 @@ export type { LanguageItemResponseModel } from './models/LanguageItemResponseMod
export type { LanguageModelBaseModel } from './models/LanguageModelBaseModel';
export type { LanguageResponseModel } from './models/LanguageResponseModel';
export type { LoggerResponseModel } from './models/LoggerResponseModel';
export type { LoginRequestModel } from './models/LoginRequestModel';
export type { LogLevelCountsReponseModel } from './models/LogLevelCountsReponseModel';
export { LogLevelModel } from './models/LogLevelModel';
export type { LogMessagePropertyPresentationModel } from './models/LogMessagePropertyPresentationModel';
@@ -112,11 +114,14 @@ export type { MediaValueModel } from './models/MediaValueModel';
export type { MediaVariantRequestModel } from './models/MediaVariantRequestModel';
export type { MediaVariantResponseModel } from './models/MediaVariantResponseModel';
export type { MemberGroupItemReponseModel } from './models/MemberGroupItemReponseModel';
export type { MemberItemResponseModel } from './models/MemberItemResponseModel';
export type { MemberTypeItemResponseModel } from './models/MemberTypeItemResponseModel';
export type { ModelsBuilderResponseModel } from './models/ModelsBuilderResponseModel';
export { ModelsModeModel } from './models/ModelsModeModel';
export type { MoveDataTypeRequestModel } from './models/MoveDataTypeRequestModel';
export type { MoveDictionaryRequestModel } from './models/MoveDictionaryRequestModel';
export type { MoveDocumentRequestModel } from './models/MoveDocumentRequestModel';
export type { MoveMediaRequestModel } from './models/MoveMediaRequestModel';
export type { ObjectTypeResponseModel } from './models/ObjectTypeResponseModel';
export type { OkResultModel } from './models/OkResultModel';
export { OperatorModel } from './models/OperatorModel';
@@ -128,6 +133,7 @@ export type { PackageMigrationStatusResponseModel } from './models/PackageMigrat
export type { PackageModelBaseModel } from './models/PackageModelBaseModel';
export type { PagedAuditLogResponseModel } from './models/PagedAuditLogResponseModel';
export type { PagedAuditLogWithUsernameResponseModel } from './models/PagedAuditLogWithUsernameResponseModel';
export type { PagedBooleanModel } from './models/PagedBooleanModel';
export type { PagedContentTreeItemResponseModel } from './models/PagedContentTreeItemResponseModel';
export type { PagedCultureReponseModel } from './models/PagedCultureReponseModel';
export type { PagedDictionaryOverviewResponseModel } from './models/PagedDictionaryOverviewResponseModel';
@@ -154,6 +160,7 @@ export type { PagedRelationResponseModel } from './models/PagedRelationResponseM
export type { PagedSavedLogSearchResponseModel } from './models/PagedSavedLogSearchResponseModel';
export type { PagedSearcherResponseModel } from './models/PagedSearcherResponseModel';
export type { PagedSearchResultResponseModel } from './models/PagedSearchResultResponseModel';
export type { PagedTagResponseModel } from './models/PagedTagResponseModel';
export type { PagedTelemetryResponseModel } from './models/PagedTelemetryResponseModel';
export type { PagedUserGroupPresentationModel } from './models/PagedUserGroupPresentationModel';
export type { PagedUserResponseModel } from './models/PagedUserResponseModel';
@@ -187,6 +194,7 @@ export type { SetAvatarRequestModel } from './models/SetAvatarRequestModel';
export type { StaticFileItemResponseModel } from './models/StaticFileItemResponseModel';
export { StatusResultTypeModel } from './models/StatusResultTypeModel';
export type { StylesheetItemResponseModel } from './models/StylesheetItemResponseModel';
export type { TagResponseModel } from './models/TagResponseModel';
export { TelemetryLevelModel } from './models/TelemetryLevelModel';
export type { TelemetryRepresentationBaseModel } from './models/TelemetryRepresentationBaseModel';
export type { TelemetryRequestModel } from './models/TelemetryRequestModel';
@@ -225,8 +233,10 @@ export type { UpdateUserGroupsOnUserRequestModel } from './models/UpdateUserGrou
export type { UpdateUserRequestModel } from './models/UpdateUserRequestModel';
export type { UpgradeSettingsResponseModel } from './models/UpgradeSettingsResponseModel';
export type { UserGroupBaseModel } from './models/UserGroupBaseModel';
export type { UserGroupItemResponseModel } from './models/UserGroupItemResponseModel';
export type { UserGroupPresentationModel } from './models/UserGroupPresentationModel';
export type { UserInstallResponseModel } from './models/UserInstallResponseModel';
export type { UserItemResponseModel } from './models/UserItemResponseModel';
export { UserOrderModel } from './models/UserOrderModel';
export type { UserPresentationBaseModel } from './models/UserPresentationBaseModel';
export type { UserResponseModel } from './models/UserResponseModel';
@@ -252,6 +262,7 @@ export { LanguageResource } from './services/LanguageResource';
export { LogViewerResource } from './services/LogViewerResource';
export { MediaResource } from './services/MediaResource';
export { MediaTypeResource } from './services/MediaTypeResource';
export { MemberResource } from './services/MemberResource';
export { MemberGroupResource } from './services/MemberGroupResource';
export { MemberTypeResource } from './services/MemberTypeResource';
export { ModelsBuilderResource } from './services/ModelsBuilderResource';
@@ -259,6 +270,7 @@ export { ObjectTypesResource } from './services/ObjectTypesResource';
export { PackageResource } from './services/PackageResource';
export { PartialViewResource } from './services/PartialViewResource';
export { ProfilingResource } from './services/ProfilingResource';
export { PropertyTypeResource } from './services/PropertyTypeResource';
export { PublishedCacheResource } from './services/PublishedCacheResource';
export { RedirectManagementResource } from './services/RedirectManagementResource';
export { RelationResource } from './services/RelationResource';
@@ -269,11 +281,11 @@ export { SecurityResource } from './services/SecurityResource';
export { ServerResource } from './services/ServerResource';
export { StaticFileResource } from './services/StaticFileResource';
export { StylesheetResource } from './services/StylesheetResource';
export { TagResource } from './services/TagResource';
export { TelemetryResource } from './services/TelemetryResource';
export { TemplateResource } from './services/TemplateResource';
export { TemporaryFileResource } from './services/TemporaryFileResource';
export { TrackedReferenceResource } from './services/TrackedReferenceResource';
export { UpgradeResource } from './services/UpgradeResource';
export { UserGroupsResource } from './services/UserGroupsResource';
export { UsersResource } from './services/UsersResource';
export { V1Resource } from './services/V1Resource';
export { UserResource } from './services/UserResource';
export { UserGroupResource } from './services/UserGroupResource';

View File

@@ -0,0 +1,10 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type CopyDocumentRequestModel = {
targetId?: string | null;
relateToOriginal?: boolean;
includeDescendants?: boolean;
};

View File

@@ -4,8 +4,9 @@
import type { DataTypeModelBaseModel } from './DataTypeModelBaseModel';
export type DataTypeResponseModel = DataTypeModelBaseModel & {
$type: string;
id?: string;
parentId?: string | null;
};
export type DataTypeResponseModel = (DataTypeModelBaseModel & {
$type: string;
id?: string;
parentId?: string | null;
});

View File

@@ -0,0 +1,9 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type LoginRequestModel = {
username?: string;
password?: string;
};

View File

@@ -0,0 +1,10 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { ItemResponseModelBaseModel } from './ItemResponseModelBaseModel';
export type MemberItemResponseModel = (ItemResponseModelBaseModel & {
icon?: string | null;
});

View File

@@ -0,0 +1,8 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type MoveDocumentRequestModel = {
targetId?: string | null;
};

View File

@@ -0,0 +1,8 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type MoveMediaRequestModel = {
targetId?: string | null;
};

View File

@@ -0,0 +1,9 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type PagedBooleanModel = {
total: number;
items: Array<boolean>;
};

View File

@@ -0,0 +1,11 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { TagResponseModel } from './TagResponseModel';
export type PagedTagResponseModel = {
total: number;
items: Array<TagResponseModel>;
};

View File

@@ -6,14 +6,15 @@ import type { PropertyTypeAppearanceModel } from './PropertyTypeAppearanceModel'
import type { PropertyTypeValidationModel } from './PropertyTypeValidationModel';
export type PropertyTypeResponseModelBaseModel = {
id?: string;
containerId?: string | null;
alias?: string;
name?: string;
description?: string | null;
dataTypeId?: string;
variesByCulture?: boolean;
variesBySegment?: boolean;
validation?: PropertyTypeValidationModel;
appearance?: PropertyTypeAppearanceModel;
id?: string;
containerId?: string | null;
alias?: string;
name?: string;
description?: string | null;
dataTypeId?: string;
variesByCulture?: boolean;
variesBySegment?: boolean;
validation?: PropertyTypeValidationModel;
appearance?: PropertyTypeAppearanceModel;
};

View File

@@ -0,0 +1,11 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type TagResponseModel = {
id?: string;
text?: string | null;
group?: string | null;
nodeCount?: number;
};

View File

@@ -0,0 +1,10 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { ItemResponseModelBaseModel } from './ItemResponseModelBaseModel';
export type UserGroupItemResponseModel = (ItemResponseModelBaseModel & {
icon?: string | null;
});

View File

@@ -0,0 +1,8 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { ItemResponseModelBaseModel } from './ItemResponseModelBaseModel';
export type UserItemResponseModel = ItemResponseModelBaseModel;

View File

@@ -136,6 +136,27 @@ export class DataTypeResource {
});
}
/**
* @returns boolean Success
* @throws ApiError
*/
public static getDataTypeByIdIsUsed({
id,
}: {
id: string,
}): CancelablePromise<boolean> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/data-type/{id}/is-used',
path: {
'id': id,
},
errors: {
404: `Not Found`,
},
});
}
/**
* @returns any Success
* @throws ApiError

View File

@@ -1,10 +1,12 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { CopyDocumentRequestModel } from '../models/CopyDocumentRequestModel';
import type { CreateDocumentRequestModel } from '../models/CreateDocumentRequestModel';
import type { DocumentItemResponseModel } from '../models/DocumentItemResponseModel';
import type { DocumentNotificationResponseModel } from '../models/DocumentNotificationResponseModel';
import type { DocumentResponseModel } from '../models/DocumentResponseModel';
import type { MoveDocumentRequestModel } from '../models/MoveDocumentRequestModel';
import type { PagedDocumentTreeItemResponseModel } from '../models/PagedDocumentTreeItemResponseModel';
import type { PagedRecycleBinItemResponseModel } from '../models/PagedRecycleBinItemResponseModel';
import type { UpdateDocumentNotificationsRequestModel } from '../models/UpdateDocumentNotificationsRequestModel';
@@ -108,6 +110,33 @@ export class DocumentResource {
});
}
/**
* @returns string Created
* @throws ApiError
*/
public static postDocumentByIdCopy({
id,
requestBody,
}: {
id: string,
requestBody?: CopyDocumentRequestModel,
}): CancelablePromise<string> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/document/{id}/copy',
path: {
'id': id,
},
body: requestBody,
mediaType: 'application/json',
responseHeader: 'Location',
errors: {
400: `Bad Request`,
404: `Not Found`,
},
});
}
/**
* @returns any Success
* @throws ApiError
@@ -148,6 +177,32 @@ export class DocumentResource {
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static putDocumentByIdMove({
id,
requestBody,
}: {
id: string,
requestBody?: MoveDocumentRequestModel,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'PUT',
url: '/umbraco/management/api/v1/document/{id}/move',
path: {
'id': id,
},
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
404: `Not Found`,
},
});
}
/**
* @returns any Success
* @throws ApiError

View File

@@ -6,6 +6,7 @@ import type { CreateMediaRequestModel } from '../models/CreateMediaRequestModel'
import type { DocumentResponseModel } from '../models/DocumentResponseModel';
import type { DocumentTreeItemResponseModel } from '../models/DocumentTreeItemResponseModel';
import type { MediaItemResponseModel } from '../models/MediaItemResponseModel';
import type { MoveMediaRequestModel } from '../models/MoveMediaRequestModel';
import type { PagedContentTreeItemResponseModel } from '../models/PagedContentTreeItemResponseModel';
import type { PagedRecycleBinItemResponseModel } from '../models/PagedRecycleBinItemResponseModel';
import type { UpdateMediaRequestModel } from '../models/UpdateMediaRequestModel';
@@ -107,6 +108,32 @@ export class MediaResource {
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static putMediaByIdMove({
id,
requestBody,
}: {
id: string,
requestBody?: MoveMediaRequestModel,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'PUT',
url: '/umbraco/management/api/v1/media/{id}/move',
path: {
'id': id,
},
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
404: `Not Found`,
},
});
}
/**
* @returns any Success
* @throws ApiError

View File

@@ -1,28 +1,28 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { StaticFileItemResponseModel } from '../models/StaticFileItemResponseModel';
import type { MemberItemResponseModel } from '../models/MemberItemResponseModel';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class V1Resource {
export class MemberResource {
/**
* @returns any Success
* @throws ApiError
*/
public static getItem({
path,
public static getMemberItem({
id,
}: {
path?: Array<string>,
}): CancelablePromise<Array<StaticFileItemResponseModel>> {
id?: Array<string>,
}): CancelablePromise<Array<MemberItemResponseModel>> {
return __request(OpenAPI, {
method: 'GET',
url: '/item',
url: '/umbraco/management/api/v1/member/item',
query: {
'path': path,
'id': id,
},
});
}

View File

@@ -0,0 +1,36 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { PagedBooleanModel } from '../models/PagedBooleanModel';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class PropertyTypeResource {
/**
* @returns PagedBooleanModel Success
* @throws ApiError
*/
public static getPropertyTypeIsUsed({
contentTypeId,
propertyAlias,
}: {
contentTypeId?: string,
propertyAlias?: string,
}): CancelablePromise<PagedBooleanModel> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/property-type/is-used',
query: {
'contentTypeId': contentTypeId,
'propertyAlias': propertyAlias,
},
errors: {
400: `Bad Request`,
},
});
}
}

View File

@@ -1,6 +1,8 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { LoginRequestModel } from '../models/LoginRequestModel';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
@@ -22,10 +24,16 @@ export class SecurityResource {
* @returns any Success
* @throws ApiError
*/
public static postSecurityBackOfficeAuthorize(): CancelablePromise<any> {
public static postSecurityBackOfficeLogin({
requestBody,
}: {
requestBody?: LoginRequestModel,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/security/back-office/authorize',
url: '/umbraco/management/api/v1/security/back-office/login',
body: requestBody,
mediaType: 'application/json',
});
}

View File

@@ -2,6 +2,7 @@
/* tslint:disable */
/* eslint-disable */
import type { PagedFileSystemTreeItemPresentationModel } from '../models/PagedFileSystemTreeItemPresentationModel';
import type { StaticFileItemResponseModel } from '../models/StaticFileItemResponseModel';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
@@ -9,6 +10,24 @@ import { request as __request } from '../core/request';
export class StaticFileResource {
/**
* @returns any Success
* @throws ApiError
*/
public static getStaticFileItem({
path,
}: {
path?: Array<string>,
}): CancelablePromise<Array<StaticFileItemResponseModel>> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/static-file/item',
query: {
'path': path,
},
});
}
/**
* @returns PagedFileSystemTreeItemPresentationModel Success
* @throws ApiError

View File

@@ -0,0 +1,42 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { PagedTagResponseModel } from '../models/PagedTagResponseModel';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class TagResource {
/**
* @returns PagedTagResponseModel Success
* @throws ApiError
*/
public static getTag({
query,
tagGroup,
culture,
skip,
take = 100,
}: {
query?: string,
tagGroup?: string,
culture?: string,
skip?: number,
take?: number,
}): CancelablePromise<PagedTagResponseModel> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/tag',
query: {
'query': query,
'tagGroup': tagGroup,
'culture': culture,
'skip': skip,
'take': take,
},
});
}
}

View File

@@ -4,26 +4,27 @@
import type { PagedUserGroupPresentationModel } from '../models/PagedUserGroupPresentationModel';
import type { SaveUserGroupRequestModel } from '../models/SaveUserGroupRequestModel';
import type { UpdateUserGroupRequestModel } from '../models/UpdateUserGroupRequestModel';
import type { UserGroupItemResponseModel } from '../models/UserGroupItemResponseModel';
import type { UserGroupPresentationModel } from '../models/UserGroupPresentationModel';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class UserGroupsResource {
export class UserGroupResource {
/**
* @returns string Created
* @throws ApiError
*/
public static postUserGroups({
public static postUserGroup({
requestBody,
}: {
requestBody?: SaveUserGroupRequestModel,
}): CancelablePromise<string> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/user-groups',
url: '/umbraco/management/api/v1/user-group',
body: requestBody,
mediaType: 'application/json',
responseHeader: 'Location',
@@ -37,7 +38,7 @@ export class UserGroupsResource {
* @returns PagedUserGroupPresentationModel Success
* @throws ApiError
*/
public static getUserGroups({
public static getUserGroup({
skip,
take = 100,
}: {
@@ -46,7 +47,7 @@ export class UserGroupsResource {
}): CancelablePromise<PagedUserGroupPresentationModel> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/user-groups',
url: '/umbraco/management/api/v1/user-group',
query: {
'skip': skip,
'take': take,
@@ -58,14 +59,14 @@ export class UserGroupsResource {
* @returns any Success
* @throws ApiError
*/
public static getUserGroupsById({
public static getUserGroupById({
id,
}: {
id: string,
}): CancelablePromise<UserGroupPresentationModel> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/user-groups/{id}',
url: '/umbraco/management/api/v1/user-group/{id}',
path: {
'id': id,
},
@@ -79,14 +80,14 @@ export class UserGroupsResource {
* @returns any Success
* @throws ApiError
*/
public static deleteUserGroupsById({
public static deleteUserGroupById({
id,
}: {
id: string,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/umbraco/management/api/v1/user-groups/{id}',
url: '/umbraco/management/api/v1/user-group/{id}',
path: {
'id': id,
},
@@ -100,7 +101,7 @@ export class UserGroupsResource {
* @returns any Success
* @throws ApiError
*/
public static putUserGroupsById({
public static putUserGroupById({
id,
requestBody,
}: {
@@ -109,7 +110,7 @@ export class UserGroupsResource {
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'PUT',
url: '/umbraco/management/api/v1/user-groups/{id}',
url: '/umbraco/management/api/v1/user-group/{id}',
path: {
'id': id,
},
@@ -121,4 +122,22 @@ export class UserGroupsResource {
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static getUserGroupItem({
id,
}: {
id?: Array<string>,
}): CancelablePromise<Array<UserGroupItemResponseModel>> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/user-group/item',
query: {
'id': id,
},
});
}
}

View File

@@ -0,0 +1,324 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { ChangePasswordUserRequestModel } from '../models/ChangePasswordUserRequestModel';
import type { CreateUserRequestModel } from '../models/CreateUserRequestModel';
import type { CreateUserResponseModel } from '../models/CreateUserResponseModel';
import type { DirectionModel } from '../models/DirectionModel';
import type { DisableUserRequestModel } from '../models/DisableUserRequestModel';
import type { EnableUserRequestModel } from '../models/EnableUserRequestModel';
import type { InviteUserRequestModel } from '../models/InviteUserRequestModel';
import type { PagedUserResponseModel } from '../models/PagedUserResponseModel';
import type { SetAvatarRequestModel } from '../models/SetAvatarRequestModel';
import type { UnlockUsersRequestModel } from '../models/UnlockUsersRequestModel';
import type { UpdateUserGroupsOnUserRequestModel } from '../models/UpdateUserGroupsOnUserRequestModel';
import type { UpdateUserRequestModel } from '../models/UpdateUserRequestModel';
import type { UserItemResponseModel } from '../models/UserItemResponseModel';
import type { UserOrderModel } from '../models/UserOrderModel';
import type { UserResponseModel } from '../models/UserResponseModel';
import type { UserStateModel } from '../models/UserStateModel';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class UserResource {
/**
* @returns any Success
* @throws ApiError
*/
public static postUser({
requestBody,
}: {
requestBody?: CreateUserRequestModel | InviteUserRequestModel;
}): CancelablePromise<CreateUserResponseModel> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/user',
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
},
});
}
/**
* @returns PagedUserResponseModel Success
* @throws ApiError
*/
public static getUser({
skip,
take = 100,
}: {
skip?: number;
take?: number;
}): CancelablePromise<PagedUserResponseModel> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/user',
query: {
skip: skip,
take: take,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static getUserById({ id }: { id: string }): CancelablePromise<UserResponseModel> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/user/{id}',
path: {
id: id,
},
errors: {
404: `Not Found`,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static deleteUserById({ id }: { id: string }): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/umbraco/management/api/v1/user/{id}',
path: {
id: id,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static putUserById({
id,
requestBody,
}: {
id: string;
requestBody?: UpdateUserRequestModel;
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'PUT',
url: '/umbraco/management/api/v1/user/{id}',
path: {
id: id,
},
body: requestBody,
mediaType: 'application/json',
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static deleteUserAvatarById({ id }: { id: string }): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/umbraco/management/api/v1/user/avatar/{id}',
path: {
id: id,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUserAvatarById({
id,
requestBody,
}: {
id: string;
requestBody?: SetAvatarRequestModel;
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/user/avatar/{id}',
path: {
id: id,
},
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUserChangePasswordById({
id,
requestBody,
}: {
id: string;
requestBody?: ChangePasswordUserRequestModel;
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/user/change-password/{id}',
path: {
id: id,
},
body: requestBody,
mediaType: 'application/json',
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUserDisable({ requestBody }: { requestBody?: DisableUserRequestModel }): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/user/disable',
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUserEnable({ requestBody }: { requestBody?: EnableUserRequestModel }): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/user/enable',
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static getUserFilter({
skip,
take = 100,
orderBy,
orderDirection,
userGroupIds,
userStates,
filter = '',
}: {
skip?: number;
take?: number;
orderBy?: UserOrderModel;
orderDirection?: DirectionModel;
userGroupIds?: Array<string>;
userStates?: Array<UserStateModel>;
filter?: string;
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/user/filter',
query: {
skip: skip,
take: take,
orderBy: orderBy,
orderDirection: orderDirection,
userGroupIds: userGroupIds,
userStates: userStates,
filter: filter,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUserInvite({ requestBody }: { requestBody?: InviteUserRequestModel }): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/user/invite',
body: requestBody,
mediaType: 'application/json',
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static getUserItem({ id }: { id?: Array<string> }): CancelablePromise<Array<UserItemResponseModel>> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/user/item',
query: {
id: id,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUserSetUserGroups({
requestBody,
}: {
requestBody?: UpdateUserGroupsOnUserRequestModel;
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/user/set-user-groups',
body: requestBody,
mediaType: 'application/json',
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUserUnlock({ requestBody }: { requestBody?: UnlockUsersRequestModel }): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/user/unlock',
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUsersUnlock({ requestBody }: { requestBody?: UnlockUsersRequestModel }): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/users/unlock',
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
},
});
}
}

View File

@@ -1,323 +0,0 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { ChangePasswordUserRequestModel } from '../models/ChangePasswordUserRequestModel';
import type { CreateUserRequestModel } from '../models/CreateUserRequestModel';
import type { CreateUserResponseModel } from '../models/CreateUserResponseModel';
import type { DirectionModel } from '../models/DirectionModel';
import type { DisableUserRequestModel } from '../models/DisableUserRequestModel';
import type { EnableUserRequestModel } from '../models/EnableUserRequestModel';
import type { InviteUserRequestModel } from '../models/InviteUserRequestModel';
import type { PagedUserResponseModel } from '../models/PagedUserResponseModel';
import type { SetAvatarRequestModel } from '../models/SetAvatarRequestModel';
import type { UnlockUsersRequestModel } from '../models/UnlockUsersRequestModel';
import type { UpdateUserGroupsOnUserRequestModel } from '../models/UpdateUserGroupsOnUserRequestModel';
import type { UpdateUserRequestModel } from '../models/UpdateUserRequestModel';
import type { UserOrderModel } from '../models/UserOrderModel';
import type { UserResponseModel } from '../models/UserResponseModel';
import type { UserStateModel } from '../models/UserStateModel';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class UsersResource {
/**
* @returns any Success
* @throws ApiError
*/
public static postUsers({
requestBody,
}: {
requestBody?: (CreateUserRequestModel | InviteUserRequestModel),
}): CancelablePromise<CreateUserResponseModel> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/users',
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
},
});
}
/**
* @returns PagedUserResponseModel Success
* @throws ApiError
*/
public static getUsers({
skip,
take = 100,
}: {
skip?: number,
take?: number,
}): CancelablePromise<PagedUserResponseModel> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/users',
query: {
'skip': skip,
'take': take,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static getUsersById({
id,
}: {
id: string,
}): CancelablePromise<UserResponseModel> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/users/{id}',
path: {
'id': id,
},
errors: {
404: `Not Found`,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static deleteUsersById({
id,
}: {
id: string,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/umbraco/management/api/v1/users/{id}',
path: {
'id': id,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static putUsersById({
id,
requestBody,
}: {
id: string,
requestBody?: UpdateUserRequestModel,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'PUT',
url: '/umbraco/management/api/v1/users/{id}',
path: {
'id': id,
},
body: requestBody,
mediaType: 'application/json',
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static deleteUsersAvatarById({
id,
}: {
id: string,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/umbraco/management/api/v1/users/avatar/{id}',
path: {
'id': id,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUsersAvatarById({
id,
requestBody,
}: {
id: string,
requestBody?: SetAvatarRequestModel,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/users/avatar/{id}',
path: {
'id': id,
},
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUsersChangePasswordById({
id,
requestBody,
}: {
id: string,
requestBody?: ChangePasswordUserRequestModel,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/users/change-password/{id}',
path: {
'id': id,
},
body: requestBody,
mediaType: 'application/json',
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUsersDisable({
requestBody,
}: {
requestBody?: DisableUserRequestModel,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/users/disable',
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUsersEnable({
requestBody,
}: {
requestBody?: EnableUserRequestModel,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/users/enable',
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static getUsersFilter({
skip,
take = 100,
orderBy,
orderDirection,
userGroupIds,
userStates,
filter = '',
}: {
skip?: number,
take?: number,
orderBy?: UserOrderModel,
orderDirection?: DirectionModel,
userGroupIds?: Array<string>,
userStates?: Array<UserStateModel>,
filter?: string,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/umbraco/management/api/v1/users/filter',
query: {
'skip': skip,
'take': take,
'orderBy': orderBy,
'orderDirection': orderDirection,
'userGroupIds': userGroupIds,
'userStates': userStates,
'filter': filter,
},
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUsersInvite({
requestBody,
}: {
requestBody?: InviteUserRequestModel,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/users/invite',
body: requestBody,
mediaType: 'application/json',
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUsersSetUserGroups({
requestBody,
}: {
requestBody?: UpdateUserGroupsOnUserRequestModel,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/users/set-user-groups',
body: requestBody,
mediaType: 'application/json',
});
}
/**
* @returns any Success
* @throws ApiError
*/
public static postUsersUnlock({
requestBody,
}: {
requestBody?: UnlockUsersRequestModel,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'POST',
url: '/umbraco/management/api/v1/users/unlock',
body: requestBody,
mediaType: 'application/json',
errors: {
400: `Bad Request`,
},
});
}
}

View File

@@ -0,0 +1,149 @@
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
import {
UmbArrayState,
UmbNumberState,
UmbObjectState,
UmbObserverController,
} from '@umbraco-cms/backoffice/observable-api';
import { umbExtensionsRegistry, createExtensionClass } from '@umbraco-cms/backoffice/extensions-api';
import { UmbCollectionRepository } from '@umbraco-cms/backoffice/repository';
import type { UmbFilterModel } from '@umbraco-cms/backoffice/models';
// TODO: Clean up the need for store as Media has switched to use Repositories(repository).
export class UmbCollectionContext<ItemType, FilterModelType extends UmbFilterModel> {
private _host: UmbControllerHostElement;
private _entityType: string | null;
protected _dataObserver?: UmbObserverController<ItemType[]>;
#items = new UmbArrayState<ItemType>([]);
public readonly items = this.#items.asObservable();
#total = new UmbNumberState(0);
public readonly total = this.#total.asObservable();
#selection = new UmbArrayState<string>([]);
public readonly selection = this.#selection.asObservable();
#filter = new UmbObjectState<FilterModelType | object>({});
public readonly filter = this.#filter.asObservable();
repository?: UmbCollectionRepository;
/*
TODO:
private _search = new StringState('');
public readonly search = this._search.asObservable();
*/
constructor(host: UmbControllerHostElement, entityType: string | null, repositoryAlias: string) {
this._entityType = entityType;
this._host = host;
new UmbObserverController(
this._host,
umbExtensionsRegistry.getByTypeAndAlias('repository', repositoryAlias),
async (repositoryManifest) => {
if (repositoryManifest) {
const result = await createExtensionClass<UmbCollectionRepository>(repositoryManifest, [this._host]);
this.repository = result;
this._onRepositoryReady();
}
}
);
}
public isSelected(id: string) {
return this.#selection.getValue().includes(id);
}
public setSelection(value: Array<string>) {
if (!value) return;
this.#selection.next(value);
}
public clearSelection() {
this.#selection.next([]);
}
public select(id: string) {
this.#selection.appendOne(id);
}
public deselect(id: string) {
this.#selection.filter((k) => k !== id);
}
// TODO: how can we make sure to call this.
public destroy(): void {
this.#items.unsubscribe();
}
public getEntityType() {
return this._entityType;
}
/*
public getData() {
return this.#data.getValue();
}
*/
/*
public update(data: Partial<DataType>) {
this._data.next({ ...this.getData(), ...data });
}
*/
// protected _onStoreSubscription(): void {
// if (!this._store) {
// return;
// }
// this._dataObserver?.destroy();
// if (this._entityId) {
// this._dataObserver = new UmbObserverController(
// this._host,
// this._store.getTreeItemChildren(this._entityId),
// (nodes) => {
// if (nodes) {
// this.#data.next(nodes);
// }
// }
// );
// } else {
// this._dataObserver = new UmbObserverController(this._host, this._store.getTreeRoot(), (nodes) => {
// if (nodes) {
// this.#data.next(nodes);
// }
// });
// }
// }
protected async _onRepositoryReady() {
if (!this.repository) return;
this.requestCollection();
}
public async requestCollection() {
if (!this.repository) return;
const filter = this.#filter.getValue();
const { data } = await this.repository.requestCollection(filter);
if (data) {
this.#total.next(data.total);
this.#items.next(data.items);
}
}
// TODO: find better name
setFilter(filter: Partial<FilterModelType>) {
this.#filter.next({ ...this.#filter.getValue(), ...filter });
this.requestCollection();
}
}
export const UMB_COLLECTION_CONTEXT_TOKEN = new UmbContextToken<UmbCollectionContext<any, any>>('UmbCollectionContext');

View File

@@ -0,0 +1 @@
export * from './collection.context';

View File

@@ -0,0 +1,182 @@
import { PropertyContainerTypes, UmbContentTypePropertyStructureManager } from './content-type-structure-manager.class';
import { PropertyTypeContainerResponseModelBaseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
import { UmbArrayState, UmbBooleanState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
export class UmbContentTypeContainerStructureHelper {
#host: UmbControllerHostElement;
#init;
#initResolver?: (value: unknown) => void;
#structure?: UmbContentTypePropertyStructureManager;
private _ownerType?: PropertyContainerTypes = 'Tab';
private _childType?: PropertyContainerTypes = 'Group';
private _isRoot = false;
private _ownerName?: string;
private _ownerKey?: string;
// Containers defined in data might be more than actual containers to display as we merge them by name.
// Owner containers are the containers defining the total of this container(Multiple containers with the same name and type)
private _ownerContainers: PropertyTypeContainerResponseModelBaseModel[] = [];
// State containing the merged containers (only one pr. name):
#containers = new UmbArrayState<PropertyTypeContainerResponseModelBaseModel>([], (x) => x.id);
readonly containers = this.#containers.asObservable();
#hasProperties = new UmbBooleanState(false);
readonly hasProperties = this.#hasProperties.asObservable();
constructor(host: UmbControllerHostElement) {
this.#host = host;
this.#init = new Promise((resolve) => {
this.#initResolver = resolve;
});
this.#containers.sortBy((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
}
public setStructureManager(structure: UmbContentTypePropertyStructureManager) {
this.#structure = structure;
this.#initResolver?.(undefined);
this.#initResolver = undefined;
this._observeOwnerContainers();
}
public setType(value?: PropertyContainerTypes) {
if (this._ownerType === value) return;
this._ownerType = value;
this._observeOwnerContainers();
}
public getType() {
return this._ownerType;
}
public setContainerChildType(value?: PropertyContainerTypes) {
if (this._childType === value) return;
this._childType = value;
this._observeOwnerContainers();
}
public getContainerChildType() {
return this._childType;
}
public setName(value?: string) {
if (this._ownerName === value) return;
this._ownerName = value;
this._observeOwnerContainers();
}
public getName() {
return this._ownerName;
}
public setIsRoot(value: boolean) {
if (this._isRoot === value) return;
this._isRoot = value;
this._observeOwnerContainers();
}
public getIsRoot() {
return this._isRoot;
}
private _observeOwnerContainers() {
if (!this.#structure) return;
if (this._isRoot) {
this.#containers.next([]);
// We cannot have root properties currently, therefor we set it to false:
this.#hasProperties.next(false);
this._observeRootContainers();
} else if (this._ownerName && this._ownerType) {
new UmbObserverController(
this.#host,
this.#structure.containersByNameAndType(this._ownerName, this._ownerType),
(ownerContainers) => {
this.#containers.next([]);
this._ownerContainers = ownerContainers || [];
if (this._ownerContainers.length > 0) {
this._observeOwnerProperties();
this._observeChildContainers();
}
},
'_observeOwnerContainers'
);
}
}
private _observeOwnerProperties() {
if (!this.#structure) return;
this._ownerContainers.forEach((container) => {
new UmbObserverController(
this.#host,
this.#structure!.hasPropertyStructuresOf(container.id!),
(hasProperties) => {
this.#hasProperties.next(hasProperties);
},
'_observeOwnerHasProperties_' + container.id
);
});
}
private _observeChildContainers() {
if (!this.#structure || !this._ownerName || !this._childType) return;
this._ownerContainers.forEach((container) => {
new UmbObserverController(
this.#host,
this.#structure!.containersOfParentKey(container.id, this._childType!),
this._insertGroupContainers,
'_observeGroupsOf_' + container.id
);
});
}
private _observeRootContainers() {
if (!this.#structure || !this._isRoot) return;
new UmbObserverController(
this.#host,
this.#structure.rootContainers(this._childType!),
(rootContainers) => {
this.#containers.next([]);
this._insertGroupContainers(rootContainers);
},
'_observeRootContainers'
);
}
private _insertGroupContainers = (groupContainers: PropertyTypeContainerResponseModelBaseModel[]) => {
groupContainers.forEach((group) => {
if (group.name !== null && group.name !== undefined) {
if (!this.#containers.getValue().find((x) => x.name === group.name)) {
this.#containers.appendOne(group);
}
}
});
};
/**
* Returns true if the container is an owner container.
*/
isOwnerContainer(groupId?: string) {
if (!this.#structure || !groupId) return;
return this._ownerContainers.find((x) => x.id === groupId) !== undefined;
}
/** Manipulate methods: */
async addContainer(ownerId?: string, sortOrder?: number) {
if (!this.#structure) return;
await this.#structure.createContainer(null, ownerId, this._childType, sortOrder);
}
async partialUpdateContainer(groupId?: string, partialUpdate?: Partial<PropertyTypeContainerResponseModelBaseModel>) {
await this.#init;
if (!this.#structure || !groupId || !partialUpdate) return;
return await this.#structure.updateContainer(null, groupId, partialUpdate);
}
}

View File

@@ -0,0 +1,142 @@
import { PropertyContainerTypes, UmbContentTypePropertyStructureManager } from './content-type-structure-manager.class';
import {
DocumentTypePropertyTypeResponseModel,
PropertyTypeResponseModelBaseModel,
} from '@umbraco-cms/backoffice/backend-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
import { UmbArrayState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
export class UmbContentTypePropertyStructureHelper {
#host: UmbControllerHostElement;
#init;
#initResolver?: (value: unknown) => void;
#structure?: UmbContentTypePropertyStructureManager;
private _containerType?: PropertyContainerTypes;
private _isRoot?: boolean;
private _containerName?: string;
#propertyStructure = new UmbArrayState<DocumentTypePropertyTypeResponseModel>([], (x) => x.id);
readonly propertyStructure = this.#propertyStructure.asObservable();
constructor(host: UmbControllerHostElement) {
this.#host = host;
this.#init = new Promise((resolve) => {
this.#initResolver = resolve;
});
// TODO: Remove as any when sortOrder is implemented:
this.#propertyStructure.sortBy((a, b) => ((a as any).sortOrder ?? 0) - ((b as any).sortOrder ?? 0));
}
public setStructureManager(structure: UmbContentTypePropertyStructureManager) {
this.#structure = structure;
this.#initResolver?.(undefined);
this.#initResolver = undefined;
this._observeGroupContainers();
}
public setContainerType(value?: PropertyContainerTypes) {
if (this._containerType === value) return;
this._containerType = value;
this._observeGroupContainers();
}
public getContainerType() {
return this._containerType;
}
public setContainerName(value?: string) {
if (this._containerName === value) return;
this._containerName = value;
this._observeGroupContainers();
}
public getContainerName() {
return this._containerName;
}
public setIsRoot(value: boolean) {
if (this._isRoot === value) return;
this._isRoot = value;
this._observeGroupContainers();
}
public getIsRoot() {
return this._isRoot;
}
private _observeGroupContainers() {
if (!this.#structure || !this._containerType) return;
if (this._isRoot === true) {
this._observePropertyStructureOf(null);
} else if (this._containerName !== undefined) {
new UmbObserverController(
this.#host,
this.#structure.containersByNameAndType(this._containerName, this._containerType),
(groupContainers) => {
groupContainers.forEach((group) => this._observePropertyStructureOf(group.id));
},
'_observeGroupContainers'
);
}
}
private _observePropertyStructureOf(groupId?: string | null) {
if (!this.#structure || groupId === undefined) return;
new UmbObserverController(
this.#host,
this.#structure.propertyStructuresOf(groupId),
(properties) => {
// If this need to be able to remove properties, we need to clean out the ones of this group.id before inserting them:
const _propertyStructure = this.#propertyStructure.getValue().filter((x) => x.containerId !== groupId);
properties?.forEach((property) => {
if (!_propertyStructure.find((x) => x.alias === property.alias)) {
_propertyStructure.push(property);
}
});
// Fire update to subscribers:
this.#propertyStructure.next(_propertyStructure);
},
'_observePropertyStructureOfGroup' + groupId
);
}
// TODO: consider moving this to another class, to separate 'viewer' from 'manipulator':
/** Manipulate methods: */
async addProperty(ownerId?: string, sortOrder?: number) {
await this.#init;
if (!this.#structure) return;
return await this.#structure.createProperty(null, ownerId, sortOrder);
}
async insertProperty(property: PropertyTypeResponseModelBaseModel, sortOrder = 0) {
await this.#init;
if (!this.#structure) return false;
const newProperty = { ...property, sortOrder };
// TODO: Remove as any when server model has gotten sortOrder:
await this.#structure.insertProperty(null, newProperty);
return true;
}
async removeProperty(propertyId: string) {
await this.#init;
if (!this.#structure) return false;
await this.#structure.removeProperty(null, propertyId);
return true;
}
// Takes optional arguments as this is easier for the implementation in the view:
async partialUpdateProperty(propertyKey?: string, partialUpdate?: Partial<DocumentTypePropertyTypeResponseModel>) {
await this.#init;
if (!this.#structure || !propertyKey || !partialUpdate) return;
return await this.#structure.updateProperty(null, propertyKey, partialUpdate);
}
}

View File

@@ -0,0 +1,341 @@
import { UmbDetailRepository } from '../repository';
import { UmbId } from '@umbraco-cms/backoffice/id';
import {
DocumentTypePropertyTypeResponseModel,
PropertyTypeContainerResponseModelBaseModel,
PropertyTypeResponseModelBaseModel,
DocumentTypeResponseModel,
} from '@umbraco-cms/backoffice/backend-api';
import { UmbControllerHostElement, UmbControllerInterface } from '@umbraco-cms/backoffice/controller';
import {
UmbArrayState,
UmbObserverController,
MappingFunction,
partialUpdateFrozenArray,
appendToFrozenArray,
filterFrozenArray,
} from '@umbraco-cms/backoffice/observable-api';
export type PropertyContainerTypes = 'Group' | 'Tab';
type T = DocumentTypeResponseModel;
// TODO: get this type from the repository, or use some generic type.
export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepository<T> = UmbDetailRepository<T>> {
#host: UmbControllerHostElement;
#init!: Promise<unknown>;
#contentTypeRepository: R;
#rootDocumentTypeId?: string;
#documentTypeObservers = new Array<UmbControllerInterface>();
#documentTypes = new UmbArrayState<T>([], (x) => x.id);
readonly documentTypes = this.#documentTypes.asObservable();
private readonly _documentTypeContainers = this.#documentTypes.getObservablePart((x) =>
x.flatMap((x) => x.containers ?? [])
);
#containers = new UmbArrayState<PropertyTypeContainerResponseModelBaseModel>([], (x) => x.id);
constructor(host: UmbControllerHostElement, typeRepository: R) {
this.#host = host;
this.#contentTypeRepository = typeRepository;
new UmbObserverController(host, this.documentTypes, (documentTypes) => {
documentTypes.forEach((documentType) => {
this._loadDocumentTypeCompositions(documentType);
});
});
new UmbObserverController(host, this._documentTypeContainers, (documentTypeContainers) => {
this.#containers.next(documentTypeContainers);
});
}
/**
* loadType will load the node type and all inherited and composed types.
* This will give us all the structure for properties and containers.
*/
public async loadType(id?: string) {
this._reset();
this.#rootDocumentTypeId = id;
const promiseResult = this._loadType(id);
this.#init = promiseResult;
await this.#init;
return promiseResult;
}
public async createScaffold(parentId: string) {
this._reset();
if (!parentId) return {};
const { data } = await this.#contentTypeRepository.createScaffold(parentId);
if (!data) return {};
this.#rootDocumentTypeId = data.id;
this.#init = this._observeDocumentType(data);
await this.#init;
return { data };
}
private async _ensureType(id?: string) {
if (!id) return;
if (this.#documentTypes.getValue().find((x) => x.id === id)) return;
await this._loadType(id);
}
private async _loadType(id?: string) {
if (!id) return {};
const { data } = await this.#contentTypeRepository.requestById(id);
if (!data) return {};
await this._observeDocumentType(data);
return { data };
}
public async _observeDocumentType(data: T) {
if (!data.id) return;
// Load inherited and composed types:
this._loadDocumentTypeCompositions(data);
this.#documentTypeObservers.push(
new UmbObserverController(this.#host, await this.#contentTypeRepository.byId(data.id), (docType) => {
if (docType) {
// TODO: Handle if there was changes made to the owner document type in this context.
/*
possible easy solutions could be to notify user wether they want to update(Discard the changes to accept the new ones).
*/
this.#documentTypes.appendOne(docType);
}
})
);
}
private async _loadDocumentTypeCompositions(documentType: T) {
documentType.compositions?.forEach((composition) => {
this._ensureType(composition.id);
});
}
/*
private async _initDocumentTypeContainers(documentType: T) {
documentType.containers?.forEach((container) => {
this.#containers.appendOne({ ...container, _ownerDocumentTypeKey: documentType.id });
});
}
*/
/** Public methods for consuming structure: */
rootDocumentType() {
return this.#documentTypes.getObservablePart((x) => x.find((y) => y.id === this.#rootDocumentTypeId));
}
getRootDocumentType() {
return this.#documentTypes.getValue().find((y) => y.id === this.#rootDocumentTypeId);
}
updateRootDocumentType(entry: T) {
this.#documentTypes.updateOne(this.#rootDocumentTypeId, entry);
}
// We could move the actions to another class?
async createContainer(
contentTypeId: string | null,
parentId: string | null = null,
type: PropertyContainerTypes = 'Group',
sortOrder?: number
) {
await this.#init;
contentTypeId = contentTypeId ?? this.#rootDocumentTypeId!;
const container: PropertyTypeContainerResponseModelBaseModel = {
id: UmbId.new(),
parentId: parentId,
name: 'New',
type: type,
sortOrder: sortOrder ?? 0,
};
const containers = [...(this.#documentTypes.getValue().find((x) => x.id === contentTypeId)?.containers ?? [])];
containers.push(container);
this.#documentTypes.updateOne(contentTypeId, { containers });
return container;
}
async updateContainer(
documentTypeId: string | null,
groupKey: string,
partialUpdate: Partial<PropertyTypeContainerResponseModelBaseModel>
) {
await this.#init;
documentTypeId = documentTypeId ?? this.#rootDocumentTypeId!;
const frozenContainers = this.#documentTypes.getValue().find((x) => x.id === documentTypeId)?.containers ?? [];
const containers = partialUpdateFrozenArray(frozenContainers, partialUpdate, (x) => x.id === groupKey);
this.#documentTypes.updateOne(documentTypeId, { containers });
}
async removeContainer(documentTypeKey: string | null, containerId: string | null = null) {
await this.#init;
documentTypeKey = documentTypeKey ?? this.#rootDocumentTypeId!;
const frozenContainers = this.#documentTypes.getValue().find((x) => x.id === documentTypeKey)?.containers ?? [];
const containers = frozenContainers.filter((x) => x.id !== containerId);
this.#documentTypes.updateOne(documentTypeKey, { containers });
}
async createProperty(documentTypeId: string | null, containerId: string | null = null, sortOrder?: number) {
await this.#init;
documentTypeId = documentTypeId ?? this.#rootDocumentTypeId!;
const property: PropertyTypeResponseModelBaseModel = {
id: UmbId.new(),
containerId: containerId,
//sortOrder: sortOrder ?? 0,
};
const properties = [...(this.#documentTypes.getValue().find((x) => x.id === documentTypeId)?.properties ?? [])];
properties.push(property);
this.#documentTypes.updateOne(documentTypeId, { properties });
return property;
}
async insertProperty(documentTypeId: string | null, property: PropertyTypeResponseModelBaseModel) {
await this.#init;
documentTypeId = documentTypeId ?? this.#rootDocumentTypeId!;
const frozenProperties = this.#documentTypes.getValue().find((x) => x.id === documentTypeId)?.properties ?? [];
const properties = appendToFrozenArray(frozenProperties, property, (x) => x.id === property.id);
this.#documentTypes.updateOne(documentTypeId, { properties });
}
async removeProperty(documentTypeId: string | null, propertyId: string) {
await this.#init;
documentTypeId = documentTypeId ?? this.#rootDocumentTypeId!;
const frozenProperties = this.#documentTypes.getValue().find((x) => x.id === documentTypeId)?.properties ?? [];
const properties = filterFrozenArray(frozenProperties, (x) => x.id === propertyId);
this.#documentTypes.updateOne(documentTypeId, { properties });
}
async updateProperty(
documentTypeId: string | null,
propertyId: string,
partialUpdate: Partial<PropertyTypeResponseModelBaseModel>
) {
await this.#init;
documentTypeId = documentTypeId ?? this.#rootDocumentTypeId!;
const frozenProperties = this.#documentTypes.getValue().find((x) => x.id === documentTypeId)?.properties ?? [];
const properties = partialUpdateFrozenArray(frozenProperties, partialUpdate, (x) => x.id === propertyId);
this.#documentTypes.updateOne(documentTypeId, { properties });
}
/*
rootDocumentTypeName() {
return this.#documentTypes.getObservablePart((docTypes) => {
const docType = docTypes.find((x) => x.id === this.#rootDocumentTypeKey);
return docType?.name ?? '';
});
}
*/
rootDocumentTypeObservablePart<PartResult>(mappingFunction: MappingFunction<T, PartResult>) {
return this.#documentTypes.getObservablePart((docTypes) => {
const docType = docTypes.find((x) => x.id === this.#rootDocumentTypeId);
return docType ? mappingFunction(docType) : undefined;
});
}
/*
nameOfDocumentType(id: string) {
return this.#documentTypes.getObservablePart((docTypes) => {
const docType = docTypes.find((x) => x.id === id);
return docType?.name ?? '';
});
}
*/
hasPropertyStructuresOf(containerId: string | null) {
return this.#documentTypes.getObservablePart((docTypes) => {
return (
docTypes.find((docType) => {
return docType.properties?.find((property) => property.containerId === containerId);
}) !== undefined
);
});
}
rootPropertyStructures() {
return this.propertyStructuresOf(null);
}
propertyStructuresOf(containerId: string | null) {
return this.#documentTypes.getObservablePart((docTypes) => {
const props: DocumentTypePropertyTypeResponseModel[] = [];
docTypes.forEach((docType) => {
docType.properties?.forEach((property) => {
if (property.containerId === containerId) {
props.push(property);
}
});
});
return props;
});
}
rootContainers(containerType: PropertyContainerTypes) {
return this.#containers.getObservablePart((data) => {
return data.filter((x) => x.parentId === null && x.type === containerType);
});
}
hasRootContainers(containerType: PropertyContainerTypes) {
return this.#containers.getObservablePart((data) => {
return data.filter((x) => x.parentId === null && x.type === containerType).length > 0;
});
}
containersOfParentKey(
parentId: PropertyTypeContainerResponseModelBaseModel['parentId'],
containerType: PropertyContainerTypes
) {
return this.#containers.getObservablePart((data) => {
return data.filter((x) => x.parentId === parentId && x.type === containerType);
});
}
// In future this might need to take parentName(parentId lookup) into account as well? otherwise containers that share same name and type will always be merged, but their position might be different and they should nto be merged.
containersByNameAndType(name: string, containerType: PropertyContainerTypes) {
return this.#containers.getObservablePart((data) => {
return data.filter((x) => x.name === name && x.type === containerType);
});
}
private _reset() {
this.#documentTypeObservers.forEach((observer) => observer.destroy());
this.#documentTypeObservers = [];
this.#documentTypes.next([]);
this.#containers.next([]);
}
public destroy() {
this._reset();
this.#documentTypes.complete();
this.#containers.complete();
}
}

View File

@@ -0,0 +1,3 @@
export * from './content-type-container-structure-helper.class';
export * from './content-type-property-structure-helper.class';
export * from './content-type-structure-manager.class';

View File

@@ -3,33 +3,34 @@ import { isManifestElementNameType } from './is-manifest-element-name-type.funct
import { loadExtension } from './load-extension.function';
import type { HTMLElementConstructor } from '@umbraco-cms/backoffice/models';
import type { ManifestElement } from '@umbraco-cms/backoffice/extensions-registry';
import type { PageComponent } from '@umbraco-cms/backoffice/router';
export async function createExtensionElement(manifest: ManifestElement): Promise<PageComponent> {
export async function createExtensionElement<ElementType extends HTMLElement>(
manifest: ManifestElement<ElementType>
): Promise<ElementType | undefined> {
//TODO: Write tests for these extension options:
const js = await loadExtension(manifest);
if (isManifestElementNameType(manifest)) {
// created by manifest method providing HTMLElement
return document.createElement(manifest.elementName);
return document.createElement(manifest.elementName) as ElementType;
}
// TODO: Do we need this except for the default() loader?
if (js) {
if (hasDefaultExport<HTMLElementConstructor>(js)) {
// created by default class
if (hasDefaultExport<HTMLElementConstructor<ElementType>>(js)) {
// Element will be created by default class
return new js.default();
}
// If some JS was loaded and manifest did not have a elementName neither it the JS file contain a default export, so we will fail:
console.error(
'-- Extension did not succeed creating an element, missing a default export of the served JavaScript file',
manifest
);
// If some JS was loaded and it did not at least contain a default export, then we are safe to assume that it executed its side effects and does not need to be returned
return undefined;
}
// If some JS was loaded and manifest did not have a elementName neither it the JS file contain a default export, so we will fail:
console.error(
'-- Extension did not succeed creating an element, missing a default export or `elementName` in the manifest.',
manifest

View File

@@ -4,5 +4,5 @@ import { isManifestClassConstructorType } from './is-manifest-class-instance-typ
import type { ManifestBase, ManifestClass } from '@umbraco-cms/backoffice/extensions-registry';
export function isManifestClassableType(manifest: ManifestBase): manifest is ManifestClass {
return isManifestClassConstructorType(manifest) || isManifestLoaderType(manifest) || isManifestJSType(manifest);
return isManifestClassConstructorType(manifest) || isManifestLoaderType<object>(manifest) || isManifestJSType<object>(manifest);
}

View File

@@ -3,6 +3,10 @@ import { isManifestJSType } from './is-manifest-js-type.function';
import { isManifestLoaderType } from './is-manifest-loader-type.function';
import type { ManifestElement, ManifestBase } from '@umbraco-cms/backoffice/extensions-registry';
export function isManifestElementableType(manifest: ManifestBase): manifest is ManifestElement {
return isManifestElementNameType(manifest) || isManifestLoaderType(manifest) || isManifestJSType(manifest);
export function isManifestElementableType<ElementType extends HTMLElement = HTMLElement>(manifest: ManifestBase): manifest is ManifestElement {
return (
isManifestElementNameType(manifest) ||
isManifestLoaderType<ElementType>(manifest) ||
isManifestJSType<ElementType>(manifest)
);
}

View File

@@ -1,6 +1,6 @@
import { ManifestJSType } from './load-extension.function';
import type { ManifestBase } from '@umbraco-cms/backoffice/extensions-registry';
import type { ManifestBase, ManifestWithLoader } from '@umbraco-cms/backoffice/extensions-registry';
export function isManifestJSType(manifest: ManifestBase | unknown): manifest is ManifestJSType {
return (manifest as ManifestJSType).js !== undefined;
export type ManifestJSType<T> = ManifestWithLoader<T> & { js: string };
export function isManifestJSType<T>(manifest: ManifestBase | unknown): manifest is ManifestJSType<T> {
return (manifest as ManifestJSType<T>).js !== undefined;
}

View File

@@ -1,6 +1,8 @@
import { ManifestLoaderType } from './load-extension.function';
import type { ManifestBase } from '@umbraco-cms/backoffice/extensions-registry';
export function isManifestLoaderType(manifest: ManifestBase): manifest is ManifestLoaderType {
return typeof (manifest as ManifestLoaderType).loader === 'function';
import type { ManifestBase, ManifestWithLoader } from '@umbraco-cms/backoffice/extensions-registry';
export type ManifestLoaderType<T> = ManifestWithLoader<T> & {
loader: () => Promise<T>;
};
export function isManifestLoaderType<T>(manifest: ManifestBase): manifest is ManifestLoaderType<T> {
return typeof (manifest as ManifestLoaderType<T>).loader === 'function';
}

View File

@@ -1,17 +1,14 @@
import { isManifestJSType } from './is-manifest-js-type.function';
import { isManifestLoaderType } from './is-manifest-loader-type.function';
import type { ManifestElement } from '@umbraco-cms/backoffice/extensions-registry';
import type { ManifestWithLoader } from '@umbraco-cms/backoffice/extensions-registry';
export type ManifestLoaderType = ManifestElement & { loader: () => Promise<object | HTMLElement> };
export type ManifestJSType = ManifestElement & { js: string };
export async function loadExtension(manifest: ManifestElement): Promise<object | HTMLElement | null> {
export async function loadExtension<T = unknown>(manifest: ManifestWithLoader<T>): Promise<T | null> {
try {
if (isManifestLoaderType(manifest)) {
if (isManifestLoaderType<T>(manifest)) {
return manifest.loader();
}
if (isManifestJSType(manifest) && manifest.js) {
if (isManifestJSType<T>(manifest) && manifest.js) {
return await import(/* @vite-ignore */ manifest.js);
}
} catch (err: any) {

View File

@@ -1,11 +0,0 @@
import type { ManifestElement } from './models';
export interface ManifestExternalLoginProvider extends ManifestElement {
type: 'externalLoginProvider';
meta: MetaExternalLoginProvider;
}
export interface MetaExternalLoginProvider {
label: string;
pathname: string;
}

View File

@@ -1,2 +1,3 @@
export * from './interfaces';
export * from './models';
export * from './entry-point-extension-initializer';

View File

@@ -0,0 +1,5 @@
import type { ManifestDashboard } from '../models';
export interface UmbDashboardExtensionElement extends HTMLElement {
manifest?: ManifestDashboard;
}

View File

@@ -0,0 +1,5 @@
import type { ManifestExternalLoginProvider } from '../models';
export interface UmbExternalLoginProviderExtensionElement extends HTMLElement {
manifest?: ManifestExternalLoginProvider;
}

View File

@@ -0,0 +1,10 @@
export * from './dashboard-extension-element.interface';
export * from './external-login-provider-extension-element.interface';
export * from './menu-item-extension-element.interface';
export * from './modal-extension-element.interface';
export * from './property-editor-ui-extension-element.interface';
export * from './section-extension-element.interface';
export * from './section-sidebar-app-extension-element.interface';
export * from './section-view-extension-element.interface';
export * from './tree-item-extension-element.interface';
export * from './workspace-editor-view-extension-element.interface';

View File

@@ -0,0 +1,5 @@
import type { ManifestMenuItem } from '../models';
export interface UmbMenuItemExtensionElement extends HTMLElement {
manifest?: ManifestMenuItem;
}

View File

@@ -0,0 +1,8 @@
import type { UmbModalHandler } from '@umbraco-cms/backoffice/modal';
export interface UmbModalExtensionElement<UmbModalData extends object = object, UmbModalResult = unknown>
extends HTMLElement {
modalHandler?: UmbModalHandler<UmbModalData, UmbModalResult>;
data?: UmbModalData;
}

View File

@@ -1,6 +1,6 @@
import { DataTypePropertyPresentationModel } from '@umbraco-cms/backoffice/backend-api';
export interface UmbPropertyEditorElement extends HTMLElement {
export interface UmbPropertyEditorExtensionElement extends HTMLElement {
value: unknown;
config: DataTypePropertyPresentationModel[];
}

View File

@@ -0,0 +1,5 @@
import type { ManifestSection } from '../models';
export interface UmbSectionExtensionElement extends HTMLElement {
manifest?: ManifestSection;
}

View File

@@ -0,0 +1,5 @@
import type { ManifestSectionSidebarApp } from '../models';
export interface UmbSectionSidebarAppExtensionElement extends HTMLElement {
manifest?: ManifestSectionSidebarApp;
}

View File

@@ -0,0 +1,5 @@
import type { ManifestSectionView } from '../models';
export interface UmbSectionViewExtensionElement extends HTMLElement {
manifest?: ManifestSectionView;
}

View File

@@ -0,0 +1,5 @@
import { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api';
export interface UmbTreeItemExtensionElement extends HTMLElement {
item?: TreeItemPresentationModel;
}

View File

@@ -0,0 +1,5 @@
import type { ManifestWorkspaceEditorView } from '../models';
export interface UmbWorkspaceEditorViewExtensionElement extends HTMLElement {
manifest?: ManifestWorkspaceEditorView;
}

View File

@@ -1,4 +1,4 @@
import type { ManifestElement, ManifestWithConditions } from './models';
import type { ManifestElement, ManifestWithConditions } from '.';
export interface ManifestCollectionView extends ManifestElement, ManifestWithConditions<ConditionsCollectionView> {
type: 'collectionView';

View File

@@ -1,4 +1,4 @@
import type { ManifestBase } from './models';
import type { ManifestBase } from '.';
export interface ManifestDashboardCollection extends ManifestBase {
type: 'dashboardCollection';

View File

@@ -1,6 +1,9 @@
import type { ManifestElement, ManifestWithConditions } from './models';
import type { UmbDashboardExtensionElement } from '../interfaces';
import type { ManifestElement, ManifestWithConditions } from '.';
export interface ManifestDashboard extends ManifestElement, ManifestWithConditions<ConditionsDashboard> {
export interface ManifestDashboard
extends ManifestElement<UmbDashboardExtensionElement>,
ManifestWithConditions<ConditionsDashboard> {
type: 'dashboard';
meta: MetaDashboard;
}

View File

@@ -1,4 +1,4 @@
import type { ManifestElement } from './models';
import type { ManifestElement } from '.';
/**
* An action to perform on an entity

View File

@@ -1,4 +1,4 @@
import type { ManifestElement, ManifestWithConditions } from './models';
import type { ManifestElement, ManifestWithConditions } from '.';
/**
* An action to perform on multiple entities

View File

@@ -0,0 +1,12 @@
import type { UmbExternalLoginProviderExtensionElement } from '../interfaces/external-login-provider-extension-element.interface';
import type { ManifestElement } from '.';
export interface ManifestExternalLoginProvider extends ManifestElement<UmbExternalLoginProviderExtensionElement> {
type: 'externalLoginProvider';
meta: MetaExternalLoginProvider;
}
export interface MetaExternalLoginProvider {
label: string;
pathname: string;
}

View File

@@ -1,4 +1,4 @@
import type { ManifestElement } from './models';
import type { ManifestElement } from '.';
/**
* Header apps are displayed in the top right corner of the backoffice

View File

@@ -1,4 +1,4 @@
import type { ManifestElement } from './models';
import type { ManifestElement } from '.';
export interface ManifestHealthCheck extends ManifestElement {
type: 'healthCheck';

View File

@@ -1,59 +1,60 @@
import type { ManifestCollectionView } from './collection-view.models';
import type { ManifestDashboard } from './dashboard.models';
import type { ManifestDashboardCollection } from './dashboard-collection.models';
import type { ManifestEntityAction } from './entity-action.models';
import type { ManifestEntityBulkAction } from './entity-bulk-action.models';
import type { ManifestExternalLoginProvider } from './external-login-provider.models';
import type { ManifestHeaderApp, ManifestHeaderAppButtonKind } from './header-app.models';
import type { ManifestHealthCheck } from './health-check.models';
import type { ManifestPackageView } from './package-view.models';
import type { ManifestPropertyAction } from './property-action.models';
import type { ManifestPropertyEditorUI, ManifestPropertyEditorModel } from './property-editor.models';
import type { ManifestSection } from './section.models';
import type { ManifestSectionView } from './section-view.models';
import type { ManifestSectionSidebarApp, ManifestSectionSidebarAppMenuKind } from './section-sidebar-app.models';
import type { ManifestMenu } from './menu.models';
import type { ManifestMenuItem, ManifestMenuItemTreeKind } from './menu-item.models';
import type { ManifestTheme } from './theme.models';
import type { ManifestTree } from './tree.models';
import type { ManifestTreeItem } from './tree-item.models';
import type { ManifestUserProfileApp } from './user-profile-app.models';
import type { ManifestWorkspace } from './workspace.models';
import type { ManifestWorkspaceAction } from './workspace-action.models';
import type { ManifestWorkspaceView } from './workspace-view.models';
import type { ManifestWorkspaceViewCollection } from './workspace-view-collection.models';
import type { ManifestRepository } from './repository.models';
import type { ManifestModal } from './modal.models';
import type { ManifestStore, ManifestTreeStore, ManifestItemStore } from './store.models';
import type { ManifestCollectionView } from './collection-view.model';
import type { ManifestDashboard } from './dashboard.model';
import type { ManifestDashboardCollection } from './dashboard-collection.model';
import type { ManifestEntityAction } from './entity-action.model';
import type { ManifestEntityBulkAction } from './entity-bulk-action.model';
import type { ManifestExternalLoginProvider } from './external-login-provider.model';
import type { ManifestHeaderApp, ManifestHeaderAppButtonKind } from './header-app.model';
import type { ManifestHealthCheck } from './health-check.model';
import type { ManifestMenu } from './menu.model';
import type { ManifestMenuItem, ManifestMenuItemTreeKind } from './menu-item.model';
import type { ManifestModal } from './modal.model';
import type { ManifestPackageView } from './package-view.model';
import type { ManifestPropertyAction } from './property-action.model';
import type { ManifestPropertyEditorUI, ManifestPropertyEditorModel } from './property-editor.model';
import type { ManifestRepository } from './repository.model';
import type { ManifestSection } from './section.model';
import type { ManifestSectionSidebarApp, ManifestSectionSidebarAppMenuKind } from './section-sidebar-app.model';
import type { ManifestSectionView } from './section-view.model';
import type { ManifestStore, ManifestTreeStore, ManifestItemStore } from './store.model';
import type { ManifestTheme } from './theme.model';
import type { ManifestTree } from './tree.model';
import type { ManifestTreeItem } from './tree-item.model';
import type { ManifestUserProfileApp } from './user-profile-app.model';
import type { ManifestWorkspace } from './workspace.model';
import type { ManifestWorkspaceAction } from './workspace-action.model';
import type { ManifestWorkspaceEditorView } from './workspace-editor-view.model';
import type { ManifestWorkspaceViewCollection } from './workspace-view-collection.model';
import type { ClassConstructor } from '@umbraco-cms/backoffice/models';
export * from './collection-view.models';
export * from './dashboard-collection.models';
export * from './dashboard.models';
export * from './entity-action.models';
export * from './entity-bulk-action.models';
export * from './external-login-provider.models';
export * from './header-app.models';
export * from './health-check.models';
export * from './package-view.models';
export * from './property-action.models';
export * from './property-editor.models';
export * from './section-view.models';
export * from './section.models';
export * from './section-sidebar-app.models';
export * from './menu.models';
export * from './menu-item.models';
export * from './theme.models';
export * from './tree.models';
export * from './tree-item.models';
export * from './user-profile-app.models';
export * from './workspace-action.models';
export * from './workspace-view-collection.models';
export * from './workspace-view.models';
export * from './repository.models';
export * from './store.models';
export * from './workspace.models';
export * from './modal.models';
export * from './collection-view.model';
export * from './dashboard-collection.model';
export * from './dashboard.model';
export * from './entity-action.model';
export * from './entity-bulk-action.model';
export * from './external-login-provider.model';
export * from './header-app.model';
export * from './health-check.model';
export * from './menu-item.model';
export * from './menu.model';
export * from './modal.model';
export * from './package-view.model';
export * from './property-action.model';
export * from './property-editor.model';
export * from './repository.model';
export * from './section-sidebar-app.model';
export * from './section-view.model';
export * from './section.model';
export * from './store.model';
export * from './theme.model';
export * from './tree-item.model';
export * from './tree.model';
export * from './user-profile-app.model';
export * from './workspace-action.model';
export * from './workspace-view-collection.model';
export * from './workspace-editor-view.model';
export * from './workspace.model';
export type ManifestTypes =
| ManifestCollectionView
@@ -66,6 +67,11 @@ export type ManifestTypes =
| ManifestHeaderApp
| ManifestHeaderAppButtonKind
| ManifestHealthCheck
| ManifestItemStore
| ManifestMenu
| ManifestMenuItem
| ManifestMenuItemTreeKind
| ManifestModal
| ManifestPackageView
| ManifestPropertyAction
| ManifestPropertyEditorModel
@@ -75,21 +81,16 @@ export type ManifestTypes =
| ManifestSectionSidebarApp
| ManifestSectionSidebarAppMenuKind
| ManifestSectionView
| ManifestMenu
| ManifestMenuItem
| ManifestMenuItemTreeKind
| ManifestStore
| ManifestTheme
| ManifestTree
| ManifestTreeItem
| ManifestTreeStore
| ManifestUserProfileApp
| ManifestWorkspace
| ManifestWorkspaceAction
| ManifestWorkspaceView
| ManifestWorkspaceEditorView
| ManifestWorkspaceViewCollection
| ManifestModal
| ManifestStore
| ManifestTreeStore
| ManifestItemStore
| ManifestBase;
export type ManifestStandardTypes = ManifestTypes['type'];
@@ -155,8 +156,10 @@ export interface ManifestWithLoader<LoaderReturnType> extends ManifestBase {
/**
* The type of extension such as dashboard etc...
*/
export interface ManifestClass<T = unknown> extends ManifestWithLoader<object> {
export interface ManifestClass<ClassType = unknown>
extends ManifestWithLoader<{ default: ClassConstructor<ClassType> }> {
//type: ManifestStandardTypes;
readonly CLASS_TYPE?: ClassType;
/**
* The file location of the javascript file to load
@@ -172,16 +175,18 @@ export interface ManifestClass<T = unknown> extends ManifestWithLoader<object> {
/**
* @TJS-ignore
*/
class?: ClassConstructor<T>;
class?: ClassConstructor<ClassType>;
//loader?: () => Promise<object | HTMLElement>;
}
export interface ManifestClassWithClassConstructor extends ManifestClass {
class: ClassConstructor<unknown>;
export interface ManifestClassWithClassConstructor<T = unknown> extends ManifestClass<T> {
class: ClassConstructor<T>;
}
export interface ManifestElement extends ManifestWithLoader<object | HTMLElement> {
export interface ManifestElement<ElementType extends HTMLElement = HTMLElement>
extends ManifestWithLoader<{ default: ClassConstructor<ElementType> } | Omit<object, 'default'>> {
//type: ManifestStandardTypes;
readonly ELEMENT_TYPE?: ElementType;
/**
* The file location of the javascript file to load
@@ -204,7 +209,7 @@ export interface ManifestElement extends ManifestWithLoader<object | HTMLElement
meta?: unknown;
}
export interface ManifestWithView extends ManifestElement {
export interface ManifestWithView<ElementType extends HTMLElement = HTMLElement> extends ManifestElement<ElementType> {
meta: MetaManifestWithView;
}

View File

@@ -1,6 +1,7 @@
import type { ManifestElement } from './models';
import type { UmbMenuItemExtensionElement } from '../interfaces/menu-item-extension-element.interface';
import type { ManifestElement } from '.';
export interface ManifestMenuItem extends ManifestElement {
export interface ManifestMenuItem extends ManifestElement<UmbMenuItemExtensionElement> {
type: 'menuItem';
meta: MetaMenuItem;
conditions: ConditionsMenuItem;

View File

@@ -1,4 +1,4 @@
import type { ManifestElement } from './models';
import type { ManifestElement } from '.';
export interface ManifestMenu extends ManifestElement {
type: 'menu';

View File

@@ -1,4 +1,4 @@
import type { ManifestElement } from './models';
import type { ManifestElement } from '.';
export interface ManifestModal extends ManifestElement {
type: 'modal';

View File

@@ -1,4 +1,4 @@
import type { ManifestElement } from './models';
import type { ManifestElement } from '.';
export interface ManifestPackageView extends ManifestElement {
type: 'packageView';

View File

@@ -1,4 +1,4 @@
import type { ManifestElement, ManifestWithConditions } from './models';
import type { ManifestElement, ManifestWithConditions } from '.';
export interface ManifestPropertyAction extends ManifestElement, ManifestWithConditions<ConditionsPropertyAction> {
type: 'propertyAction';

View File

@@ -1,7 +1,7 @@
import type { ManifestElement, ManifestBase } from './models';
import type { UmbPropertyEditorExtensionElement } from '../interfaces';
import type { ManifestElement, ManifestBase } from '.';
// UI
export interface ManifestPropertyEditorUI extends ManifestElement {
export interface ManifestPropertyEditorUI extends ManifestElement<UmbPropertyEditorExtensionElement> {
type: 'propertyEditorUI';
meta: MetaPropertyEditorUI;
}

View File

@@ -0,0 +1,6 @@
import type { ManifestClass } from '.';
// TODO: Consider adding a ClassType for this manifest. (Currently we cannot know the scope of a repository, therefor we are going with unknown for now.)
export interface ManifestRepository extends ManifestClass<unknown> {
type: 'repository';
}

View File

@@ -1,6 +1,7 @@
import type { ManifestElement } from './models';
import type { UmbSectionSidebarAppExtensionElement } from '../interfaces/section-sidebar-app-extension-element.interface';
import type { ManifestElement } from '.';
export interface ManifestSectionSidebarApp extends ManifestElement {
export interface ManifestSectionSidebarApp extends ManifestElement<UmbSectionSidebarAppExtensionElement> {
type: 'sectionSidebarApp';
conditions: ConditionsSectionSidebarApp;
}

View File

@@ -0,0 +1,19 @@
import type { UmbSectionViewExtensionElement } from '../interfaces/section-view-extension-element.interface';
import type { ManifestElement, ManifestWithConditions } from '.';
export interface ManifestSectionView
extends ManifestElement<UmbSectionViewExtensionElement>,
ManifestWithConditions<ConditionsSectionView> {
type: 'sectionView';
meta: MetaSectionView;
}
export interface MetaSectionView {
label: string;
pathname: string;
icon: string;
}
export interface ConditionsSectionView {
sections: Array<string>;
}

View File

@@ -0,0 +1,12 @@
import type { UmbSectionExtensionElement } from '../interfaces';
import type { ManifestElement } from '.';
export interface ManifestSection extends ManifestElement<UmbSectionExtensionElement> {
type: 'section';
meta: MetaSection;
}
export interface MetaSection {
label: string;
pathname: string;
}

View File

@@ -1,4 +1,4 @@
import type { ManifestClass } from './models';
import type { ManifestClass } from '.';
import { UmbItemStore, UmbStoreBase, UmbTreeStore } from '@umbraco-cms/backoffice/store';
export interface ManifestStore extends ManifestClass<UmbStoreBase> {

View File

@@ -1,4 +1,4 @@
import type { ManifestWithLoader } from './models';
import type { ManifestWithLoader } from '.';
// TODO: make or find type for JS Module with default export: Would be nice to support css file directly.

View File

@@ -0,0 +1,11 @@
import { UmbTreeItemExtensionElement } from '../interfaces';
import type { ManifestElement } from '.';
export interface ManifestTreeItem extends ManifestElement<UmbTreeItemExtensionElement> {
type: 'treeItem';
conditions: ConditionsTreeItem;
}
export interface ConditionsTreeItem {
entityType: string;
}

View File

@@ -1,4 +1,4 @@
import type { ManifestBase } from './models';
import type { ManifestBase } from '.';
export interface ManifestTree extends ManifestBase {
type: 'tree';

View File

@@ -1,4 +1,4 @@
import type { ManifestElement } from './models';
import type { ManifestElement } from '.';
export interface ManifestUserProfileApp extends ManifestElement {
type: 'userProfileApp';

View File

@@ -1,6 +1,7 @@
import type { InterfaceColor, InterfaceLook } from '@umbraco-ui/uui-base/lib/types/index';
import type { ManifestElement } from './models';
import type { ManifestElement } from '.';
import type { ClassConstructor } from '@umbraco-cms/backoffice/models';
import { UmbWorkspaceAction } from '@umbraco-cms/backoffice/workspace';
export interface ManifestWorkspaceAction extends ManifestElement {
type: 'workspaceAction';
@@ -12,7 +13,7 @@ export interface MetaWorkspaceAction {
label?: string; //TODO: Use or implement additional label-key
look?: InterfaceLook;
color?: InterfaceColor;
api: ClassConstructor<any>;
api: ClassConstructor<UmbWorkspaceAction>;
}
export interface ConditionsWorkspaceAction {

View File

@@ -0,0 +1,11 @@
import type { UmbWorkspaceEditorViewExtensionElement } from '../interfaces/workspace-editor-view-extension-element.interface';
import type { ManifestWithView } from '.';
export interface ManifestWorkspaceEditorView extends ManifestWithView<UmbWorkspaceEditorViewExtensionElement> {
type: 'workspaceEditorView';
conditions: ConditionsWorkspaceView;
}
export interface ConditionsWorkspaceView {
workspaces: string[];
}

View File

@@ -0,0 +1,16 @@
import type { ManifestWithConditions, ManifestWithView, MetaManifestWithView } from '.';
export interface ManifestWorkspaceViewCollection
extends ManifestWithView,
ManifestWithConditions<ConditionsEditorViewCollection> {
type: 'workspaceViewCollection';
meta: MetaEditorViewCollection;
}
export interface MetaEditorViewCollection extends MetaManifestWithView {
entityType: string;
repositoryAlias: string;
}
export interface ConditionsEditorViewCollection {
workspaces: string[];
}

View File

@@ -1,4 +1,4 @@
import type { ManifestElement } from './models';
import type { ManifestElement } from '.';
export interface ManifestWorkspace extends ManifestElement {
type: 'workspace';

View File

@@ -1,5 +0,0 @@
import type { ManifestClass } from './models';
export interface ManifestRepository extends ManifestClass {
type: 'repository';
}

View File

@@ -1,16 +0,0 @@
import type { ManifestElement, ManifestWithConditions } from './models';
export interface ManifestSectionView extends ManifestElement, ManifestWithConditions<ConditionsSectionView> {
type: 'sectionView';
meta: MetaSectionView;
}
export interface MetaSectionView {
label: string;
pathname: string;
icon: string;
}
export interface ConditionsSectionView {
sections: Array<string>;
}

View File

@@ -1,11 +0,0 @@
import type { ManifestElement } from './models';
export interface ManifestSection extends ManifestElement {
type: 'section';
meta: MetaSection;
}
export interface MetaSection {
label: string;
pathname: string;
}

View File

@@ -1,10 +0,0 @@
import type { ManifestElement } from './models';
export interface ManifestTreeItem extends ManifestElement {
type: 'treeItem';
conditions: ConditionsTreeItem;
}
export interface ConditionsTreeItem {
entityType: string;
}

View File

@@ -1,22 +0,0 @@
import type { ManifestBase, ManifestWithConditions } from './models';
export interface ManifestWorkspaceViewCollection
extends ManifestBase,
ManifestWithConditions<ConditionsEditorViewCollection> {
type: 'workspaceViewCollection';
meta: MetaEditorViewCollection;
}
// TODO: Get rid of store alias, when we are done migrating to repositories(remember to enforce repositoryAlias):
export interface MetaEditorViewCollection {
pathname: string;
label: string;
icon: string;
entityType: string;
storeAlias?: string;
repositoryAlias?: string;
}
export interface ConditionsEditorViewCollection {
workspaces: string[];
}

View File

@@ -1,17 +0,0 @@
import type { ManifestWithView } from './models';
export interface ManifestWorkspaceView extends ManifestWithView {
type: 'workspaceView';
meta: MetaWorkspaceView;
conditions: ConditionsWorkspaceView;
}
export interface MetaWorkspaceView {
pathname: string;
label: string;
icon: string;
}
export interface ConditionsWorkspaceView {
workspaces: string[];
}

View File

@@ -0,0 +1,11 @@
import { v4, validate } from 'uuid';
export class UmbId {
public static new() {
return v4();
}
public static validate(id: string) {
return validate(id);
}
}

View File

@@ -4,10 +4,10 @@ import type {
UUIModalSidebarElement,
UUIModalSidebarSize,
} from '@umbraco-ui/uui';
import { v4 as uuidv4 } from 'uuid';
import { BehaviorSubject } from 'rxjs';
import { UmbModalConfig, UmbModalType } from './modal.context';
import { UmbModalToken } from './token/modal-token';
import { UmbId } from '@umbraco-cms/backoffice/id';
import { createExtensionElement, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api';
import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
@@ -62,7 +62,7 @@ export class UmbModalHandlerClass<ModalData extends object = object, ModalResult
config?: UmbModalConfig
) {
this.#host = host;
this.key = config?.key || uuidv4();
this.key = config?.key || UmbId.new();
if (modalAlias instanceof UmbModalToken) {
this.type = modalAlias.getDefaultConfig()?.type || this.type;

View File

@@ -1,7 +1,7 @@
import { v4 as uuidv4 } from 'uuid';
import { UmbModalHandler } from './modal-handler';
import { UmbModalConfig, UmbModalContext } from './modal.context';
import { UmbModalToken } from './token/modal-token';
import { UmbId } from '@umbraco-cms/backoffice/id';
import type { Params } from '@umbraco-cms/backoffice/router';
export type UmbModalRouteBuilder = (params: { [key: string]: string | number }) => string;
@@ -26,7 +26,7 @@ export class UmbModalRouteRegistration<UmbModalTokenData extends object = object
path: string,
modalConfig?: UmbModalConfig
) {
this.#key = modalConfig?.key || uuidv4();
this.#key = modalConfig?.key || UmbId.new();
this.#modalAlias = modalAlias;
this.#path = path;
this.#modalConfig = { ...modalConfig, key: this.#key };

View File

@@ -1,9 +1,9 @@
export interface UmbPickerModalData<T> {
multiple: boolean;
selection: Array<string>;
filter?: (language: T) => boolean;
filter?: (item: T) => boolean;
}
export interface UmbPickerModalResult<T> {
export interface UmbPickerModalResult {
selection: Array<string>;
}

View File

@@ -1,7 +1,16 @@
import type { UserDetails } from '@umbraco-cms/backoffice/models';
import { UmbModalToken, UmbPickerModalData } from '@umbraco-cms/backoffice/modal';
import { UserResponseModel } from '@umbraco-cms/backoffice/backend-api';
export const UMB_USER_PICKER_MODAL = new UmbModalToken<UmbPickerModalData<UserDetails>>('Umb.Modal.UserPicker', {
type: 'sidebar',
size: 'small',
});
export type UmbUserPickerModalData = UmbPickerModalData<UserResponseModel>;
export interface UmbUserPickerModalResult {
selection: Array<string>;
}
export const UMB_USER_PICKER_MODAL = new UmbModalToken<UmbUserPickerModalData, UmbUserPickerModalResult>(
'Umb.Modal.UserPicker',
{
type: 'sidebar',
size: 'small',
}
);

View File

@@ -108,3 +108,9 @@ export type PackageManifestResponse = UmbPackage[];
export type UmbPackageWithMigrationStatus = UmbPackage & {
hasPendingMigrations: boolean;
};
export interface UmbFilterModel {
skip?: number;
take?: number;
filter?: string;
}

View File

@@ -1,9 +1,7 @@
import { assert, expect } from '@open-wc/testing';
import { validate as uuidValidate } from 'uuid';
import { UmbNotificationHandler } from './notification-handler';
import type { UmbNotificationOptions } from './notification.context';
import { UmbId } from '@umbraco-cms/backoffice/id';
describe('UmbNotificationHandler', () => {
let notificationHandler: UmbNotificationHandler;
@@ -17,7 +15,7 @@ describe('UmbNotificationHandler', () => {
describe('properties', () => {
it('has a key property', () => {
expect(notificationHandler).to.have.property('key');
expect(uuidValidate(notificationHandler.key)).to.be.true;
expect(UmbId.validate(notificationHandler.key)).to.be.true;
});
it('has an element property', () => {

View File

@@ -1,6 +1,6 @@
import { UUIToastNotificationElement } from '@umbraco-ui/uui';
import { v4 as uuidv4 } from 'uuid';
import type { UmbNotificationOptions, UmbNotificationColor, UmbNotificationDefaultData } from './notification.context';
import { UmbId } from '@umbraco-cms/backoffice/id';
/**
* @export
@@ -27,7 +27,7 @@ export class UmbNotificationHandler {
* @memberof UmbNotificationHandler
*/
constructor(options: UmbNotificationOptions) {
this.key = uuidv4();
this.key = UmbId.new();
this.color = options.color || this._defaultColor;
this.duration = options.duration !== undefined ? options.duration : this._defaultDuration;

View File

@@ -0,0 +1,3 @@
export interface UmbCollectionRepository {
requestCollection(filter?: any): Promise<any>;
}

View File

@@ -0,0 +1,7 @@
import type { UmbPagedData } from '../tree-repository.interface';
import type { DataSourceResponse } from '../../repository';
export interface UmbCollectionDataSource<ItemType = any, PagedItemType = UmbPagedData<ItemType>> {
getCollection(): Promise<DataSourceResponse<PagedItemType>>;
filterCollection(filter: any): Promise<DataSourceResponse<PagedItemType>>;
}

View File

@@ -1,9 +1,9 @@
import type { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api';
import type { ApiError, CancelError } from '@umbraco-cms/backoffice/backend-api';
export interface DataSourceResponse<T = undefined> extends UmbDataSourceErrorResponse {
data?: T;
}
export interface UmbDataSourceErrorResponse {
error?: ProblemDetailsModel;
error?: ApiError | CancelError;
}

View File

@@ -1,9 +1,9 @@
import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository';
export interface UmbDataSource<CreateRequestType, UpdateRequestType, ResponseType> {
export interface UmbDataSource<CreateRequestType, CreateResponseType, UpdateRequestType, ResponseType> {
createScaffold(parentId: string | null): Promise<DataSourceResponse<CreateRequestType>>;
get(unique: string): Promise<DataSourceResponse<ResponseType>>;
insert(data: CreateRequestType): Promise<any>;
insert(data: CreateRequestType): Promise<DataSourceResponse<CreateResponseType>>;
update(unique: string, data: UpdateRequestType): Promise<DataSourceResponse<ResponseType>>;
delete(unique: string): Promise<DataSourceResponse>;
}

View File

@@ -5,3 +5,4 @@ export * from './tree-data-source.interface';
export * from './item-data-source.interface';
export * from './move-data-source.interface';
export * from './copy-data-source.interface';
export * from './collection-data-source.interface';

View File

@@ -1,3 +1,4 @@
import { Observable } from 'rxjs';
import type { ProblemDetailsModel } from '@umbraco-cms/backoffice/backend-api';
export interface UmbRepositoryErrorResponse {
@@ -7,10 +8,16 @@ export interface UmbRepositoryResponse<T> extends UmbRepositoryErrorResponse {
data?: T;
}
export interface UmbDetailRepository<CreateRequestType = any, UpdateRequestType = any, ResponseType = any> {
export interface UmbDetailRepository<
CreateRequestType = any,
CreateResponseType = any,
UpdateRequestType = any,
ResponseType = any
> {
createScaffold(parentId: string | null): Promise<UmbRepositoryResponse<CreateRequestType>>;
requestById(id: string): Promise<UmbRepositoryResponse<ResponseType>>;
create(data: CreateRequestType): Promise<UmbRepositoryErrorResponse>;
byId(id: string): Promise<Observable<ResponseType>>;
create(data: CreateRequestType): Promise<UmbRepositoryResponse<CreateResponseType>>;
save(id: string, data: UpdateRequestType): Promise<UmbRepositoryErrorResponse>;
delete(id: string): Promise<UmbRepositoryErrorResponse>;
}

Some files were not shown because too many files have changed in this diff Show More