create-sitecore-jss 22.2.0-canary.8 → 22.2.0-canary.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/dist/bin.js +17 -43
  2. package/dist/common/processes/next.js +4 -1
  3. package/dist/common/processes/transform.js +2 -12
  4. package/dist/common/prompts/base.js +0 -13
  5. package/dist/common/prompts/proxy.js +35 -0
  6. package/dist/common/prompts/sxp.js +16 -2
  7. package/dist/common/utils/helpers.js +27 -2
  8. package/dist/init-runner.js +1 -1
  9. package/dist/initializers/angular/prompts.js +4 -4
  10. package/dist/initializers/angular-xmcloud/index.js +21 -7
  11. package/dist/initializers/node-xmcloud-proxy/index.js +2 -1
  12. package/dist/templates/angular/.env +4 -5
  13. package/dist/templates/angular/.eslintrc +1 -0
  14. package/dist/templates/angular/gitignore +5 -0
  15. package/dist/templates/angular/package.json +1 -3
  16. package/dist/templates/angular/scripts/config/plugins/fallback.ts +0 -1
  17. package/dist/templates/angular/scripts/generate-component-factory/index.ts +45 -0
  18. package/dist/templates/angular/scripts/generate-component-factory/plugins/component-factory.ts +147 -0
  19. package/dist/templates/angular/scripts/generate-component-factory/plugins/components.ts +19 -0
  20. package/dist/templates/angular/scripts/generate-component-factory/plugins/packages.ts +29 -0
  21. package/dist/templates/angular/scripts/generate-component-factory/template.ts +46 -0
  22. package/dist/templates/angular/scripts/generate-config.ts +25 -6
  23. package/dist/templates/angular/scripts/generate-plugins.ts +5 -0
  24. package/dist/templates/angular/scripts/update-graphql-fragment-data.ts +21 -30
  25. package/dist/templates/angular/server.bundle.ts +3 -23
  26. package/dist/templates/angular/server.exports.ts +13 -0
  27. package/dist/templates/angular/src/app/JssState.ts +2 -9
  28. package/dist/templates/angular/src/app/app.module.ts +5 -4
  29. package/dist/templates/angular/src/app/app.server.module.ts +9 -6
  30. package/dist/templates/angular/src/app/components/gitignore +1 -1
  31. package/dist/templates/angular/src/app/i18n/jss-translation-client-loader.service.ts +15 -7
  32. package/dist/templates/angular/src/app/i18n/jss-translation-server-loader.service.ts +14 -2
  33. package/dist/templates/angular/src/app/jss-context.server-side.service.ts +4 -2
  34. package/dist/templates/angular/src/app/jss-context.service.ts +14 -11
  35. package/dist/templates/angular/src/app/jss-graphql.service.ts +7 -7
  36. package/dist/templates/angular/src/app/layout/jss-layout.service.ts +2 -2
  37. package/dist/templates/angular/src/app/lib/dictionary-service-factory.ts +4 -1
  38. package/dist/templates/angular/src/app/lib/graphql-client-factory/config.ts +21 -0
  39. package/dist/templates/angular/src/app/lib/graphql-client-factory/index.ts +16 -0
  40. package/dist/templates/angular/src/app/lib/layout-service-factory.ts +1 -1
  41. package/dist/templates/angular/src/app/routing/layout/layout.component.ts +10 -9
  42. package/dist/templates/angular/src/environments/gitignore +2 -1
  43. package/dist/templates/angular-sxp/.env +2 -0
  44. package/dist/templates/angular-sxp/scripts/config/plugins/disconnected.ts +4 -2
  45. package/dist/templates/angular-sxp/src/app/components/graph-ql-layout/graph-ql-layout.component.ts +1 -1
  46. package/dist/templates/angular-xmcloud/.env +15 -2
  47. package/dist/templates/angular-xmcloud/angular.json +0 -1
  48. package/dist/templates/angular-xmcloud/package.json +2 -0
  49. package/dist/templates/angular-xmcloud/scripts/bootstrap.ts +28 -0
  50. package/dist/templates/angular-xmcloud/scripts/config/plugins/xmcloud.ts +16 -0
  51. package/dist/templates/angular-xmcloud/scripts/generate-component-factory/plugins/packages.ts +34 -0
  52. package/dist/templates/angular-xmcloud/scripts/generate-component-factory/template.ts +57 -0
  53. package/dist/templates/angular-xmcloud/scripts/generate-metadata.ts +25 -0
  54. package/dist/templates/angular-xmcloud/server.exports.ts +24 -0
  55. package/dist/templates/angular-xmcloud/src/app/components/app-components.shared.module.ts +21 -0
  56. package/dist/templates/angular-xmcloud/src/app/components/column-splitter/column-splitter.component.html +5 -0
  57. package/dist/templates/angular-xmcloud/src/app/components/column-splitter/column-splitter.component.ts +40 -0
  58. package/dist/templates/angular-xmcloud/src/app/components/container/container.component.html +2 -3
  59. package/dist/templates/angular-xmcloud/src/app/components/image/image.component.html +36 -0
  60. package/dist/templates/angular-xmcloud/src/app/components/image/image.component.ts +67 -0
  61. package/dist/templates/angular-xmcloud/src/app/components/link-list/link-list.component.html +15 -0
  62. package/dist/templates/angular-xmcloud/src/app/components/link-list/link-list.component.ts +41 -0
  63. package/dist/templates/angular-xmcloud/src/app/components/navigation/navigation-item.component.html +23 -0
  64. package/dist/templates/angular-xmcloud/src/app/components/navigation/navigation-item.component.ts +65 -0
  65. package/dist/templates/angular-xmcloud/src/app/components/navigation/navigation.component.html +21 -0
  66. package/dist/templates/angular-xmcloud/src/app/components/navigation/navigation.component.ts +49 -0
  67. package/dist/templates/angular-xmcloud/src/app/components/page-content/page-content.component.html +5 -0
  68. package/dist/templates/angular-xmcloud/src/app/components/page-content/page-content.component.ts +39 -0
  69. package/dist/templates/angular-xmcloud/src/app/components/partial-design-dynamic-placeholder/partial-design-dynamic-placeholder.component.html +1 -0
  70. package/dist/templates/angular-xmcloud/src/app/components/partial-design-dynamic-placeholder/partial-design-dynamic-placeholder.component.ts +15 -0
  71. package/dist/templates/angular-xmcloud/src/app/components/promo/promo.component.html +21 -0
  72. package/dist/templates/angular-xmcloud/src/app/components/promo/promo.component.ts +13 -0
  73. package/dist/templates/angular-xmcloud/src/app/components/richtext/richtext.component.html +7 -12
  74. package/dist/templates/angular-xmcloud/src/app/components/richtext/richtext.component.ts +6 -1
  75. package/dist/templates/angular-xmcloud/src/app/components/row-splitter/row-splitter.component.html +11 -0
  76. package/dist/templates/angular-xmcloud/src/app/components/row-splitter/row-splitter.component.ts +35 -0
  77. package/dist/templates/angular-xmcloud/src/app/components/sxa.component.ts +3 -3
  78. package/dist/templates/angular-xmcloud/src/app/components/title/title.component.html +10 -0
  79. package/dist/templates/angular-xmcloud/src/app/components/title/title.component.ts +56 -0
  80. package/dist/templates/angular-xmcloud/src/app/jss-link.service.ts +55 -0
  81. package/dist/templates/angular-xmcloud/src/app/lib/config.ts +2 -0
  82. package/dist/templates/angular-xmcloud/src/app/lib/graphql-client-factory/config.ts +58 -0
  83. package/dist/templates/angular-xmcloud/src/app/routing/layout/layout.component.html +38 -0
  84. package/dist/templates/angular-xmcloud/src/app/routing/layout/layout.component.ts +104 -0
  85. package/dist/templates/angular-xmcloud/src/app/routing/scripts/cdp-page-view.component.ts +77 -0
  86. package/dist/templates/angular-xmcloud/src/app/routing/scripts/cloud-sdk-init.component.ts +48 -0
  87. package/dist/templates/angular-xmcloud/src/app/routing/scripts/scripts.component.html +5 -0
  88. package/dist/templates/angular-xmcloud/src/app/routing/scripts/scripts.module.ts +12 -0
  89. package/dist/templates/angular-xmcloud/src/assets/styles/basic/_header.scss +3 -1
  90. package/dist/templates/angular-xmcloud/src/assets/styles/main.scss +10 -0
  91. package/dist/templates/angular-xmcloud/src/assets/styles/sass/components/_component-image.scss +1 -1
  92. package/dist/templates/nextjs/package.json +1 -1
  93. package/dist/templates/nextjs/scripts/config/plugins/fallback.ts +0 -1
  94. package/dist/templates/nextjs/scripts/generate-config.ts +8 -1
  95. package/dist/templates/nextjs/src/lib/page-props-factory/plugins/component-props.ts +2 -1
  96. package/dist/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts +1 -0
  97. package/dist/templates/nextjs-sxa/src/assets/sass/components/_component-image.scss +1 -1
  98. package/dist/templates/nextjs-sxa/src/assets/sass/components/common/_alignment.scss +34 -7
  99. package/dist/templates/nextjs-sxa/src/components/Container.tsx +6 -14
  100. package/dist/templates/nextjs-xmcloud/package.json +3 -2
  101. package/dist/templates/nextjs-xmcloud/src/Bootstrap.tsx +25 -10
  102. package/dist/templates/nextjs-xmcloud/src/byoc/{index.ts → index.tsx} +25 -8
  103. package/dist/templates/nextjs-xmcloud/src/components/CdpPageView.tsx +9 -14
  104. package/dist/templates/nextjs-xmcloud/src/lib/page-props-factory/plugins/component-themes.ts +2 -1
  105. package/dist/templates/nextjs-xmcloud/src/lib/page-props-factory/plugins/preview-mode.ts +2 -1
  106. package/dist/templates/node-headless-ssr-experience-edge/gitignore +19 -0
  107. package/dist/templates/node-headless-ssr-proxy/gitignore +19 -0
  108. package/dist/templates/node-headless-ssr-proxy/src/config.ts +3 -3
  109. package/dist/templates/node-headless-ssr-proxy/src/httpAgents.ts +2 -2
  110. package/dist/templates/node-headless-ssr-proxy/src/index.ts +9 -2
  111. package/dist/templates/node-xmcloud-proxy/.env +7 -1
  112. package/dist/templates/node-xmcloud-proxy/README.md +1 -1
  113. package/dist/templates/node-xmcloud-proxy/gitignore +33 -0
  114. package/dist/templates/node-xmcloud-proxy/package.json +3 -2
  115. package/dist/templates/node-xmcloud-proxy/src/config.ts +9 -3
  116. package/dist/templates/node-xmcloud-proxy/src/index.ts +54 -5
  117. package/dist/templates/node-xmcloud-proxy/src/types.ts +10 -42
  118. package/dist/templates/react/scripts/generate-config.js +10 -3
  119. package/dist/templates/vue/scripts/generate-config.js +5 -0
  120. package/package.json +2 -2
  121. package/dist/templates/angular/scripts/generate-component-factory.ts +0 -166
  122. package/dist/templates/angular/src/app/lib/graphql-client-factory.ts +0 -28
  123. package/dist/templates/angular-xmcloud/src/app/lib/graphql-client-factory.ts +0 -44
  124. package/dist/templates/nextjs-xmcloud/src/lib/context/index.ts +0 -22
  125. package/dist/templates/nextjs-xmcloud/src/lib/context/sdk/events.ts +0 -26
