UNPKG

@acorel/contentful-integration

Version:
246 lines (225 loc) 7.35 kB
import {Injectable} from "@angular/core"; import { CmsComponentType, convertComponent, getComponentTypeByTypeName, GraphqlCmsIntegrationService } from "@acorel/graphql-integration"; import * as gqlbuilder from 'gql-query-builder' import {gql, QueryOptions} from "@apollo/client/core"; import {CmsService, CmsStructureModel, PageContext} from "@spartacus/core"; import {ContentSlotData} from "@spartacus/core/src/cms/model/content-slot-data.model"; import {CmsComponent} from "@spartacus/core/src/model/cms.model"; import {ContentfulLivePreviewService} from "./contentful-live-preview.service"; import {CONTENTFUL_ENTITY} from "./contentful-integration.util"; import {ContentfulConfig} from "./contentful-config"; @Injectable({ providedIn: 'root', }) export class ContentfulIntegrationService implements GraphqlCmsIntegrationService { constructor( private contentfulLivePreviewService: ContentfulLivePreviewService, private cmsService: CmsService, private config: ContentfulConfig ) { GraphqlCmsIntegrationService.COMPONENTTYPES = this.componentTypes(); } pageQuery(options: {preview: boolean, slug: string, pageType: string}): QueryOptions { const query = gqlbuilder.query([{ operation: "webPageCollection", fields: [{ items: [ ...CONTENTFUL_ENTITY, 'slug', 'pageTitle', 'pageType', 'showResults', { operation: "contentSlotsCollection", fields: [{ items: [ ...CONTENTFUL_ENTITY, 'name', { operation: "componentsCollection", fields: [{ items: [ ...this.pageComponentQuery() ] }], variables: { componentLimit: { name: "limit", value: 10 } } } ] }], variables: { contentSlotLimit: { name: "limit", value: 10 } } } ] }], variables: { preview: { name: "preview", value: options.preview, }, limit: { name: "limit", value: 1 }, where: { name: "where", type: "WebPageFilter", value: { "AND": [ {"slug": options.slug}, {"pageType": options.pageType} ] } } } },]); return { query: gql(query.query), variables: query.variables } } pageComponentQuery() : object[] { const fragments: object[] = []; this.componentTypes().forEach(ct => { fragments.push({ operation: ct.typename, fields: CONTENTFUL_ENTITY, fragment: true, }) }) return fragments; } pageResult(pageContext: PageContext, item: any): CmsStructureModel { console.log('ITEM', item); if (this.contentfulLivePreviewService.isPreviewEnabled()) { this.contentfulLivePreviewService.subscribe(pageContext.id, pageContext,{ locale: this.contentfulLivePreviewService.currentLocale(), data: item, callback: data => { this.contentfulLivePreviewService.update(pageContext.id, pageContext, data); this.cmsService.refreshLatestPage(); } }) } return { page: { pageId: pageContext.id, name: item.pageTitle, title: item.pageTitle, slots: this.convertSlots(pageContext, item.contentSlotsCollection.items), properties: { showResults: item.showResults } } } } convertSlots(pageContext: PageContext, items: any[] ): { [key: string]: ContentSlotData; } { let returnObject = {} as { [key: string]: ContentSlotData; }; items.forEach(item => { let name = (item.name) ? item.name : item.sys.id; let slot = this.convertSlot(pageContext, item); if (returnObject[name] && returnObject[name].components && slot.components) { slot.components.forEach(comp => { // @ts-ignore returnObject[name].components.push(comp); }) } else { returnObject[name] = slot; } }); return returnObject; } convertSlot(pageContext: PageContext, item: any ): ContentSlotData { return { // We introduce a slot component, this will make it possible to add multiple contentful slot component in // a single page slot. components: [convertComponent(pageContext, item)] } } componentQuery(id: string, options: {preview: boolean, typeCode?: string}): QueryOptions | undefined { const type = (options.typeCode) ? options.typeCode : GraphqlCmsIntegrationService.COMPONENT_TYPE_MAPPING[id]?.typeName; const componentType = getComponentTypeByTypeName(type); if (componentType) { const query = gqlbuilder.query([{ operation: componentType.collection, fields: componentType.fields, variables: { preview: { name: "preview", value: options.preview, }, id: { name: "id", type: "String!", value: id } } }]); return { query: gql(query.query), variables: query.variables, fetchPolicy: (options.preview) ? 'network-only' : 'cache-first' } } else { return undefined } } componentResult<T extends CmsComponent>(id: string, pageContext: PageContext, item: any, typeCode?: string): T { const type = (typeCode) ? typeCode : GraphqlCmsIntegrationService.COMPONENT_TYPE_MAPPING[id]?.typeName; const componentType = getComponentTypeByTypeName(type); if (componentType) { // If live preview enabled: if (this.contentfulLivePreviewService.isPreviewEnabled()) { this.contentfulLivePreviewService.subscribe(id, pageContext,{ locale: this.contentfulLivePreviewService.currentLocale(), data: item, callback: data => { this.contentfulLivePreviewService.update(id, pageContext, data); this.cmsService.refreshComponent(id, pageContext); } }) } return componentType.converter(pageContext, item); } else { throw "No component type found for component with id: " + id; } } private componentTypes() : CmsComponentType[] { if (this.config.contentful?.components) { return Array.from(new Map(Object.entries(this.config.contentful?.components)).values()) .filter(item => {return item != undefined}).map(item => { return item.component}) as CmsComponentType[]; } return []; } isPreview(pageContext: PageContext): boolean { if (this.config.contentful?.previewUrl) { return pageContext.id.startsWith(this.config.contentful.previewUrl); } return false; } slugFromPage(pageContext: PageContext): string { if (this.config.contentful?.previewUrl) { return pageContext.id.replace(this.config.contentful.previewUrl, "") .replace(/^\/|\/$/g, ''); } return pageContext.id; } }