@progress/sitefinity-nextjs-sdk
Version:
Provides OOB widgets developed using the Next.js framework, which includes an abstraction layer for Sitefinity communication. Additionally, it offers an expanded API, typings, and tools for further development and integration.
221 lines (220 loc) • 10.2 kB
JavaScript
import { FilterOperators } from '../../rest-sdk/filters/filter-clause';
import { FilterConverterService } from '../../rest-sdk/filters/filter-converter';
import { FilterTypes } from '../../rest-sdk/filters/filter-types';
import { RestClient } from '../../rest-sdk/rest-client';
import { ServiceMetadata } from '../../rest-sdk/service-metadata';
import { EMTPY_GUID } from '../../editor/utils/guid';
import { RootUrlService } from '../../rest-sdk/root-url.service';
export class ContentListsCommonRestService {
static ClassificationSegmentRegex = /(^-in-((?:\w|-){1,}),(.+?);?$)+/;
static async getItems(entity, detailItem, requestContext, currentPage = 1, traceContext, showListViewOnChildDetailsView = true) {
if (entity.SelectedItems && entity.SelectedItems.Content && entity.SelectedItems.Content.length > 0
&& entity.SelectedItems.Content[0].Type && entity.SelectedItems.Content[0].Variations) {
const selectedContent = entity.SelectedItems.Content[0];
const variation = selectedContent.Variations[0];
if (!showListViewOnChildDetailsView && detailItem) {
const childTypes = ServiceMetadata.getChildTypes(selectedContent.Type).flatMap(x => x);
if (childTypes.find(x => x === detailItem.ItemType)) {
return Promise.resolve(({ Items: [], TotalCount: 0 }));
}
}
let parentFilter = null;
if (variation?.DynamicFilterByParent) {
parentFilter = this.getParentFilterExpression(selectedContent, detailItem);
if (!parentFilter && !entity.ShowListViewOnEmptyParentFilter) {
return Promise.resolve(({ Items: [], TotalCount: 0 }));
}
}
// handle filtering
let mainFilter = FilterConverterService.getMainFilter(variation);
mainFilter = ContentListsCommonRestService.modifyFilterOperatorForMainFilter(entity, mainFilter);
const classification = requestContext ? await this.getClassificationFilter(entity, requestContext, traceContext) : null;
const additionalFilter = entity.FilterExpression;
const filters = [mainFilter, additionalFilter, parentFilter, classification];
let bigFilter = {
Operator: entity.SelectionGroupLogicalOperator,
ChildFilters: filters.filter(x => x)
};
const skipAndTakeParams = this.getSkipAndTake(entity, currentPage);
const getAllArgs = {
skip: skipAndTakeParams.Skip,
take: skipAndTakeParams.Take,
count: skipAndTakeParams.Count,
type: selectedContent.Type,
provider: variation?.Source,
culture: requestContext?.culture,
orderBy: this.getOrderByExpression(entity),
fields: this.getSelectExpression(entity),
filter: bigFilter,
traceContext
};
const result = await RestClient.getItems(getAllArgs);
if (entity.SelectedItems?.ItemIdsOrdered && entity.SelectedItems?.ItemIdsOrdered.length > 1) {
const orderedCollection = [];
entity.SelectedItems.ItemIdsOrdered.forEach(id => {
const orderedItem = result.Items.find(x => x.Id === id);
if (orderedItem) {
orderedCollection.push(orderedItem);
}
});
return Promise.resolve({ Items: orderedCollection, TotalCount: result.TotalCount });
}
return Promise.resolve(result);
}
;
return Promise.resolve(({ Items: [], TotalCount: 0 }));
}
static getParentFilterExpression(selectedContent, detailItem) {
let filterByParentExpressionSerialized = null;
let parentType = ServiceMetadata.getParentType(selectedContent.Type);
if (parentType != null && detailItem && detailItem.ItemType === parentType) {
return {
FieldName: 'ParentId',
FieldValue: detailItem.Id,
Operator: FilterOperators.Equal
};
}
return filterByParentExpressionSerialized;
}
static getSkipAndTake(entity, pageNumber) {
let retVal = {};
let currentPage = 1;
if (!entity.ListSettings) {
return retVal;
}
switch (entity.ListSettings.DisplayMode) {
case 'Paging':
retVal.ShowPager = true;
retVal.Take = entity.ListSettings.ItemsPerPage;
currentPage = pageNumber;
if (currentPage > 1) {
retVal.Skip = entity.ListSettings.ItemsPerPage * (currentPage - 1);
}
retVal.Count = true;
break;
case 'Limit':
retVal.Take = entity.ListSettings.LimitItemsCount;
break;
default:
break;
}
return retVal;
}
static getOrderByExpression(entity) {
if (entity.OrderBy === 'Manually') {
return;
}
const sortExpression = entity.OrderBy === 'Custom' ?
entity.SortExpression :
entity.OrderBy;
if (!sortExpression) {
return;
}
const orderByCollection = [];
const sortExpressions = sortExpression.split(',');
sortExpressions.forEach(expression => {
const sortExpressionParts = expression.trim().split(' ');
if (sortExpressionParts.length !== 2) {
return;
}
const sortOrder = sortExpressionParts[1].trim().toUpperCase();
const orderBy = {
Name: sortExpressionParts[0],
Type: sortOrder
};
orderByCollection.push(orderBy);
});
return orderByCollection;
}
static getSelectExpression(entity) {
if (!entity.SelectExpression) {
return ['*'];
}
const splitExpressions = entity.SelectExpression.split(';');
const fields = splitExpressions.map((split) => {
return split.trim();
});
return fields;
}
static modifyFilterOperatorForMainFilter(entity, filter) {
if (entity.SelectedItems && entity.SelectedItems.Content && entity.SelectedItems?.Content.length > 0 && entity.SelectedItems?.Content[0].Variations) {
for (let i = 0; i < entity.SelectedItems.Content[0].Variations.length; i++) {
const variation = entity.SelectedItems.Content[0].Variations[i];
if (filter && variation.Filter.Key === FilterTypes.Complex) {
if (entity.SelectionGroupLogicalOperator === 'AND') {
filter.Operator = 'AND';
}
else {
filter.Operator = 'OR';
}
}
}
}
return filter;
}
static getClassificationSegment(requestContext) {
const url = requestContext.url;
const segments = url ? url.split('/') : [];
const matchedSegments = segments.map(x => decodeURIComponent(x)).map(x => x.match(ContentListsCommonRestService.ClassificationSegmentRegex)).filter(x => !!x);
if (matchedSegments.length === 1) {
const segment = matchedSegments[0][0];
const segmentIndex = requestContext.layout.UrlParameters?.findIndex(x => x === segment);
if (segmentIndex > -1) {
requestContext.layout.UrlParameters?.splice(segmentIndex, 1);
}
return segment;
}
return null;
}
static async getClassificationFilter(entity, requestContext, traceContext) {
const classificationSegment = this.getClassificationSegment(requestContext);
if (classificationSegment) {
const emptyClause = { FieldValue: EMTPY_GUID, FieldName: 'Id', Operator: FilterOperators.Equal };
const distinctFilters = classificationSegment.split(';').map(x => {
const match = x.match(ContentListsCommonRestService.ClassificationSegmentRegex);
return {
taxaName: match[2],
taxaUrl: match[3]
};
});
const filterPromises = distinctFilters.map(({ taxaName, taxaUrl }) => {
return new Promise(resolve => {
const queryParams = RestClient.buildQueryParams({
'sf_culture': requestContext.culture,
'@param': `'${encodeURIComponent(taxaUrl)}'`
});
RestClient.sendRequest({
url: `${RootUrlService.getServerCmsServiceUrl()}/taxonomies/Default.GetTaxonByUrl(taxonomyName='${taxaName}',taxonUrl=@param)${queryParams}`,
traceContext
}).then(taxonId => {
const fieldName = ServiceMetadata.getTaxonomyFieldName(entity.SelectedItems?.Content[0].Type, taxaName);
if (fieldName) {
resolve({
FieldName: fieldName,
FieldValue: taxonId?.value,
Operator: FilterOperators.ContainsOr
});
}
else {
resolve(emptyClause);
}
});
});
});
return Promise.all(filterPromises).then(x => {
const filter = {
ChildFilters: [],
Operator: 'AND'
};
if (x.includes(emptyClause)) {
filter.ChildFilters = [emptyClause];
}
else {
filter.ChildFilters = x;
}
return filter;
});
}
return Promise.resolve(null);
}
}