import { ElementType, Elements } from '../../elements'; import { IDeliveryClientConfig } from '../../config'; import { ClientTypes, Filters, IContentItem, IKontentListAllResponse, IKontentListResponse, IQueryConfig, Parameters, SortOrder } from '../../models'; import { QueryService } from '../../services'; import { BaseListingQuery } from './base-listing-query.class'; export abstract class BaseItemListingQuery< TClientTypes extends ClientTypes, TResponse extends IKontentListResponse, TAllResponse extends IKontentListAllResponse, TQueryConfig extends IQueryConfig, TContract > extends BaseListingQuery { constructor(protected config: IDeliveryClientConfig, protected queryService: QueryService) { super(config, queryService); } /** * Empty filter condition * @param element Element with empty value */ emptyFilter(element: string): this { this.parameters.push(new Filters.EmptyFilter(element)); return this; } /** * Not empty filter condition * @param element Element with non-empty value */ notEmptyFilter(element: string): this { this.parameters.push(new Filters.NotEmptyFilter(element)); return this; } /** * Equals filter condition * @param element Element to filter. Example: 'elements.movie' * @param value Value to match. Example: 'Kingsman' */ equalsFilter(element: string, value: string): this { this.parameters.push(new Filters.EqualsFilter(element, value)); return this; } /** * Not equals filter condition * @param element Element to filter. Example: 'elements.movie' * @param value Value to match. Example: 'Kingsman' */ notEqualsFilter(element: string, value: string): this { this.parameters.push(new Filters.NotEqualsFilter(element, value)); return this; } /** * All filter * @param element Element to filter. * @param values Values */ allFilter(element: string, values: string[]): this { this.parameters.push(new Filters.AllFilter(element, values)); return this; } /** * Any filter * @param element Element to filter. * @param values Values */ anyFilter(element: string, values: string[]): this { this.parameters.push(new Filters.AnyFilter(element, values)); return this; } /** * Contains filter * @param element Element to filter. * @param values Values */ containsFilter(element: string, values: string[]): this { this.parameters.push(new Filters.ContainsFilter(element, values)); return this; } /** * Greater then filter * @param element Element to filter. * @param value Value */ greaterThanFilter(element: string, value: string | number): this { this.parameters.push(new Filters.GreaterThanFilter(element, value)); return this; } /** * Greater then or equals filter * @param element Element to filter. * @param value Value */ greaterThanOrEqualFilter(element: string, value: string | number): this { this.parameters.push(new Filters.GreaterThanOrEqualFilter(element, value)); return this; } /** * In filter * @param element Element to filter. * @param values Values */ inFilter(element: string, values: string[]): this { this.parameters.push(new Filters.InFilter(element, values)); return this; } /** * Not in filter * @param element Element to filter. * @param values Values */ notInFilter(element: string, values: string[]): this { this.parameters.push(new Filters.NotInFilter(element, values)); return this; } /** * Less then filter * @param element Element to filter. * @param value Value */ lessThanFilter(element: string, value: string | number): this { this.parameters.push(new Filters.LessThanFilter(element, value)); return this; } /** * @param element Element to filter. * @param value Value */ lessThanOrEqualFilter(element: string, value: string | number): this { this.parameters.push(new Filters.LessThanOrEqualFilter(element, value)); return this; } /** * @param element Element to filter. * @param lowerValue Lower value of range (e.g. 2) * @param higherValue Higher value of range (e.g. 10) */ rangeFilter(element: string, lowerValue: number | string, higherValue: number | string): this { this.parameters.push(new Filters.RangeFilter(element, lowerValue, higherValue)); return this; } /** * Limits the number of items returned by query * @param limit Number of items to load */ limitParameter(limit: number): this { this.parameters.push(new Parameters.LimitParameter(limit)); return this; } /** * Orders query based on given element and sort order * @param element Element by which to order * @param sortOrder Asc/Desc order type */ orderParameter(element: string, sortOrder: SortOrder): this { this.parameters.push(new Parameters.OrderParameter(element, sortOrder)); return this; } /** * Sets descending order on given element * @param element Element by which to order */ orderByDescending(element: string): this { this.parameters.push(new Parameters.OrderParameter(element, 'desc')); return this; } /** * Sets Ascending order on given element * @param element Element by which to order */ orderByAscending(element: string): this { this.parameters.push(new Parameters.OrderParameter(element, 'asc')); return this; } /** * Skips the selected number of items * @param skip Number of items to skip */ skipParameter(skip: number): this { 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; } } } } }