Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1489,7 +1489,7 @@ public async Task<PagedModel<TItem>> GetAllAllowedAsRootAsync(int skip, int take
TItem[] allowedChildren = GetMany(sortedKeys).ToArray();
result = new PagedModel<TItem>
{
Items = allowedChildren.OrderBy(x => sortedKeys.IndexOf(x.Key)).Take(take).Skip(skip),
Items = allowedChildren.OrderBy(x => sortedKeys.IndexOf(x.Key)).Skip(skip).Take(take),
Total = allowedChildren.Length,
};
}
Expand Down
9 changes: 5 additions & 4 deletions src/Umbraco.Web.UI.Client/mocks/db/document-type.db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { UmbMockEntityFolderManager } from './utils/entity/entity-folder.manager
import { UmbMockEntityTreeManager } from './utils/entity/entity-tree.manager.js';
import { UmbMockEntityNamedItemManager } from './utils/entity/entity-named-item.manager.js';
import { UmbMockEntityDetailManager } from './utils/entity/entity-detail.manager.js';
import { pagedResult } from './utils/paged-result.js';
import { UmbId } from '@umbraco-cms/backoffice/id';
import {
DataTypeChangeModeModel,
Expand Down Expand Up @@ -42,19 +43,19 @@ class UmbDocumentTypeMockDB extends UmbEntityMockDbBase<UmbMockDocumentTypeModel
super('documentType', data);
}

