Skip to content
Merged
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
29 changes: 0 additions & 29 deletions FAQ.md

This file was deleted.

17 changes: 16 additions & 1 deletion lib/client/delivery-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
TaxonomyQuery,
LanguagesQuery,
InitializeSyncQuery,
SyncChangesQuery
SyncChangesQuery,
UsedInQuery
} from '../query';
import { sdkInfo } from '../sdk-info.generated';
import { IMappingService, MappingService, QueryService } from '../services';
Expand Down Expand Up @@ -137,4 +138,18 @@ export class DeliveryClient<TClientTypes extends ClientTypes = ClientTypes> impl
syncChanges(): SyncChangesQuery<TClientTypes> {
return new SyncChangesQuery(this.config, this.queryService);
}

/**
* Item listing of where an asset is used
*/
assetUsedIn(assetCodename: string): UsedInQuery<TClientTypes> {
return new UsedInQuery(this.config, this.queryService, { entity: 'asset', codename: assetCodename });
}

/**
* Item listing of where a content item is used
*/
itemUsedIn(itemCodename: string): UsedInQuery<TClientTypes> {
return new UsedInQuery(this.config, this.queryService, { entity: 'contentItem', codename: itemCodename });
}
}
13 changes: 12 additions & 1 deletion lib/client/idelivery-client.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
TaxonomyQuery,
LanguagesQuery,
InitializeSyncQuery,
SyncChangesQuery
SyncChangesQuery,
UsedInQuery
} from '../query';
import { IMappingService } from '../services';

Expand Down Expand Up @@ -88,4 +89,14 @@ export interface IDeliveryClient<TClientTypes extends ClientTypes = ClientTypes>
* Gets query fetching delta updates of content items
*/
syncChanges(): SyncChangesQuery<TClientTypes>;

/**
* Item listing of where an asset is used
*/
assetUsedIn(assetCodename: string): UsedInQuery<TClientTypes>;

/**
* Item listing of where a content item is used
*/
itemUsedIn(itemCodename: string): UsedInQuery<TClientTypes>;
}
18 changes: 18 additions & 0 deletions lib/contracts/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,24 @@ export namespace Contracts {

export interface IItemsFeedContract extends IItemsWithModularContentContract {}

export interface IUsedInItemsContract {
items: IUsedInItemContract[];
}

export interface IUsedInItemContract {
system: {
id: string;
name: string;
codename: string;
language: string;
type: string;
collection: string;
workflow: string;
workflow_step: string;
last_modified: string;
};
}

export interface IListContentItemsContract extends IItemsWithModularContentContract {
pagination: IPaginationContract;
}
Expand Down
1 change: 1 addition & 0 deletions lib/mappers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export * from './taxonomy.mapper';
export * from './type.mapper';
export * from './generic-element.mapper';
export * from './language.mapper';
export * from './used-in.mapper';
export * from './sync.mapper';
20 changes: 20 additions & 0 deletions lib/mappers/used-in.mapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Contracts } from '../contracts';
import { ClientTypes, IUsedInItemRecord } from '../models';

export class UsedInMapper<TClientTypes extends ClientTypes> {
mapUsedInItem(response: Contracts.IUsedInItemContract): IUsedInItemRecord<TClientTypes> {
return {
system: {
id: response.system.id,
name: response.system.name,
codename: response.system.codename,
language: response.system.language,
type: response.system.type,
collection: response.system.collection,
workflow: response.system.workflow,
workflowStep: response.system.workflow_step,
lastModified: response.system.last_modified
}
};
}
}
14 changes: 14 additions & 0 deletions lib/models/item-models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,20 @@ export interface IItemFeedQueryConfig extends IQueryConfig {
disableItemLinking?: boolean;
}

export interface IUsedInItemRecord<TClientTypes extends ClientTypes> {
readonly system: {
readonly id: string;
readonly name: string;
readonly codename: string;
readonly language: TClientTypes['languageCodenames'];
readonly type: TClientTypes['contentTypeCodenames'];
readonly collection: TClientTypes['collectionCodenames'];
readonly workflow: TClientTypes['workflowCodenames'];
readonly workflowStep: TClientTypes['worfklowStepCodenames'];
readonly lastModified: string;
};
}