@@ -0,0 +1,58 @@
1
+ import {
2
+ GraphQLRequestClientFactoryConfig,
3
+ getEdgeProxyContentUrl,
4
+ } from '@sitecore-jss/sitecore-jss-angular/cjs';
5
+ import { environment as env } from '../../../environments/environment';
6
+
7
+ /**
8
+ * Gets the configuration for the GraphQLRequestClientFactory
9
+ * @returns GraphQLRequestClientFactoryConfig
10
+ */
11
+ export const getGraphQLClientFactoryConfig = () => {
12
+ let clientConfig: GraphQLRequestClientFactoryConfig;
13
+
14
+ // Server side requests should go directly to the Sitecore, browser requests should go through the proxy.
15
+ const isServer = typeof window === 'undefined';
16
+ // If we are in a production environment we are going to use Node XM Cloud proxy
17
+ const isProduction = env.production === 'true';
18
+
19
+ if (isProduction) {
20
+ if (!env.proxyHost) {
21
+ throw new Error('Please configure your proxyHost.');
22
+ }
23
+
24
+ if (env.sitecoreEdgeContextId) {
25
+ clientConfig = {
26
+ endpoint: isServer
27
+ ? getEdgeProxyContentUrl(env.sitecoreEdgeContextId, env.sitecoreEdgeUrl)
28
+ : getEdgeProxyContentUrl(env.sitecoreEdgeContextId, env.proxyHost),
29
+ };
30
+ } else if (env.graphQLEndpoint && env.sitecoreApiKey) {
31
+ const graphQLEndpointPath = new URL(env.graphQLEndpoint).pathname;
32
+
33
+ clientConfig = {
34
+ endpoint: isServer ? env.graphQLEndpoint : `${env.proxyHost}${graphQLEndpointPath}`,
35
+ apiKey: env.sitecoreApiKey,
36
+ };
37
+ }
38
+ } else {
39
+ if (env.sitecoreEdgeContextId) {
40
+ clientConfig = {
41
+ endpoint: getEdgeProxyContentUrl(env.sitecoreEdgeContextId, env.sitecoreEdgeUrl),
42
+ };
43
+ } else if (env.graphQLEndpoint && env.sitecoreApiKey) {
44
+ clientConfig = {
45
+ endpoint: env.graphQLEndpoint,
46
+ apiKey: env.sitecoreApiKey,
47
+ };
48
+ }
49
+ }
50
+
51
+ if (!clientConfig?.endpoint) {
52
+ throw new Error(
53
+ 'Please configure either your sitecoreEdgeContextId, or your graphQLEndpoint and sitecoreApiKey.'
54
+ );
55
+ }
56
+
57
+ return clientConfig;
58
+ };
@@ -0,0 +1,38 @@
1
+ <div class="{{ mainClassPageEditing }}">
2
+ <ng-container *ngIf="state === LayoutState.Layout">
3
+ <app-scripts></app-scripts>
4
+ <header>
5
+ <div id="header">
6
+ <sc-placeholder
7
+ name="headless-header"
8
+ [rendering]="route"
9
+ (loaded)="onPlaceholderLoaded($event)"
10
+ ></sc-placeholder>
11
+ </div>
12
+ </header>
13
+ <main>
14
+ <div id="content">
15
+ <sc-placeholder
16
+ name="headless-main"
17
+ [rendering]="route"
18
+ (loaded)="onPlaceholderLoaded($event)"
19
+ ></sc-placeholder>
20
+ </div>
21
+ </main>
22
+ <footer>
23
+ <div id="footer">
24
+ <sc-placeholder
25
+ name="headless-footer"
26
+ [rendering]="route"
27
+ (loaded)="onPlaceholderLoaded($event)"
28
+ ></sc-placeholder>
29
+ </div>
30
+ </footer>
31
+ </ng-container>
32
+
33
+ <app-not-found
34
+ *ngIf="state === LayoutState.NotFound"
35
+ [errorContextData]="errorContextData"
36
+ ></app-not-found>
37
+ <app-server-error *ngIf="state === LayoutState.Error"></app-server-error>
38
+ </div>
@@ -0,0 +1,104 @@
1
+ /* eslint-disable no-shadow, no-console */
2
+ import { Component, OnInit, OnDestroy } from '@angular/core';
3
+ import {
4
+ RouteData,
5
+ Field,
6
+ LayoutServiceContextData,
7
+ getContentStylesheetLink,
8
+ } from '@sitecore-jss/sitecore-jss-angular';
9
+ import { ActivatedRoute } from '@angular/router';
10
+ import { Subscription } from 'rxjs';
11
+ import { JssState } from '../../JssState';
12
+ import { JssMetaService } from '../../jss-meta.service';
13
+ import { JssLinkService } from '../../jss-link.service';
14
+ import { environment as env } from '../../../environments/environment';
15
+
16
+ enum LayoutState {
17
+ Layout,
18
+ NotFound,
19
+ Error,
20
+ }
21
+
22
+ interface RouteFields {
23
+ [name: string]: unknown;
24
+ pageTitle?: Field<string>;
25
+ }
26
+
27
+ @Component({
28
+ selector: 'app-layout',
29
+ templateUrl: './layout.component.html',
30
+ })
31
+ export class LayoutComponent implements OnInit, OnDestroy {
32
+ route: RouteData<RouteFields>;
33
+ state: LayoutState;
34
+ LayoutState = LayoutState;
35
+ subscription: Subscription;
36
+ errorContextData: LayoutServiceContextData;
37
+ mainClassPageEditing: string;
38
+
39
+ constructor(
40
+ private activatedRoute: ActivatedRoute,
41
+ private readonly meta: JssMetaService,
42
+ private linkService: JssLinkService
43
+ ) {}
44
+
45
+ ngOnInit() {
46
+ // route data is populated by the JssRouteResolver
47
+ this.subscription = this.activatedRoute.data.subscribe((data: { jssState: JssState }) => {
48
+ if (!data.jssState) {
49
+ this.state = LayoutState.NotFound;
50
+ return;
51
+ }
52
+
53
+ if (data.jssState.sitecore && data.jssState.sitecore.route) {
54
+ this.route = data.jssState.sitecore.route;
55
+ this.setMetadata(this.route.fields);
56
+ this.state = LayoutState.Layout;
57
+ this.mainClassPageEditing = data.jssState.sitecore.context.pageEditing
58
+ ? 'editing-mode'
59
+ : 'prod-mode';
60
+
61
+ const contentStyles = getContentStylesheetLink(
62
+ { sitecore: data.jssState.sitecore },
63
+ env.sitecoreEdgeContextId,
64
+ env.sitecoreEdgeUrl
65
+ );
66
+
67
+ if (contentStyles) {
68
+ this.linkService.addHeadLinks(contentStyles);
69
+ }
70
+ }
71
+
72
+ if (data.jssState.routeFetchError) {
73
+ if (
74
+ data.jssState.routeFetchError.status >= 400 &&
75
+ data.jssState.routeFetchError.status < 500
76
+ ) {
77
+ this.state = LayoutState.NotFound;
78
+ } else {
79
+ this.state = LayoutState.Error;
80
+ }
81
+
82
+ this.errorContextData =
83
+ data.jssState.routeFetchError.data && data.jssState.routeFetchError.data.sitecore;
84
+ }
85
+ });
86
+ }
87
+
88
+ ngOnDestroy() {
89
+ // important to unsubscribe when the component is destroyed
90
+ this.subscription.unsubscribe();
91
+ }
92
+
93
+ setMetadata(routeFields: RouteFields) {
94
+ // set page title, if it exists
95
+ if (routeFields && routeFields.pageTitle) {
96
+ this.meta.setTitle(routeFields.pageTitle.value || 'Page');
97
+ }
98
+ }
99
+
100
+ onPlaceholderLoaded(_placeholderName: string) {
101
+ // you may optionally hook to the loaded event for a placeholder,
102
+ // which can be useful for analytics and other DOM-based things that need to know when a placeholder's content is available.
103
+ }
104
+ }
@@ -0,0 +1,77 @@
1
+ import { Component, OnInit, OnDestroy } from '@angular/core';
2
+ import { Subscription } from 'rxjs';
3
+ import { isServer, CdpHelper, LayoutServicePageState } from '@sitecore-jss/sitecore-jss-angular';
4
+ import { pageView, PageViewData } from '@sitecore-cloudsdk/events/browser';
5
+ import { JssContextService } from '../../jss-context.service';
6
+ import { JssState } from '../../JssState';
7
+ import { environment } from '../../../environments/environment';
8
+
9
+ /**
10
+ * This is the CDP page view component.
11
+ * It uses the Sitecore Cloud SDK to enable page view events on the client-side.
12
+ * See Sitecore Cloud SDK documentation for details.
13
+ * https://www.npmjs.com/package/@sitecore-cloudsdk/events
14
+ */
15
+ @Component({
16
+ selector: 'app-cdp-page-view',
17
+ template: '',
18
+ })
19
+ export class CdpPageViewComponent implements OnInit, OnDestroy {
20
+ private contextSubscription: Subscription;
21
+
22
+ constructor(private jssContext: JssContextService) {}
23
+
24
+ ngOnInit(): void {
25
+ if (!isServer()) {
26
+ this.contextSubscription = this.jssContext.state.subscribe((newState: JssState) => {
27
+ const {
28
+ route,
29
+ context: { pageState, language, variantId },
30
+ } = newState.sitecore;
31
+
32
+ // Do not create events in editing or preview mode or if missing route data
33
+ if (pageState !== LayoutServicePageState.Normal || !route?.itemId) {
34
+ return;
35
+ }
36
+
37
+ // Do not create events if disabled (e.g. we don't have consent)
38
+ if (this.disabled()) {
39
+ return;
40
+ }
41
+
42
+ const scope = process.env.PERSONALIZE_SCOPE;
43
+ const pageVariantId = CdpHelper.getPageVariantId(
44
+ route.itemId,
45
+ language || environment.defaultLanguage,
46
+ variantId as string,
47
+ scope
48
+ );
49
+
50
+ const pageViewData: PageViewData = {
51
+ channel: 'WEB',
52
+ currency: 'USD',
53
+ page: route.name,
54
+ pageVariantId,
55
+ language,
56
+ };
57
+
58
+ pageView(pageViewData).catch((err) => console.debug(err));
59
+ });
60
+ }
61
+ }
62
+
63
+ ngOnDestroy() {
64
+ if (this.contextSubscription) {
65
+ this.contextSubscription.unsubscribe();
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Determines if the page view events should be turned off.
71
+ * IMPORTANT: You should implement based on your cookie consent management solution of choice.
72
+ * By default it is disabled if not in production mode
73
+ */
74
+ disabled = () => {
75
+ return !environment.production;
76
+ };
77
+ }
@@ -0,0 +1,48 @@
1
+ import { Component, OnInit } from '@angular/core';
2
+ import { take } from 'rxjs/operators';
3
+ import { CloudSDK } from '@sitecore-cloudsdk/core/browser';
4
+ import '@sitecore-cloudsdk/events/browser';
5
+ import { isServer, LayoutServicePageState } from '@sitecore-jss/sitecore-jss-angular';
6
+ import { environment } from '../../../environments/environment';
7
+ import { JssContextService } from '../../jss-context.service';
8
+ import { JssState } from '../../JssState';
9
+
10
+ /**
11
+ * Component to init CloudSDK logic - to allow events throughout the site
12
+ */
13
+ @Component({
14
+ selector: 'app-cloud-sdk-init',
15
+ template: '',
16
+ })
17
+ export class CloudSdkInitComponent implements OnInit {
18
+ constructor(private jssContext: JssContextService) {}
19
+
20
+ ngOnInit(): void {
21
+ if (!isServer() && environment.production) {
22
+ // to ensure that CloudSDK initialization logic runs only once in the browser, take only the first emitted value of state
23
+ this.jssContext.state.pipe(take(1)).subscribe((newState: JssState) => {
24
+ const {
25
+ route,
26
+ context: { pageState },
27
+ } = newState.sitecore;
28
+
29
+ // Do not initialize CloudSDK in editing or preview mode or if missing route data
30
+ if (pageState !== LayoutServicePageState.Normal || !route?.itemId) {
31
+ return;
32
+ }
33
+
34
+ CloudSDK({
35
+ siteName: environment.sitecoreSiteName,
36
+ sitecoreEdgeUrl: environment.sitecoreEdgeUrl,
37
+ sitecoreEdgeContextId: environment.sitecoreEdgeContextId,
38
+ // Replace with the top level cookie domain of the website that is being integrated e.g ".example.com" and not "www.example.com"
39
+ cookieDomain: window.location.hostname.replace(/^www\./, ''),
40
+ // Cookie may be created in personalize middleware (server), but if not we should create it here
41
+ enableBrowserCookie: true,
42
+ })
43
+ .addEvents()
44
+ .initialize();
45
+ });
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,5 @@
1
+ <ng-container>
2
+ <sc-editing-scripts></sc-editing-scripts>
3
+ <app-cloud-sdk-init></app-cloud-sdk-init>
4
+ <app-cdp-page-view></app-cdp-page-view>
5
+ </ng-container>
@@ -0,0 +1,12 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { ScriptsComponent } from './scripts.component';
3
+ import { JssModule } from '@sitecore-jss/sitecore-jss-angular';
4
+ import { CloudSdkInitComponent } from './cloud-sdk-init.component';
5
+ import { CdpPageViewComponent } from './cdp-page-view.component';
6
+
7
+ @NgModule({
8
+ exports: [ScriptsComponent],
9
+ imports: [JssModule],
10
+ declarations: [ScriptsComponent, CloudSdkInitComponent, CdpPageViewComponent],
11
+ })
12
+ export class ScriptsModule {}
@@ -8,7 +8,9 @@
8
8
 
9
9
  @include respond-to(mobile-large) {
10
10
  padding-bottom: 0;
11
- flex-direction: column-reverse;
11
+ sc-placeholder {
12
+ flex-direction: column-reverse;
13
+ }
12
14
  }
13
15
  }
14
16
  }
@@ -2,3 +2,13 @@
2
2
  @import "bootstrap/scss/bootstrap";
3
3
  @import "sass/main.scss";
4
4
  @import "basic/main.scss";
5
+
6
+ sc-placeholder {
7
+ display: flex;
8
+ flex-direction: column;
9
+ flex-grow: 1;
10
+
11
+ &.row {
12
+ flex-direction: row;
13
+ }
14
+ }
@@ -9,7 +9,7 @@
9
9
  display: inline-block;
10
10
  max-width: 100%;
11
11
  }
12
- .image-caption {
12
+ span {
13
13
  display: block;
14
14
  font-style: italic;
15
15
  font-size: $font-small;
@@ -28,7 +28,7 @@
28
28
  "@sitecore-jss/sitecore-jss-nextjs": "~22.2.0-canary",
29
29
  "graphql": "~15.8.0",
30
30
  "graphql-tag": "^2.12.6",
31
- "next": "^14.1.0",
31
+ "next": "^14.2.7",
32
32
  "next-localization": "^0.12.0",
33
33
  "react": "^18.2.0",
34
34
  "react-dom": "^18.2.0",
@@ -13,7 +13,6 @@ class FallbackPlugin implements ConfigPlugin {
13
13
  async exec(config: JssConfig) {
14
14
  return Object.assign({}, config, {
15
15
  defaultLanguage: config.defaultLanguage || 'en',
16
- sitecoreApiKey: config.sitecoreApiKey || 'no-api-key-set',
17
16
  layoutServiceConfigurationName: config.layoutServiceConfigurationName || 'default',
18
17
  publicUrl: config.publicUrl || getPublicUrl(),
19
18
  });
@@ -29,6 +29,11 @@ generateConfig(defaultConfig);
29
29
  * @param {JssConfig} defaultConfig Default configuration.
30
30
  */
31
31
  function generateConfig(defaultConfig: JssConfig): void {
32
+ // Handle undefined values
33
+ Object.keys(defaultConfig).forEach(prop => {
34
+ defaultConfig[prop] = defaultConfig[prop] || '';
35
+ }, {});
36
+
32
37
  jssConfigFactory
33
38
  .create(defaultConfig)
34
39
  .then(config => {
@@ -53,7 +58,9 @@ const config = {};\n`;
53
58
 
54
59
  // Set configuration values, allowing override with environment variables
55
60
  Object.keys(config).forEach(prop => {
56
- configText += `config.${prop} = process.env.${constantCase(prop)} || '${config[prop]?.trim()}';\n`;
61
+ // Handle undefined values
62
+ const value = config[prop] || '';
63
+ configText += `config.${prop} = process.env.${constantCase(prop)} || '${value.trim()}';\n`;
57
64
  });
58
65
 
59
66
  configText += `module.exports = config;`;
@@ -7,7 +7,8 @@ import { Plugin, isServerSidePropsContext } from '..';
7
7
  class ComponentPropsPlugin implements Plugin {
8
8
  private componentPropsService: ComponentPropsService;
9
9
 
10
- order = 2;
10
+ // Make sure to run this plugin last to ensure that the updated layout data is used
11
+ order = 10;
11
12
 
12
13
  constructor() {
13
14
  this.componentPropsService = new ComponentPropsService();
@@ -29,6 +29,7 @@ class DisconnectedPlugin implements ConfigPlugin {
29
29
 
30
30
  return Object.assign({}, config, {
31
31
  sitecoreApiHost: `http://localhost:${port}`,
32
+ sitecoreApiKey: config.sitecoreApiKey || 'no-api-key-set',
32
33
  });
33
34
  }
34
35
  }
@@ -9,7 +9,7 @@
9
9
  display: inline-block;
10
10
  max-width: 100%;
11
11
  }
12
- .image-caption {
12
+ span {
13
13
  display: block;
14
14
  font-style: italic;
15
15
  font-size: $font-small;
@@ -1,26 +1,53 @@
1
+ @import '~bootstrap/scss/functions';
2
+ @import '~bootstrap/scss/variables';
3
+ @import '~bootstrap/scss/mixins';
4
+
5
+ $breakpoints: sm, md, lg, xl, xxl;
6
+
1
7
  .position-left,
2
8
  .position-left * {
3
- text-align: left !important;
9
+ text-align: left !important;
4
10
  }
5
11
 
6
12
  .position-right,
7
13
  .position-right * {
8
- text-align: right !important;
14
+ text-align: right !important;
9
15
  }
10
16
 
11
17
  .position-center,
12
18
  .position-center * {
13
- text-align: center !important;
19
+ text-align: center !important;
14
20
  }
15
21
 
16
22
  .position-left select {
17
- direction: ltr !important;
23
+ direction: ltr !important;
18
24
  }
19
25
 
20
26
  .position-right select {
21
- direction: rtl !important;
27
+ direction: rtl !important;
22
28
  }
23
29
 
24
30
  .position-center select {
25
- text-align-last: center !important;
26
- }
31
+ text-align-last: center !important;
32
+ }
33
+
34
+ @mixin auto-margins($breakpoint) {
35
+ @include media-breakpoint-up(#{$breakpoint}) {
36
+ .ms-#{$breakpoint}-auto {
37
+ margin-left: auto !important;
38
+ margin-right: 0 !important;
39
+ }
40
+ .me-#{$breakpoint}-auto {
41
+ margin-right: auto !important;
42
+ margin-left: 0 !important;
43
+ }
44
+ .mx-#{$breakpoint}-auto {
45
+ margin-right: auto !important;
46
+ margin-left: auto !important;
47
+ }
48
+ }
49
+ }
50
+
51
+ @each $breakpoint in $breakpoints {
52
+ @include auto-margins($breakpoint);
53
+ }
@@ -1,14 +1,9 @@
1
- import React from 'react';
2
1
  import {
3
2
  ComponentParams,
4
3
  ComponentRendering,
5
4
  Placeholder,
6
- useSitecoreContext,
7
5
  } from '@sitecore-jss/sitecore-jss-nextjs';
8
-
9
- const BACKGROUND_REG_EXP = new RegExp(
10
- /[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/gi
11
- );
6
+ import React from 'react';
12
7
 
13
8
  interface ComponentProps {
14
9
  rendering: ComponentRendering & { params: ComponentParams };
@@ -16,22 +11,19 @@ interface ComponentProps {
16
11
  }
17
12
 
18
13
  const DefaultContainer = (props: ComponentProps): JSX.Element => {
19
- const { sitecoreContext } = useSitecoreContext();
20
14
  const containerStyles = props.params && props.params.Styles ? props.params.Styles : '';
21
15
  const styles = `${props.params.GridParameters} ${containerStyles}`.trimEnd();
22
16
  const phKey = `container-${props.params.DynamicPlaceholderId}`;
23
17
  const id = props.params.RenderingIdentifier;
18
+ const mediaUrlPattern = new RegExp(/mediaurl=\"([^"]*)\"/, 'i');
24
19
  let backgroundImage = props.params.BackgroundImage as string;
25
20
  let backgroundStyle: { [key: string]: string } = {};
26
21
 
27
- if (backgroundImage) {
28
- const prefix = `${sitecoreContext.pageState !== 'normal' ? '/sitecore/shell' : ''}/-/media/`;
29
- backgroundImage = `${backgroundImage
30
- ?.match(BACKGROUND_REG_EXP)
31
- ?.pop()
32
- ?.replace(/-/gi, '')}`;
22
+ if (backgroundImage && backgroundImage.match(mediaUrlPattern)) {
23
+ const mediaUrl = backgroundImage.match(mediaUrlPattern)?.[1] || '';
24
+
33
25
  backgroundStyle = {
34
- backgroundImage: `url('${prefix}${backgroundImage}')`,
26
+ backgroundImage: `url('${mediaUrl}')`,
35
27
  };
36
28
  }
37
29
 
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "dependencies": {
3
- "@sitecore/components": "^1.1.10",
4
- "@sitecore-cloudsdk/events": "^0.3.1",
3
+ "@sitecore/components": "~2.0.0",
4
+ "@sitecore-cloudsdk/core": "^0.4.0",
5
+ "@sitecore-cloudsdk/events": "^0.4.0",
5
6
  "@sitecore-feaas/clientside": "^0.5.17"
6
7
  }
7
8
  }
@@ -1,21 +1,36 @@
1
+ import { useEffect } from 'react';
1
2
  import { SitecorePageProps } from 'lib/page-props';
2
- import { context } from 'src/lib/context';
3
+ import { CloudSDK } from '@sitecore-cloudsdk/core/browser';
4
+ import '@sitecore-cloudsdk/events/browser';
3
5
  import config from 'temp/config';
6
+ import { LayoutServicePageState } from '@sitecore-jss/sitecore-jss-nextjs';
4
7
 
5
8
  /**
6
9
  * The Bootstrap component is the entry point for performing any initialization logic
7
10
  * that needs to happen early in the application's lifecycle.
8
11
  */
9
12
  const Bootstrap = (props: SitecorePageProps): JSX.Element | null => {
10
- /**
11
- * Initializes the application Context and associated Software Development Kits (SDKs).
12
- * This function is the entry point for setting up the application's context and any SDKs that are required for its proper functioning.
13
- * It prepares the resources needed to interact with various services and features within the application.
14
- */
15
- context.init({
16
- siteName: props.site?.name || config.sitecoreSiteName,
17
- pageState: props.layoutData?.sitecore?.context?.pageState,
18
- });
13
+ // Browser ClientSDK init allows for page view events to be tracked
14
+ useEffect(() => {
15
+ const pageState = props.layoutData?.sitecore?.context.pageState;
16
+ if (process.env.NODE_ENV === 'development')
17
+ console.debug('Browser Events SDK is not initialized in development environment');
18
+ else if (pageState !== LayoutServicePageState.Normal)
19
+ console.debug('Browser Events SDK is not initialized in edit and preview modes');
20
+ else {
21
+ CloudSDK({
22
+ sitecoreEdgeUrl: config.sitecoreEdgeUrl,
23
+ sitecoreEdgeContextId: config.sitecoreEdgeContextId,
24
+ siteName: props.site?.name || config.sitecoreSiteName,
25
+ enableBrowserCookie: true,
26
+ // Replace with the top level cookie domain of the website that is being integrated e.g ".example.com" and not "www.example.com"
27
+ cookieDomain: window.location.hostname.replace(/^www\./, ''),
28
+ })
29
+ .addEvents()
30
+ .initialize();
31
+ }
32
+ // eslint-disable-next-line react-hooks/exhaustive-deps
33
+ }, [props.site?.name]);
19
34
 
20
35
  return null;
21
36
  };