getAllowedChildren(id: string): PagedAllowedDocumentTypeModel {
getAllowedChildren(id: string, skip = 0, take = 100): PagedAllowedDocumentTypeModel {
const documentType = this.detail.read(id);
const allowedDocumentTypes = documentType.allowedDocumentTypes.map((sortModel: DocumentTypeSortModel) =>
this.detail.read(sortModel.documentType.id),
);
const mappedItems = allowedDocumentTypes.map((item: UmbMockDocumentTypeModel) => allowedDocumentTypeMapper(item));
return { items: mappedItems, total: mappedItems.length };
return pagedResult(mappedItems, skip, take);
}

getAllowedAtRoot(): PagedAllowedDocumentTypeModel {
getAllowedAtRoot(skip = 0, take = 100): PagedAllowedDocumentTypeModel {
const mockItems = this.data.filter((item) => item.allowedAsRoot);
const mappedItems = mockItems.map((item) => allowedDocumentTypeMapper(item));
return { items: mappedItems, total: mappedItems.length };
return pagedResult(mappedItems, skip, take);
}

getAllowedParents(id: string): DocumentTypeAllowedParentsResponseModel {
Expand Down
14 changes: 8 additions & 6 deletions src/Umbraco.Web.UI.Client/mocks/db/media-type.db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { UmbMockEntityTreeManager } from './utils/entity/entity-tree.manager.js'
import { UmbMockEntityNamedItemManager } from './utils/entity/entity-named-item.manager.js';
import { UmbMockEntityDetailManager } from './utils/entity/entity-detail.manager.js';
import { umbDataTypeMockDb } from './data-type.db.js';
import { pagedResult } from './utils/paged-result.js';
import { UmbId } from '@umbraco-cms/backoffice/id';
import type {
AllowedMediaTypeItemResponseModel,
Expand Down Expand Up @@ -34,19 +35,19 @@ class UmbMediaTypeMockDB extends UmbEntityMockDbBase<UmbMockMediaTypeModel> {
super('mediaType', data);
}

getAllowedChildren(id: string): PagedAllowedMediaTypeModel {
getAllowedChildren(id: string, skip = 0, take = 100): PagedAllowedMediaTypeModel {
const mediaType = this.detail.read(id);
const allowedMediaTypes = mediaType.allowedMediaTypes.map((sortModel: MediaTypeSortModel) =>
this.detail.read(sortModel.mediaType.id),
);
const mappedItems = allowedMediaTypes.map((item: UmbMockMediaTypeModel) => allowedMediaTypeMapper(item));
return { items: mappedItems, total: mappedItems.length };
return pagedResult(mappedItems, skip, take);
}

getAllowedAtRoot(): PagedAllowedMediaTypeModel {
getAllowedAtRoot(skip = 0, take = 100): PagedAllowedMediaTypeModel {
const mockItems = this.data.filter((item) => item.allowedAsRoot);
const mappedItems = mockItems.map((item) => allowedMediaTypeMapper(item));
return { items: mappedItems, total: mappedItems.length };
return pagedResult(mappedItems, skip, take);
}

getAllowedParents(id: string) {
Expand All @@ -56,7 +57,7 @@ class UmbMediaTypeMockDB extends UmbEntityMockDbBase<UmbMockMediaTypeModel> {
return { allowedParentIds };
}

getAllowedByFileExtension(fileExtension: string): GetItemMediaTypeAllowedResponse {
getAllowedByFileExtension(fileExtension: string, skip = 0, take = 100): GetItemMediaTypeAllowedResponse {
const allowedTypes = this.data.filter((field) => {
const allProperties = field.properties.flat();

Expand All @@ -73,7 +74,8 @@ class UmbMediaTypeMockDB extends UmbEntityMockDbBase<UmbMockMediaTypeModel> {
});

const mappedTypes = allowedTypes.map((item) => allowedExtensionMediaTypeItemMapper(item, true));
return allowedExtensionMediaTypeMapper(mappedTypes, mappedTypes.length);
const paged = pagedResult(mappedTypes, skip, take);
return allowedExtensionMediaTypeMapper(paged.items, paged.total);
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/Umbraco.Web.UI.Client/mocks/db/member-type.db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { UmbEntityMockDbBase } from './utils/entity/entity-base.js';
import { UmbMockEntityTreeManager } from './utils/entity/entity-tree.manager.js';
import { UmbMockEntityNamedItemManager } from './utils/entity/entity-named-item.manager.js';
import { UmbMockEntityDetailManager } from './utils/entity/entity-detail.manager.js';
import { pagedResult } from './utils/paged-result.js';
import { UmbId } from '@umbraco-cms/backoffice/id';
import type {
AllowedMemberTypeModel,
Expand All @@ -21,10 +22,10 @@ class UmbMemberTypeMockDB extends UmbEntityMockDbBase<UmbMockMemberTypeModel> {
super('memberType', data);
}

getAllowedAtRoot(): PagedAllowedMemberTypeModel {
getAllowedAtRoot(skip = 0, take = 100): PagedAllowedMemberTypeModel {
const mockItems = this.data.filter((item) => item.allowedAsRoot);
const mappedItems = mockItems.map((item) => allowedMemberTypeMapper(item));
return { items: mappedItems, total: mappedItems.length };
return pagedResult(mappedItems, skip, take);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ import { UMB_SLUG } from './slug.js';
import { umbracoPath } from '@umbraco-cms/backoffice/utils';

export const structureHandlers = [
http.get(umbracoPath(`${UMB_SLUG}/:id/allowed-children`), ({ params }) => {
http.get(umbracoPath(`${UMB_SLUG}/:id/allowed-children`), ({ params, request }) => {
const id = params.id as string;
if (!id) return new HttpResponse(null, { status: 400 });
const response = umbDocumentTypeMockDb.getAllowedChildren(id);
const url = new URL(request.url);
const skip = Number(url.searchParams.get('skip')) || 0;
const take = Number(url.searchParams.get('take')) || 100;

const response = umbDocumentTypeMockDb.getAllowedChildren(id, skip, take);
return HttpResponse.json(response);
}),

http.get(umbracoPath(`${UMB_SLUG}/allowed-at-root`), () => {
const response = umbDocumentTypeMockDb.getAllowedAtRoot();
http.get(umbracoPath(`${UMB_SLUG}/allowed-at-root`), ({ request }) => {
const url = new URL(request.url);
const skip = Number(url.searchParams.get('skip')) || 0;
const take = Number(url.searchParams.get('take')) || 100;

const response = umbDocumentTypeMockDb.getAllowedAtRoot(skip, take);
return HttpResponse.json(response);
}),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ export const itemHandlers = [
}),

http.get(umbracoPath(`/item${UMB_SLUG}/allowed`), ({ request }) => {
const fileExtension = new URL(request.url).searchParams.get('fileExtension');
const url = new URL(request.url);
const fileExtension = url.searchParams.get('fileExtension');
if (!fileExtension) return;

const response = umbMediaTypeMockDb.getAllowedByFileExtension(fileExtension);
const skip = Number(url.searchParams.get('skip')) || 0;
const take = Number(url.searchParams.get('take')) || 100;

const response = umbMediaTypeMockDb.getAllowedByFileExtension(fileExtension, skip, take);

return HttpResponse.json(response);
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ import { UMB_SLUG } from './slug.js';
import { umbracoPath } from '@umbraco-cms/backoffice/utils';

export const structureHandlers = [
http.get(umbracoPath(`${UMB_SLUG}/:id/allowed-children`), ({ params }) => {
http.get(umbracoPath(`${UMB_SLUG}/:id/allowed-children`), ({ params, request }) => {
const id = params.id as string;
if (!id) return new HttpResponse(null, { status: 400 });
const response = umbMediaTypeMockDb.getAllowedChildren(id);
const url = new URL(request.url);
const skip = Number(url.searchParams.get('skip')) || 0;
const take = Number(url.searchParams.get('take')) || 100;

const response = umbMediaTypeMockDb.getAllowedChildren(id, skip, take);
return HttpResponse.json(response);
}),

http.get(umbracoPath(`${UMB_SLUG}/allowed-at-root`), () => {
const response = umbMediaTypeMockDb.getAllowedAtRoot();
http.get(umbracoPath(`${UMB_SLUG}/allowed-at-root`), ({ request }) => {
const url = new URL(request.url);
const skip = Number(url.searchParams.get('skip')) || 0;
const take = Number(url.searchParams.get('take')) || 100;

const response = umbMediaTypeMockDb.getAllowedAtRoot(skip, take);
return HttpResponse.json(response);
}),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import { UMB_SLUG } from './slug.js';
import { umbracoPath } from '@umbraco-cms/backoffice/utils';

export const structureHandlers = [
http.get(umbracoPath(`${UMB_SLUG}/allowed-at-root`), () => {
const response = umbMemberTypeMockDb.getAllowedAtRoot();
http.get(umbracoPath(`${UMB_SLUG}/allowed-at-root`), ({ request }) => {
const url = new URL(request.url);
const skip = Number(url.searchParams.get('skip')) || 0;
const take = Number(url.searchParams.get('take')) || 100;

const response = umbMemberTypeMockDb.getAllowedAtRoot(skip, take);
return HttpResponse.json(response);
}),
];
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
import type { UmbDataSourceResponse, UmbPagedModel } from '@umbraco-cms/backoffice/repository';
import type { UmbOffsetPaginationRequestModel } from '@umbraco-cms/backoffice/utils';

export interface UmbContentTypeStructureDataSourceConstructor<ItemType> {
new (host: UmbControllerHost): UmbContentTypeStructureDataSource<ItemType>;
}

export interface UmbContentTypeStructureDataSource<ItemType> {
/**
* Returns a single page of the content types allowed as children.
* @param {string | null} unique - The content type to get the allowed children of, or `null` for the root.
* @param {string | null} parentContentUnique - The content item the children will be created under, if any.
* @param {UmbOffsetPaginationRequestModel} paging - The page to return. Implementations must honour this, as a
* source that ignores it returns the same page repeatedly when a caller pages through the full set.
* @returns {Promise} A promise resolving to `{ data: { items, total } }`, or `{ error }`.
*/
getAllowedChildrenOf(
unique: string | null,
parentContentUnique: string | null,
paging?: UmbOffsetPaginationRequestModel,
): Promise<UmbDataSourceResponse<UmbPagedModel<ItemType>>>;
getAllowedParentsOf?(unique: string): Promise<UmbDataSourceResponse<Array<UmbEntityModel>>>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ import type {
UmbContentTypeStructureDataSource,
UmbContentTypeStructureDataSourceConstructor,
} from './content-type-structure-data-source.interface.js';
import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository';
import { fetchAllPages, UmbRepositoryBase } from '@umbraco-cms/backoffice/repository';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { UmbOffsetPaginationRequestModel } from '@umbraco-cms/backoffice/utils';

// Mirrors the server's default `take` for the allowed-children and allowed-at-root endpoints.
const ALLOWED_CHILDREN_PAGE_SIZE = 100;

export abstract class UmbContentTypeStructureRepositoryBase<ItemType>
extends UmbRepositoryBase
Expand All @@ -18,13 +22,34 @@ export abstract class UmbContentTypeStructureRepositoryBase<ItemType>
}

/**
* Returns a promise with the allowed children of a content type
* @param {string} unique
* @param parentContentUnique
* @returns {*}
* Returns a promise with a single page of the allowed children of a content type. The server returns the
* first 100 when no paging is given, so prefer `requestAllAllowedChildrenOf` when every allowed child is needed.
* @param {string | null} unique - The content type to get the allowed children of, or `null` for the root.
* @param {string | null} parentContentUnique - The content item the children will be created under, if any.
* @param {UmbOffsetPaginationRequestModel} paging - The page to return.
* @returns {Promise} A promise resolving to `{ data: { items, total } }`, or `{ error }`.
* @memberof UmbContentTypeStructureRepositoryBase
*/
requestAllowedChildrenOf(
unique: string | null,
parentContentUnique: string | null,
paging?: UmbOffsetPaginationRequestModel,
) {
return this._dataSource.getAllowedChildrenOf(unique, parentContentUnique, paging);
}

/**
* Returns a promise with every allowed child of a content type, by paging through the data source until all
* items have been retrieved.
* @param {string | null} unique - The content type to get the allowed children of, or `null` for the root.
* @param {string | null} parentContentUnique - The content item the children will be created under, if any.
* @returns {Promise} A promise resolving to `{ data: { items, total } }` containing every allowed child, or `{ error }`.
* @memberof UmbContentTypeStructureRepositoryBase
*/
requestAllowedChildrenOf(unique: string | null, parentContentUnique: string | null) {
return this._dataSource.getAllowedChildrenOf(unique, parentContentUnique);
requestAllAllowedChildrenOf(unique: string | null, parentContentUnique: string | null) {
return fetchAllPages<ItemType>(
(skip, take) => this._dataSource.getAllowedChildrenOf(unique, parentContentUnique, { skip, take }),
ALLOWED_CHILDREN_PAGE_SIZE,
);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import type { UmbDataSourceResponse, UmbPagedModel } from '@umbraco-cms/backoffice/repository';
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
import type { UmbOffsetPaginationRequestModel } from '@umbraco-cms/backoffice/utils';

export interface UmbContentTypeStructureRepository<ItemType> {
/**
* Returns a single page of the content types allowed as children. The server returns the first 100 when
* no paging is given, so use `requestAllAllowedChildrenOf` when every allowed child is needed.
*/
requestAllowedChildrenOf(
unique: string,
unique: string | null,
parentContentUnique: string | null,
paging?: UmbOffsetPaginationRequestModel,
): Promise<UmbDataSourceResponse<UmbPagedModel<ItemType>>>;

/**
* Returns every content type allowed as a child, paging through the data source until all have been retrieved.
*/
requestAllAllowedChildrenOf?(
unique: string | null,
parentContentUnique: string | null,
): Promise<UmbDataSourceResponse<UmbPagedModel<ItemType>>>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { tryExecute } from '@umbraco-cms/backoffice/resources';
import type { UmbPagedModel, UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';
import type { UmbOffsetPaginationRequestModel } from '@umbraco-cms/backoffice/utils';

// Keep this type internal
type AllowedContentTypeBaseModel = {
Expand All @@ -19,6 +20,7 @@ export interface UmbContentTypeStructureServerDataSourceBaseArgs<
getAllowedChildrenOf: (
unique: string | null,
parentContentUnique: string | null,
paging?: UmbOffsetPaginationRequestModel,
) => Promise<UmbDataSourceResponse<UmbPagedModel<ServerItemType>>>;
mapper: (item: ServerItemType) => ClientItemType;
}
Expand Down Expand Up @@ -48,14 +50,22 @@ export abstract class UmbContentTypeStructureServerDataSourceBase<
}

/**
* Returns a promise with the allowed content types for the given unique
* @param {string} unique
* @param parentContentUnique
* Returns a promise with a single page of the allowed content types for the given unique
* @param {string | null} unique - The content type to get the allowed children of, or `null` for the root.
* @param {string | null} parentContentUnique - The content item the children will be created under, if any.
* @param {UmbOffsetPaginationRequestModel} paging - The page to return.
* @returns {*}
* @memberof UmbContentTypeStructureServerDataSourceBase
*/
async getAllowedChildrenOf(unique: string | null, parentContentUnique: string | null) {
const { data, error } = await tryExecute(this.#host, this.#getAllowedChildrenOf(unique, parentContentUnique));
async getAllowedChildrenOf(
unique: string | null,
parentContentUnique: string | null,
paging?: UmbOffsetPaginationRequestModel,
) {
const { data, error } = await tryExecute(
this.#host,
this.#getAllowedChildrenOf(unique, parentContentUnique, paging),
);

if (data) {
const items = data.items.map((item) => this.#mapper(item));
Expand Down
Loading
Loading