export type ClientTypes = {
readonly contentItemType: IContentItem;
readonly contentTypeCodenames: string;
Expand Down
12 changes: 11 additions & 1 deletion lib/models/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { IKontentListAllResponse, IKontentListResponse, IKontentResponse } from
import { IPagination } from './common/pagination.class';
import { IContentType } from './content-type-models';
import { IGenericElementOption } from './element-models';
import { IContentItem, IContentItemsContainer } from './item-models';
import { IContentItem, IContentItemsContainer, IUsedInItemRecord } from './item-models';
import { ILanguage } from './language-models';
import { IContentItemDelta } from './sync-models';
import { ITaxonomyGroup } from './taxonomy-models';
import { ClientTypes } from './item-models';

export namespace Responses {
export interface IListContentTypesResponse<TContentTypeCodename extends string> extends IKontentListResponse {
Expand Down Expand Up @@ -35,6 +36,15 @@ export namespace Responses {
options: IGenericElementOption[];
}

export interface IUsedInResponse<TClientTypes extends ClientTypes> extends IKontentListResponse {
items: IUsedInItemRecord<TClientTypes>[];
}

export interface IUsedInAllResponse<TClientTypes extends ClientTypes> extends IKontentListAllResponse {
items: IUsedInItemRecord<TClientTypes>[];
responses: IDeliveryNetworkResponse<IUsedInResponse<TClientTypes>, Contracts.IUsedInItemsContract>[];
}

export interface IListItemsFeedResponse<
TContentItem extends IContentItem = IContentItem,
TLinkedItemType extends IContentItem = IContentItem
Expand Down
69 changes: 68 additions & 1 deletion lib/query/common/base-item-listing-query.class.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { ElementType, Elements } from '../../elements';
import { IDeliveryClientConfig } from '../../config';
import {
ClientTypes,
Filters,
IContentItem,
IKontentListAllResponse,
IKontentListResponse,
IQueryConfig,
Expand All @@ -17,7 +19,7 @@ export abstract class BaseItemListingQuery<
TAllResponse extends IKontentListAllResponse,
TQueryConfig extends IQueryConfig,
TContract
> extends BaseListingQuery<TClientTypes, TResponse, TAllResponse, TQueryConfig, TContract> {
> extends BaseListingQuery<TClientTypes, IContentItem, TResponse, TAllResponse, TQueryConfig, TContract> {
constructor(protected config: IDeliveryClientConfig, protected queryService: QueryService<TClientTypes>) {
super(config, queryService);
}
Expand Down Expand Up @@ -204,4 +206,69 @@ export abstract class BaseItemListingQuery<
this.parameters.push(new Parameters.SkipParameter(skip));
return this;
}

protected linkItemsInRte(allContentItems: IContentItem[]): void {
for (const item of allContentItems) {
for (const elementKey of Object.keys(item.elements)) {
const element = item.elements[elementKey];

if (element.type === ElementType.ModularContent) {
const linkedItemElement = element as Elements.LinkedItemsElement;

// We create separate array for ordered items because the 'linkedItems' from response might be incomplete
// e.g. If 4 items are linked, only 2 might be available in the response. Rest needs to be mapped from all available items
const orderedLinkedItems: IContentItem[] = [];

for (const linkedItemCodename of linkedItemElement.value) {
let linkedItem: IContentItem | undefined;

const linkedItemInElement = linkedItemElement.linkedItems.find(
(m) => m.system.codename.toLowerCase() === linkedItemCodename.toLowerCase()
);
if (linkedItemInElement) {
linkedItem = linkedItemInElement;
} else {
linkedItem = allContentItems.find(
(m) => m.system.codename.toLowerCase() === linkedItemCodename.toLowerCase()
);
}

if (linkedItem) {
orderedLinkedItems.push(linkedItem);
}
}

// Replace linked items with the ordered one
linkedItemElement.linkedItems = orderedLinkedItems;
}

if (element.type === ElementType.RichText) {
const orderedLinkedItems: IContentItem[] = [];

const richTextElement = element as Elements.RichTextElement;

for (const linkedItemCodename of richTextElement.linkedItemCodenames) {
let linkedItem: IContentItem | undefined;

const linkedItemInElement = richTextElement.linkedItems.find(
(m) => m.system.codename.toLowerCase() === linkedItemCodename.toLowerCase()
);
if (linkedItemInElement) {
linkedItem = linkedItemInElement;
} else {
linkedItem = allContentItems.find(
(m) => m.system.codename.toLowerCase() === linkedItemCodename.toLowerCase()
);
}

if (linkedItem) {
orderedLinkedItems.push(linkedItem);
}
}

richTextElement.linkedItems = orderedLinkedItems;
}
}
}
}
}
84 changes: 16 additions & 68 deletions lib/query/common/base-listing-query.class.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ElementType, Elements } from '../../elements';
import { IDeliveryClientConfig } from '../../config';
import {
continuationTokenHeaderName,
Expand All @@ -9,13 +8,27 @@ import {
IListAllQueryConfig,
IQueryConfig,
IContentItem,
ClientTypes
ClientTypes,
IUsedInItemRecord,
IContentType,
ITaxonomyGroup,
IContentItemDelta,
ILanguage
} from '../../models';
import { QueryService } from '../../services';
import { BaseQuery } from './base-query.class';

type ListingRecord<TClientTypes extends ClientTypes> =
| IContentItem
| IContentItemDelta
| IUsedInItemRecord<TClientTypes>
| IContentType<TClientTypes['contentTypeCodenames']>
| ILanguage<TClientTypes['languageCodenames']>
| ITaxonomyGroup<TClientTypes['taxonomyCodenames']>;

export abstract class BaseListingQuery<
TClientTypes extends ClientTypes,
TRecord extends ListingRecord<TClientTypes>,
TResponse extends IKontentListResponse,
TAllResponse extends IKontentListAllResponse,
TQueryConfig extends IQueryConfig,
Expand Down Expand Up @@ -76,72 +89,7 @@ export abstract class BaseListingQuery<
}

protected abstract allResponseFactory(
items: IContentItem[],
items: TRecord[],
responses: IDeliveryNetworkResponse<TResponse, TContract>[]
): TAllResponse;

protected linkItemsInRte(allContentItems: IContentItem[]): void {
for (const item of allContentItems) {
for (const elementKey of Object.keys(item.elements)) {
const element = item.elements[elementKey];

if (element.type === ElementType.ModularContent) {
const linkedItemElement = element as Elements.LinkedItemsElement;

// We create separate array for ordered items because the 'linkedItems' from response might be incomplete
// e.g. If 4 items are linked, only 2 might be available in the response. Rest needs to be mapped from all available items
const orderedLinkedItems: IContentItem[] = [];

for (const linkedItemCodename of linkedItemElement.value) {
let linkedItem: IContentItem | undefined;

const linkedItemInElement = linkedItemElement.linkedItems.find(
(m) => m.system.codename.toLowerCase() === linkedItemCodename.toLowerCase()
);
if (linkedItemInElement) {
linkedItem = linkedItemInElement;
} else {
linkedItem = allContentItems.find(
(m) => m.system.codename.toLowerCase() === linkedItemCodename.toLowerCase()
);
}

if (linkedItem) {
orderedLinkedItems.push(linkedItem);
}
}

// Replace linked items with the ordered one
linkedItemElement.linkedItems = orderedLinkedItems;
}

if (element.type === ElementType.RichText) {
const orderedLinkedItems: IContentItem[] = [];

const richTextElement = element as Elements.RichTextElement;

for (const linkedItemCodename of richTextElement.linkedItemCodenames) {
let linkedItem: IContentItem | undefined;

const linkedItemInElement = richTextElement.linkedItems.find(
(m) => m.system.codename.toLowerCase() === linkedItemCodename.toLowerCase()
);
if (linkedItemInElement) {
linkedItem = linkedItemInElement;
} else {
linkedItem = allContentItems.find(
(m) => m.system.codename.toLowerCase() === linkedItemCodename.toLowerCase()
);
}

if (linkedItem) {
orderedLinkedItems.push(linkedItem);
}
}

richTextElement.linkedItems = orderedLinkedItems;
}
}
}
}
}
1 change: 1 addition & 0 deletions lib/query/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './items-feed/items-feed-query.class';
export * from './language/languages-query.class';
export * from './sync/initialize-sync-query.class';
export * from './sync/sync-changes-query.class';
export * from './used-in/used-in-query.class';
Loading