diff --git a/libs/domain/content/link/link.component.ts b/libs/domain/content/link/link.component.ts index 971186437..72fbbd9bb 100644 --- a/libs/domain/content/link/link.component.ts +++ b/libs/domain/content/link/link.component.ts @@ -35,10 +35,11 @@ export class ContentLinkComponent extends ContentMixin< protected $link = computed(() => { const { url, type, id, qualifier, params } = this.$options(); + if (url) return of(url); if (type) return this.semanticLinkService.get({ - type: type, + type, id, qualifier, params, diff --git a/libs/domain/content/src/index.ts b/libs/domain/content/src/index.ts index 5cb14365b..0478f3fd3 100644 --- a/libs/domain/content/src/index.ts +++ b/libs/domain/content/src/index.ts @@ -1,3 +1,4 @@ export * from './feature'; export * from './models'; +export * from './resolvers'; export * from './services'; diff --git a/libs/template/labs/src/articles/article.model.ts b/libs/domain/content/src/models/cms.model.ts similarity index 53% rename from libs/template/labs/src/articles/article.model.ts rename to libs/domain/content/src/models/cms.model.ts index 8c57c80be..664aa2296 100644 --- a/libs/template/labs/src/articles/article.model.ts +++ b/libs/domain/content/src/models/cms.model.ts @@ -1,14 +1,18 @@ +// TODO: create dynamic types and dependable dynamic pages. +export const cmsTypes = ['article', 'faq', 'about']; + declare global { interface ContentFields { article: undefined; - about: undefined; faq: undefined; + about: undefined; } } -export interface ArticleContent { +export interface CmsContent { heading: string; description: string; content: string; type: string; + [key: string]: unknown; } diff --git a/libs/domain/content/src/models/content.model.ts b/libs/domain/content/src/models/content.model.ts index 2a11c68e3..973b6d632 100644 --- a/libs/domain/content/src/models/content.model.ts +++ b/libs/domain/content/src/models/content.model.ts @@ -1,5 +1,8 @@ declare global { interface ContentFields { + /** + * Page or component config. // ExperienceComponent + */ component: undefined; } } diff --git a/libs/domain/content/src/models/index.ts b/libs/domain/content/src/models/index.ts index 7ea3764ce..b01644602 100644 --- a/libs/domain/content/src/models/index.ts +++ b/libs/domain/content/src/models/index.ts @@ -1,3 +1,4 @@ +export * from './cms.model'; export * from './content.model'; /** diff --git a/libs/template/labs/src/articles/resolvers/article-page-description-meta.resolver.ts b/libs/domain/content/src/resolvers/cms-page-description-meta.resolver.ts similarity index 77% rename from libs/template/labs/src/articles/resolvers/article-page-description-meta.resolver.ts rename to libs/domain/content/src/resolvers/cms-page-description-meta.resolver.ts index aa64670d8..cb5179568 100644 --- a/libs/template/labs/src/articles/resolvers/article-page-description-meta.resolver.ts +++ b/libs/domain/content/src/resolvers/cms-page-description-meta.resolver.ts @@ -1,8 +1,3 @@ -import { - ContentContext, - ContentQualifier, - ContentService, -} from '@oryx-frontend/content'; import { ContextService, ElementResolver, @@ -11,9 +6,10 @@ import { import { inject } from '@oryx-frontend/di'; import { RouterService } from '@oryx-frontend/router'; import { Observable, combineLatest, map, of, switchMap } from 'rxjs'; -import { ArticleContent } from '../article.model'; +import { CmsContent, ContentQualifier } from '../models'; +import { ContentContext, ContentService } from '../services'; -export class ArticlePageDescriptionMetaResolver implements PageMetaResolver { +export class CmsPageDescriptionMetaResolver implements PageMetaResolver { constructor( protected context = inject(ContextService), protected content = inject(ContentService), @@ -26,7 +22,11 @@ export class ArticlePageDescriptionMetaResolver implements PageMetaResolver { combineLatest([ this.context.get(null, ContentContext.Content), this.router.currentRoute(), - ]).pipe(map(([type, route]) => route.includes(`/${type}/`))), + ]).pipe( + map(([qualifier, route]) => + route.includes(`/${qualifier?.type}/${qualifier?.id}`) + ) + ), ]); } @@ -41,7 +41,7 @@ export class ArticlePageDescriptionMetaResolver implements PageMetaResolver { if (!id || !type) return of({}); return this.content - .get({ + .get({ id, type, entities: [type], diff --git a/libs/template/labs/src/articles/resolvers/article-page-title-meta.resolver.ts b/libs/domain/content/src/resolvers/cms-page-title-meta.resolver.ts similarity index 77% rename from libs/template/labs/src/articles/resolvers/article-page-title-meta.resolver.ts rename to libs/domain/content/src/resolvers/cms-page-title-meta.resolver.ts index 8cb0ee089..1426d71af 100644 --- a/libs/template/labs/src/articles/resolvers/article-page-title-meta.resolver.ts +++ b/libs/domain/content/src/resolvers/cms-page-title-meta.resolver.ts @@ -1,8 +1,3 @@ -import { - ContentContext, - ContentQualifier, - ContentService, -} from '@oryx-frontend/content'; import { ContextService, ElementResolver, @@ -11,9 +6,10 @@ import { import { inject } from '@oryx-frontend/di'; import { RouterService } from '@oryx-frontend/router'; import { Observable, combineLatest, map, of, switchMap } from 'rxjs'; -import { ArticleContent } from '../article.model'; +import { CmsContent, ContentQualifier } from '../models'; +import { ContentContext, ContentService } from '../services'; -export class ArticlePageTitleMetaResolver implements PageMetaResolver { +export class CmsPageTitleMetaResolver implements PageMetaResolver { constructor( protected context = inject(ContextService), protected router = inject(RouterService), @@ -26,7 +22,11 @@ export class ArticlePageTitleMetaResolver implements PageMetaResolver { combineLatest([ this.context.get(null, ContentContext.Content), this.router.currentRoute(), - ]).pipe(map(([type, route]) => route.includes(`/${type}/`))), + ]).pipe( + map(([qualifier, route]) => + route.includes(`/${qualifier?.type}/${qualifier?.id}`) + ) + ), ]); } @@ -41,7 +41,7 @@ export class ArticlePageTitleMetaResolver implements PageMetaResolver { if (!id || !type) return of({}); return this.content - .get({ + .get({ id, type, entities: [type], diff --git a/libs/domain/content/src/resolvers/index.ts b/libs/domain/content/src/resolvers/index.ts new file mode 100644 index 000000000..6c2a01c34 --- /dev/null +++ b/libs/domain/content/src/resolvers/index.ts @@ -0,0 +1,2 @@ +export * from './cms-page-description-meta.resolver'; +export * from './cms-page-title-meta.resolver'; diff --git a/libs/template/labs/src/articles/article-context.ts b/libs/domain/content/src/services/cms/cms-context.ts similarity index 82% rename from libs/template/labs/src/articles/article-context.ts rename to libs/domain/content/src/services/cms/cms-context.ts index 2c96fcc89..5e5fd3915 100644 --- a/libs/template/labs/src/articles/article-context.ts +++ b/libs/domain/content/src/services/cms/cms-context.ts @@ -1,10 +1,10 @@ -import { ContentContext } from '@oryx-frontend/content'; import { ContextFallback } from '@oryx-frontend/core'; import { inject, Provider } from '@oryx-frontend/di'; import { RouterService } from '@oryx-frontend/router'; import { combineLatest, map } from 'rxjs'; +import { ContentContext } from '../content-context'; -export const ArticleQualifierContextFallback: Provider = { +export const CmsQualifierContextFallback: Provider = { provide: `${ContextFallback}${ContentContext.Content}`, useFactory: () => combineLatest([ diff --git a/libs/template/labs/src/articles/article-providers.ts b/libs/domain/content/src/services/cms/cms-providers.ts similarity index 50% rename from libs/template/labs/src/articles/article-providers.ts rename to libs/domain/content/src/services/cms/cms-providers.ts index 251f0e7e0..658c36868 100644 --- a/libs/template/labs/src/articles/article-providers.ts +++ b/libs/domain/content/src/services/cms/cms-providers.ts @@ -1,30 +1,29 @@ -import { - Content, - ContentConfig, - ContentQualifier, - ContentService, -} from '@oryx-frontend/content'; import { PageMetaResolver, provideEntity } from '@oryx-frontend/core'; import { Provider } from '@oryx-frontend/di'; -import { provideExperienceData } from '@oryx-frontend/experience'; -import { ArticleQualifierContextFallback } from './article-context'; -import { experienceArticlePages } from './article-page'; -import { articleTypes } from './article-types'; +import { Content, ContentQualifier, cmsTypes } from '../../models'; import { - ArticlePageDescriptionMetaResolver, - ArticlePageTitleMetaResolver, -} from './resolvers'; + CmsPageDescriptionMetaResolver, + CmsPageTitleMetaResolver, +} from '../../resolvers'; +import { ContentConfig } from '../adapter'; +import { ContentService } from '../content.service'; +import { CmsQualifierContextFallback } from './cms-context'; +import { contentfulProviders } from './contentful'; +import { storyblokProviders } from './storyblok'; +import { strapiProviders } from './strapi'; -export const articleProviders: Provider[] = [ - ArticleQualifierContextFallback, - provideExperienceData(experienceArticlePages), +export const cmsProviders: Provider[] = [ + ...contentfulProviders, + ...storyblokProviders, + ...strapiProviders, + CmsQualifierContextFallback, { provide: PageMetaResolver, - useClass: ArticlePageTitleMetaResolver, + useClass: CmsPageTitleMetaResolver, }, { provide: PageMetaResolver, - useClass: ArticlePageDescriptionMetaResolver, + useClass: CmsPageDescriptionMetaResolver, }, { provide: ContentConfig, @@ -41,10 +40,10 @@ export const articleProviders: Provider[] = [ }, }, }, - ...articleTypes.map((type) => + ...cmsTypes.map((type) => provideEntity(type, { service: ContentService, - context: type, + context: 'content', get: (service, qualifier) => (service as ContentService).get({ ...qualifier, type }), }) diff --git a/libs/domain/content/src/services/cms/index.ts b/libs/domain/content/src/services/cms/index.ts index 184e49469..afde5c7f5 100644 --- a/libs/domain/content/src/services/cms/index.ts +++ b/libs/domain/content/src/services/cms/index.ts @@ -1,3 +1,5 @@ +export * from './cms-context'; +export * from './cms-providers'; export * from './contentful'; export * from './storyblok'; export * from './strapi'; diff --git a/libs/domain/content/src/services/content.providers.ts b/libs/domain/content/src/services/content.providers.ts index abb28ba93..2184f5e6b 100644 --- a/libs/domain/content/src/services/content.providers.ts +++ b/libs/domain/content/src/services/content.providers.ts @@ -2,11 +2,7 @@ import { provideEntity } from '@oryx-frontend/core'; import { Provider } from '@oryx-frontend/di'; import { ExperienceAdapter } from '@oryx-frontend/experience'; import { ContentExperienceAdapter } from './adapter'; -import { - contentfulProviders, - storyblokProviders, - strapiProviders, -} from './cms'; +import { cmsProviders } from './cms'; import { ContentContext } from './content-context'; import { ContentService } from './content.service'; import { DefaultContentService } from './default-content.service'; @@ -25,11 +21,9 @@ export const contentProviders: Provider[] = [ provide: FontService, useClass: DefaultFontService, }, - ...contentfulProviders, - ...storyblokProviders, - ...strapiProviders, provideEntity('content', { service: ContentService, context: ContentContext.Content, }), + ...cmsProviders, ]; diff --git a/libs/platform/core/src/services/page-meta/page-meta-resolver/default-page-meta-resolver.service.ts b/libs/platform/core/src/services/page-meta/page-meta-resolver/default-page-meta-resolver.service.ts index 7ff7775f4..d697300de 100644 --- a/libs/platform/core/src/services/page-meta/page-meta-resolver/default-page-meta-resolver.service.ts +++ b/libs/platform/core/src/services/page-meta/page-meta-resolver/default-page-meta-resolver.service.ts @@ -37,7 +37,10 @@ export class DefaultPageMetaResolverService implements PageMetaResolverService { ).pipe( map((data) => data - .filter(([score]) => score !== ResolverScore.NotUsed) + .filter( + ([score, data]) => + score !== ResolverScore.NotUsed && Object.keys(data).length + ) .sort(([aScore], [bScore]) => aScore - bScore) .reduce((acc, [_, elements]) => ({ ...acc, ...elements }), {}) ) diff --git a/libs/platform/experience/data-text/data-text.component.ts b/libs/platform/experience/data-text/data-text.component.ts index fc0741bf2..fa1d6ca8e 100644 --- a/libs/platform/experience/data-text/data-text.component.ts +++ b/libs/platform/experience/data-text/data-text.component.ts @@ -20,6 +20,7 @@ export class DataTextComponent extends TextMixin( protected $data = computed(() => { const { entity: type, field } = this.$options(); + return this.entityService .getField({ element: this, type, field }) .pipe(catchError(() => of())); diff --git a/libs/template/labs/src/articles/article-page.ts b/libs/template/labs/src/articles/article-page.ts deleted file mode 100644 index 91b53088d..000000000 --- a/libs/template/labs/src/articles/article-page.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { ExperienceComponent } from '@oryx-frontend/experience'; -import { SuggestionField } from '@oryx-frontend/search'; -import { articleTypes } from './article-types'; - -export const experienceArticlePages = [ - { - merge: { - selector: 'legal-links', - type: 'patch', - }, - type: 'oryx-composition', - components: [ - { - type: 'oryx-content-text', - content: { data: { text: `©️ ${new Date().getFullYear()} Spryker` } }, - }, - { - type: 'oryx-content-list', - options: { - tags: 'legal', - rules: [ - { - layout: { - type: 'flex', - divider: true, - }, - width: 'auto', - }, - ], - }, - }, - ], - }, - ...articleTypes - .map( - (type) => - [ - { - type: 'Page', - id: `${type}-list`, - meta: { - title: `${type} List`, - route: `/${type}/:id`, - routeType: type, - }, - components: [ - { ref: 'header' }, - { - type: 'oryx-composition', - options: { - rules: [{ layout: { type: 'split' }, padding: '30px 0' }], - }, - components: [ - { - type: 'oryx-site-breadcrumb', - options: { rules: [{ colSpan: 2 }] }, - }, - { - type: 'oryx-search-box', - options: { - rules: [{ margin: 'auto', width: '580px' }], - [SuggestionField.Suggestions]: null, - [SuggestionField.Categories]: null, - [SuggestionField.Contents]: null, - [SuggestionField.Products]: null, - [type]: { max: 8 }, - }, - }, - { - type: 'oryx-content-list', - options: { - rules: [{ layout: { type: 'list' } }], - }, - }, - ], - }, - { ref: 'footer' }, - ], - }, - { - type: 'Page', - id: type, - meta: { - title: type, - route: `/${type}/:id`, - routeType: 'content', - }, - components: [ - { ref: 'header' }, - { - type: 'oryx-composition', - options: { - rules: [{ layout: { type: 'split' }, padding: '30px 0' }], - }, - components: [ - { - type: 'oryx-site-breadcrumb', - options: { rules: [{ colSpan: 2 }] }, - }, - - { - type: 'oryx-data-text', - options: { - field: 'content', - }, - }, - ], - }, - { ref: 'footer' }, - ], - }, - ] as ExperienceComponent[] - ) - .flat(), -]; diff --git a/libs/template/labs/src/articles/article-types.ts b/libs/template/labs/src/articles/article-types.ts deleted file mode 100644 index 05fe25502..000000000 --- a/libs/template/labs/src/articles/article-types.ts +++ /dev/null @@ -1 +0,0 @@ -export const articleTypes = ['article', 'faq', 'about']; diff --git a/libs/template/labs/src/articles/index.ts b/libs/template/labs/src/articles/index.ts deleted file mode 100644 index 1560b8543..000000000 --- a/libs/template/labs/src/articles/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './article-context'; -export * from './article-page'; -export * from './article-providers'; -export * from './article.model'; -export * from './resolvers'; diff --git a/libs/template/labs/src/articles/resolvers/article-page-description-meta.resolver.spec.ts b/libs/template/labs/src/articles/resolvers/article-page-description-meta.resolver.spec.ts deleted file mode 100644 index 055253739..000000000 --- a/libs/template/labs/src/articles/resolvers/article-page-description-meta.resolver.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { ContentService } from '@oryx-frontend/content'; -import { ContextService } from '@oryx-frontend/core'; -import { createInjector, destroyInjector } from '@oryx-frontend/di'; -import { RouterService } from '@oryx-frontend/router'; -import { of } from 'rxjs'; -import { ArticlePageDescriptionMetaResolver } from './article-page-description-meta.resolver'; - -const mockContentService = { - get: vi.fn(), -}; - -const mockContextService = { - get: vi.fn(), -}; - -const mockRouterService = { - currentRoute: vi.fn(), -}; - -describe('ArticlePageDescriptionMetaResolver', () => { - let service: ArticlePageDescriptionMetaResolver; - - beforeEach(() => { - const testInjector = createInjector({ - providers: [ - { - provide: ArticlePageDescriptionMetaResolver, - useClass: ArticlePageDescriptionMetaResolver, - }, - { - provide: ContextService, - useValue: mockContextService, - }, - { - provide: ContentService, - useValue: mockContentService, - }, - { - provide: RouterService, - useValue: mockRouterService, - }, - ], - }); - - service = testInjector.inject(ArticlePageDescriptionMetaResolver); - }); - - afterEach(() => { - destroyInjector(); - vi.resetAllMocks(); - }); - - describe('getScore', () => { - it('should return proper value if article exist', () => { - const callback = vi.fn(); - mockContextService.get.mockReturnValueOnce(of('id')); - mockContextService.get.mockReturnValue(of('article')); - mockRouterService.currentRoute.mockReturnValue(of(`/article/saf`)); - service.getScore().subscribe(callback); - expect(callback).toHaveBeenCalledWith(['id', 'article', true]); - }); - - it('should return proper value if article is not exist', () => { - const callback = vi.fn(); - mockContextService.get.mockReturnValue(of(undefined)); - mockRouterService.currentRoute.mockReturnValue(of('')); - - service.getScore().subscribe(callback); - expect(callback).toHaveBeenCalledWith([undefined, undefined, false]); - }); - }); - - describe('resolve', () => { - it('should return proper object with article description', () => { - const callback = vi.fn(); - mockContextService.get.mockReturnValueOnce(of('id')); - mockContextService.get.mockReturnValue(of('type')); - mockContentService.get.mockReturnValue( - of({ - fields: { - description: 'Description A', - }, - }) - ); - service.resolve().subscribe(callback); - expect(mockContentService.get).toHaveBeenCalledWith({ - id: 'id', - type: 'type', - entities: ['type'], - }); - expect(callback).toHaveBeenCalledWith({ - description: 'Description A', - }); - }); - }); -}); diff --git a/libs/template/labs/src/articles/resolvers/article-page-title-meta.resolver.spec.ts b/libs/template/labs/src/articles/resolvers/article-page-title-meta.resolver.spec.ts deleted file mode 100644 index df3d16e4b..000000000 --- a/libs/template/labs/src/articles/resolvers/article-page-title-meta.resolver.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { ContentService } from '@oryx-frontend/content'; -import { ContextService } from '@oryx-frontend/core'; -import { createInjector, destroyInjector } from '@oryx-frontend/di'; -import { RouterService } from '@oryx-frontend/router'; -import { of } from 'rxjs'; -import { ArticlePageTitleMetaResolver } from './article-page-title-meta.resolver'; - -const mockContentService = { - get: vi.fn(), -}; - -const mockContextService = { - get: vi.fn(), -}; - -const mockRouterService = { - currentRoute: vi.fn(), -}; - -describe('ArticlePageTitleMetaResolver', () => { - let service: ArticlePageTitleMetaResolver; - - beforeEach(() => { - const testInjector = createInjector({ - providers: [ - { - provide: ArticlePageTitleMetaResolver, - useClass: ArticlePageTitleMetaResolver, - }, - { - provide: ContextService, - useValue: mockContextService, - }, - { - provide: ContentService, - useValue: mockContentService, - }, - { - provide: RouterService, - useValue: mockRouterService, - }, - ], - }); - - service = testInjector.inject(ArticlePageTitleMetaResolver); - }); - - afterEach(() => { - destroyInjector(); - vi.resetAllMocks(); - }); - - describe('getScore', () => { - it('should return proper value if article exist', () => { - const callback = vi.fn(); - mockContextService.get.mockReturnValueOnce(of('id')); - mockContextService.get.mockReturnValue(of('article')); - mockRouterService.currentRoute.mockReturnValue(of(`/article/saf`)); - service.getScore().subscribe(callback); - expect(callback).toHaveBeenCalledWith(['id', 'article', true]); - }); - - it('should return proper value if article is not exist', () => { - const callback = vi.fn(); - mockContextService.get.mockReturnValue(of(undefined)); - mockRouterService.currentRoute.mockReturnValue(of('')); - - service.getScore().subscribe(callback); - expect(callback).toHaveBeenCalledWith([undefined, undefined, false]); - }); - }); - - describe('resolve', () => { - it('should return proper object with article title', () => { - const callback = vi.fn(); - mockContextService.get.mockReturnValueOnce(of('id')); - mockContextService.get.mockReturnValue(of('type')); - mockContentService.get.mockReturnValue( - of({ - fields: { - heading: 'Name A', - }, - }) - ); - service.resolve().subscribe(callback); - expect(mockContentService.get).toHaveBeenCalledWith({ - id: 'id', - type: 'type', - entities: ['type'], - }); - expect(callback).toHaveBeenCalledWith({ - title: 'Name A', - }); - }); - }); -}); diff --git a/libs/template/labs/src/articles/resolvers/index.ts b/libs/template/labs/src/articles/resolvers/index.ts deleted file mode 100644 index 0029694fe..000000000 --- a/libs/template/labs/src/articles/resolvers/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './article-page-description-meta.resolver'; -export * from './article-page-title-meta.resolver'; diff --git a/libs/template/labs/src/feature.ts b/libs/template/labs/src/feature.ts index 5d403c269..d2ed41a20 100644 --- a/libs/template/labs/src/feature.ts +++ b/libs/template/labs/src/feature.ts @@ -1,5 +1,4 @@ import { AppFeature } from '@oryx-frontend/core'; -import { articleProviders } from './articles'; import { bazaarVoiceComponentMapping } from './bazaarvoice'; import { cloudinaryImageConverter } from './cloudinary'; import * as components from './components'; @@ -24,7 +23,6 @@ export const labsFeatures: AppFeature[] = [ providers: [ cloudinaryImageConverter, bazaarVoiceComponentMapping, - ...articleProviders, ...i18nLabsProviders, ], }, diff --git a/libs/template/labs/src/index.ts b/libs/template/labs/src/index.ts index 78d78a254..42a9f556a 100644 --- a/libs/template/labs/src/index.ts +++ b/libs/template/labs/src/index.ts @@ -1,2 +1 @@ -export * from './articles'; export * from './feature'; diff --git a/libs/template/presets/storefront/experience/experience-data.ts b/libs/template/presets/storefront/experience/experience-data.ts index 8faf4b8e4..24681933d 100644 --- a/libs/template/presets/storefront/experience/experience-data.ts +++ b/libs/template/presets/storefront/experience/experience-data.ts @@ -10,6 +10,7 @@ import { cartsPage, categoryPage, checkoutPage, + cmsPage, contactPage, createAddressPage, editAddressPage, @@ -40,6 +41,7 @@ export const StaticExperienceFeature: AppFeature = { editAddressPage, ...(featureVersion >= '1.1' ? [registrationPage] : []), ...(featureVersion >= '1.4' ? [cartsPage, cartCreatePage] : []), + ...cmsPage, ]), ], }; diff --git a/libs/template/presets/storefront/experience/footer.ts b/libs/template/presets/storefront/experience/footer.ts index bec6e59d9..5b5b039e5 100644 --- a/libs/template/presets/storefront/experience/footer.ts +++ b/libs/template/presets/storefront/experience/footer.ts @@ -32,13 +32,35 @@ const legalLinks: ExperienceComponent = { components: [ { type: 'oryx-content-text', - content: { data: { text: `©️ ${new Date().getFullYear()} Spryker` } }, + content: { + data: { text: `©️ ${new Date().getFullYear()} Spryker` }, + }, }, - link('Imprint', '/faq/imprint'), - link('Terms & conditions', '/article/terms-and-conditions'), - link('Privacy Notice', '/article/privacy'), - link('Data preference'), - link('Condition of use'), + ...(featureVersion >= '1.5' + ? [ + { + type: 'oryx-content-list', + options: { + tags: 'legal', + rules: [ + { + layout: { + type: 'flex', + divider: true, + }, + width: 'auto', + }, + ], + }, + }, + ] + : [ + link('Imprint', '/faq/imprint'), + link('Terms & conditions', '/article/terms-and-conditions'), + link('Privacy Notice', '/article/privacy'), + link('Data preference'), + link('Condition of use'), + ]), ], options: { rules: [ diff --git a/libs/template/presets/storefront/experience/pages/cms-page.ts b/libs/template/presets/storefront/experience/pages/cms-page.ts new file mode 100644 index 000000000..26111bef7 --- /dev/null +++ b/libs/template/presets/storefront/experience/pages/cms-page.ts @@ -0,0 +1,34 @@ +import { cmsTypes } from '@oryx-frontend/content'; +import { ExperienceComponent } from '@oryx-frontend/experience'; + +export const cmsPage: ExperienceComponent[] = cmsTypes.map((type) => ({ + type: 'Page', + id: type, + meta: { + title: type, + route: `/${type}/:id`, + routeType: type, + }, + components: [ + { ref: 'header' }, + { + type: 'oryx-composition', + options: { + rules: [{ layout: { type: 'split' }, padding: '30px 0' }], + }, + components: [ + { + type: 'oryx-site-breadcrumb', + options: { rules: [{ colSpan: 2 }] }, + }, + { + type: 'oryx-data-text', + options: { + field: 'content', + }, + }, + ], + }, + { ref: 'footer' }, + ], +})); diff --git a/libs/template/presets/storefront/experience/pages/home-page.ts b/libs/template/presets/storefront/experience/pages/home-page.ts index a28a756d5..79ad3442a 100644 --- a/libs/template/presets/storefront/experience/pages/home-page.ts +++ b/libs/template/presets/storefront/experience/pages/home-page.ts @@ -28,6 +28,12 @@ export const homePage: ExperienceComponent = { type: 'oryx-composition', id: 'home-hero', options: { + context: { + content: { + entities: ['article'], + id: 'home-hero', + }, + }, rules: [ { height: '550px', @@ -45,17 +51,25 @@ export const homePage: ExperienceComponent = { }, components: [ { - type: 'oryx-content-image', - name: 'hero', - content: { - data: { - link: `/category/12`, - alt: 'hero image', - image: - 'https://images.unsplash.com/photo-1670272505340-d906d8d77d03?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2370&q=80', - }, - }, + ...(featureVersion >= '1.5' + ? { + type: 'oryx-data-image', + } + : { + type: 'oryx-content-image', + name: 'hero', + content: { + data: { + link: `/category/12`, + alt: 'hero image', + image: + 'https://images.unsplash.com/photo-1670272505340-d906d8d77d03?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2370&q=80', + }, + }, + }), options: { + field: 'picture', + entity: 'article', ...(featureVersion >= '1.4' ? {} : { position: 'center 20%' }), rules: [ { @@ -70,18 +84,26 @@ export const homePage: ExperienceComponent = { }, }, { - type: 'oryx-content-text', - content: { - data: { - text: ` - CANON EOS R7 System camera -

Discover everything

-
EOS R7 wows with its ability to track fast-moving subjects with its Deep-learning Dual Pixel CMOS AF II focus system.
- Shop now - `, - }, - }, + ...(featureVersion >= '1.5' + ? { + type: 'oryx-data-text', + } + : { + type: 'oryx-content-text', + content: { + data: { + text: ` + CANON EOS R7 System camera +

Discover everything

+
EOS R7 wows with its ability to track fast-moving subjects with its Deep-learning Dual Pixel CMOS AF II focus system.
+ Shop now + `, + }, + }, + }), options: { + field: 'content', + entity: 'article', rules: [ { padding: '40px', diff --git a/libs/template/presets/storefront/experience/pages/index.ts b/libs/template/presets/storefront/experience/pages/index.ts index 6ca95dcf3..6f0bb01f7 100644 --- a/libs/template/presets/storefront/experience/pages/index.ts +++ b/libs/template/presets/storefront/experience/pages/index.ts @@ -1,6 +1,7 @@ export * from './cart-page'; export * from './category-page'; export * from './checkout-page'; +export * from './cms-page'; export * from './contact-page'; export * from './home-page'; export * from './login-page';