@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.
190 lines (189 loc) • 8.87 kB
JavaScript
'use server';
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { ContentListDetail } from './detail/content-list-detail';
import { ContentListMaster } from './master/content-list-master';
import { ContentListsCommonRestService } from '../content-lists-common/content-lists-rest.setvice';
import { htmlAttributes, setHideEmptyVisual } from '../../editor/widget-framework/attributes';
import { getMinimumWidgetContext } from '../../editor/widget-framework/widget-context';
import { ContentViewDisplayMode } from '../content-lists-common/content-view-display-mode';
import { DetailPageSelectionMode } from '../content-lists-common/detail-page-selection-mode';
import { getPageNumber } from '../pager/pager-view-model';
import { ServiceMetadata } from '../../rest-sdk/service-metadata';
import { RestClient, RestSdkTypes } from '../../rest-sdk/rest-client';
import { FilterOperators } from '../../rest-sdk/filters/filter-clause';
import { Tracer } from '@progress/sitefinity-nextjs-sdk/diagnostics/empty';
import { RestClientForContext } from '../../services/rest-client-for-context';
export async function ContentList(props) {
const { span, ctx } = Tracer.traceWidget(props, true);
const model = props.model;
const properties = model.Properties;
const type = properties?.SelectedItems?.Content[0].Type;
if (props.requestContext.isEdit && !model.Caption && type) {
model.Caption = `Content list - ${ServiceMetadata.getModuleDisplayName(type)}`;
}
const context = props.requestContext;
const pageNumber = getPageNumber(properties.PagerMode, props.requestContext, properties.PagerQueryTemplate, properties.PagerTemplate);
let detailViewProps = {};
let masterViewProps = {};
let isDetailView = false;
if (properties.ContentViewDisplayMode === ContentViewDisplayMode.Automatic) {
if (context.detailItem && context.detailItem.ItemType === type && properties.DetailPageMode === DetailPageSelectionMode.SamePage) {
detailViewProps = handleDetailView(context.detailItem, props);
isDetailView = true;
}
else {
const detailProps = await handleShowDetailsViewOnChildDetailsView(props);
if (detailProps) {
detailViewProps = detailProps;
isDetailView = true;
}
else {
masterViewProps = await handleListView(props, context, pageNumber, ctx);
}
}
}
else if (properties.ContentViewDisplayMode === ContentViewDisplayMode.Detail) {
if (type) {
const selectedContent = properties.SelectedItems.Content[0];
const itemIdsOrdered = properties.SelectedItems.ItemIdsOrdered;
const detailProps = handleDetailView({
Id: itemIdsOrdered ? itemIdsOrdered[0] : '',
ItemType: selectedContent.Type,
ProviderName: selectedContent.Variations[0]?.Source
}, props);
detailViewProps = detailProps;
isDetailView = true;
}
}
else if (properties.ContentViewDisplayMode === ContentViewDisplayMode.Master) {
masterViewProps = await handleListView(props, context, pageNumber, ctx);
}
const attributes = htmlAttributes(props);
if (props.requestContext.isEdit && props.model.Properties.SelectedItems?.Content?.length &&
props.model.Properties.SelectedItems?.Content[0].Variations &&
props.model.Properties.SelectedItems.Content[0].Type) {
setHideEmptyVisual(attributes, true);
}
const result = (_jsxs(_Fragment, { children: [isDetailView && _jsx(ContentListDetail, { ...detailViewProps }), !isDetailView && _jsx(ContentListMaster, { ...masterViewProps }), Tracer.endSpan(span)] }));
// wrap everything in a single element so it will appear as a whole widget in the editor
if (props.requestContext.isEdit) {
return (_jsx("div", { ...attributes, children: result }));
}
else {
return result;
}
}
async function handleShowDetailsViewOnChildDetailsView(props) {
const context = props.requestContext;
const model = props.model;
const properties = model.Properties;
const type = properties?.SelectedItems?.Content[0].Type;
if (context.detailItem && properties.ShowDetailsViewOnChildDetailsView && type) {
const childTypes = ServiceMetadata.getChildTypes(type).flatMap((x, i) => x.map(y => {
return {
'value': y,
'key': i + 1
};
}));
let childTypeInDetails = childTypes.find(x => x.value === context.detailItem?.ItemType);
if (childTypeInDetails) {
let childItem = await RestClient.getItem({
id: context.detailItem.Id,
type: context.detailItem.ItemType,
provider: context.detailItem.ProviderName,
fields: ['ItemDefaultUrl']
});
let parentsTitles = childItem['ItemDefaultUrl'].split('/').filter((x) => x);
let parentTitle = parentsTitles.reverse()[childTypeInDetails.key];
if (type === RestSdkTypes.Blog) {
parentTitle = parentsTitles[0];
}
let parentItems = await RestClient.getItems({
type: type,
provider: context.detailItem.ProviderName,
filter: {
FieldName: 'UrlName',
Operator: FilterOperators.Equal,
FieldValue: parentTitle
}
});
if (parentItems.Items.length === 1) {
return await handleDetailView({
Id: parentItems.Items[0].Id,
ItemType: type,
ProviderName: parentItems.Items[0].Provider
}, props);
}
}
}
return null;
}
function getAttributes(props, fieldName) {
const viewCss = props.model.Properties.CssClasses?.find(x => x.FieldName === fieldName);
const contentListAttributes = props.model.Properties.Attributes?.ContentList || [];
let classAttribute = contentListAttributes.find(x => x.Key === 'class');
if (!classAttribute) {
classAttribute = {
Key: 'className',
Value: ''
};
contentListAttributes.push(classAttribute);
}
if (viewCss) {
classAttribute.Value += ` ${viewCss.CssClass}`;
}
classAttribute.Value = classAttribute.Value.trim();
const attributes = {};
contentListAttributes.forEach((pair) => {
attributes[pair.Key] = pair.Value;
});
return attributes;
}
function handleDetailView(detailItem, props) {
const detailProps = {
attributes: getAttributes(props, 'Details view'),
detailItem: detailItem,
viewName: props.model.Properties.SfDetailViewName,
widgetContext: getMinimumWidgetContext(props)
};
return detailProps;
}
async function handleListView(props, requestContext, currentPage, ctx) {
const listFieldMapping = {};
props.model.Properties.ListFieldMapping?.forEach((entry) => {
listFieldMapping[entry.FriendlyName] = entry.Name;
});
const fieldCssClassMap = {};
props.model.Properties.CssClasses?.forEach((entry) => {
fieldCssClassMap[entry.FieldName] = entry.CssClass;
});
const items = await ContentListsCommonRestService.getItems(props.model.Properties, props.requestContext.detailItem, requestContext, currentPage, ctx, props.model.Properties.ShowListViewOnChildDetailsView);
let detailPageUrl;
if (!(props.model.Properties.ContentViewDisplayMode === ContentViewDisplayMode.Master && props.model.Properties.DetailPageMode === DetailPageSelectionMode.SamePage)
&& items.Items.length > 0) {
detailPageUrl = props.requestContext.pageNode?.ViewUrl;
if (props.model.Properties.DetailPageMode === DetailPageSelectionMode.ExistingPage && props.model.Properties.DetailPage) {
const detailPages = await RestClientForContext.getItems(props.model.Properties.DetailPage, {
type: RestSdkTypes.Pages,
culture: props.requestContext.culture
});
if (detailPages.Items.length === 1) {
detailPageUrl = detailPages.Items[0].ViewUrl;
}
else {
detailPageUrl = undefined;
}
}
}
let contentListMasterModel = {
detailPageUrl: detailPageUrl,
fieldCssClassMap: fieldCssClassMap,
fieldMap: listFieldMapping,
items: items,
viewName: props.model.Properties.SfViewName,
attributes: getAttributes(props, 'Content list'),
widgetContext: getMinimumWidgetContext(props),
pageNumber: currentPage
};
return contentListMasterModel;
}