create-sitecore-jss 22.2.0-canary.9 → 22.3.0-canary.2
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.
- package/dist/bin.js +17 -43
- package/dist/common/processes/next.js +4 -1
- package/dist/common/processes/transform.js +2 -12
- package/dist/common/prompts/base.js +0 -13
- package/dist/common/prompts/proxy.js +35 -0
- package/dist/common/prompts/sxp.js +16 -2
- package/dist/common/utils/helpers.js +27 -2
- package/dist/init-runner.js +1 -1
- package/dist/initializers/angular/prompts.js +4 -4
- package/dist/initializers/angular-xmcloud/index.js +21 -7
- package/dist/initializers/node-xmcloud-proxy/index.js +2 -1
- package/dist/templates/angular/.env +4 -5
- package/dist/templates/angular/.eslintrc +1 -0
- package/dist/templates/angular/gitignore +5 -0
- package/dist/templates/angular/package.json +6 -8
- package/dist/templates/angular/scripts/config/plugins/fallback.ts +0 -1
- package/dist/templates/angular/scripts/generate-component-factory/index.ts +45 -0
- package/dist/templates/angular/scripts/generate-component-factory/plugins/component-factory.ts +147 -0
- package/dist/templates/angular/scripts/generate-component-factory/plugins/components.ts +19 -0
- package/dist/templates/angular/scripts/generate-component-factory/plugins/packages.ts +29 -0
- package/dist/templates/angular/scripts/generate-component-factory/template.ts +46 -0
- package/dist/templates/angular/scripts/generate-config.ts +25 -6
- package/dist/templates/angular/scripts/generate-plugins.ts +5 -0
- package/dist/templates/angular/scripts/update-graphql-fragment-data.ts +21 -30
- package/dist/templates/angular/server.bundle.ts +3 -23
- package/dist/templates/angular/server.exports.ts +13 -0
- package/dist/templates/angular/src/app/JssState.ts +2 -9
- package/dist/templates/angular/src/app/app.module.ts +5 -4
- package/dist/templates/angular/src/app/app.server.module.ts +9 -6
- package/dist/templates/angular/src/app/components/gitignore +1 -1
- package/dist/templates/angular/src/app/i18n/jss-translation-client-loader.service.ts +15 -7
- package/dist/templates/angular/src/app/i18n/jss-translation-server-loader.service.ts +14 -2
- package/dist/templates/angular/src/app/jss-context.server-side.service.ts +4 -2
- package/dist/templates/angular/src/app/jss-context.service.ts +14 -11
- package/dist/templates/angular/src/app/jss-graphql.service.ts +7 -7
- package/dist/templates/angular/src/app/layout/jss-layout.service.ts +2 -2
- package/dist/templates/angular/src/app/lib/dictionary-service-factory.ts +4 -1
- package/dist/templates/angular/src/app/lib/graphql-client-factory/config.ts +21 -0
- package/dist/templates/angular/src/app/lib/graphql-client-factory/index.ts +16 -0
- package/dist/templates/angular/src/app/lib/layout-service-factory.ts +1 -1
- package/dist/templates/angular/src/app/routing/layout/layout.component.ts +10 -9
- package/dist/templates/angular/src/environments/gitignore +2 -1
- package/dist/templates/angular-sxp/.env +2 -0
- package/dist/templates/angular-sxp/scripts/config/plugins/disconnected.ts +4 -2
- package/dist/templates/angular-sxp/src/app/components/graph-ql-layout/graph-ql-layout.component.ts +1 -1
- package/dist/templates/angular-xmcloud/.env +15 -2
- package/dist/templates/angular-xmcloud/angular.json +0 -1
- package/dist/templates/angular-xmcloud/package.json +2 -0
- package/dist/templates/angular-xmcloud/scripts/bootstrap.ts +28 -0
- package/dist/templates/angular-xmcloud/scripts/config/plugins/xmcloud.ts +16 -0
- package/dist/templates/angular-xmcloud/scripts/generate-component-factory/plugins/packages.ts +34 -0
- package/dist/templates/angular-xmcloud/scripts/generate-component-factory/template.ts +57 -0
- package/dist/templates/angular-xmcloud/scripts/generate-metadata.ts +25 -0
- package/dist/templates/angular-xmcloud/server.exports.ts +24 -0
- package/dist/templates/angular-xmcloud/src/app/components/app-components.shared.module.ts +21 -0
- package/dist/templates/angular-xmcloud/src/app/components/column-splitter/column-splitter.component.html +5 -0
- package/dist/templates/angular-xmcloud/src/app/components/column-splitter/column-splitter.component.ts +40 -0
- package/dist/templates/angular-xmcloud/src/app/components/container/container.component.html +2 -3
- package/dist/templates/angular-xmcloud/src/app/components/image/image.component.html +36 -0
- package/dist/templates/angular-xmcloud/src/app/components/image/image.component.ts +67 -0
- package/dist/templates/angular-xmcloud/src/app/components/link-list/link-list.component.html +15 -0
- package/dist/templates/angular-xmcloud/src/app/components/link-list/link-list.component.ts +41 -0
- package/dist/templates/angular-xmcloud/src/app/components/navigation/navigation-item.component.html +23 -0
- package/dist/templates/angular-xmcloud/src/app/components/navigation/navigation-item.component.ts +65 -0
- package/dist/templates/angular-xmcloud/src/app/components/navigation/navigation.component.html +21 -0
- package/dist/templates/angular-xmcloud/src/app/components/navigation/navigation.component.ts +49 -0
- package/dist/templates/angular-xmcloud/src/app/components/page-content/page-content.component.html +5 -0
- package/dist/templates/angular-xmcloud/src/app/components/page-content/page-content.component.ts +39 -0
- package/dist/templates/angular-xmcloud/src/app/components/partial-design-dynamic-placeholder/partial-design-dynamic-placeholder.component.html +1 -0
- package/dist/templates/angular-xmcloud/src/app/components/partial-design-dynamic-placeholder/partial-design-dynamic-placeholder.component.ts +15 -0
- package/dist/templates/angular-xmcloud/src/app/components/promo/promo.component.html +21 -0
- package/dist/templates/angular-xmcloud/src/app/components/promo/promo.component.ts +13 -0
- package/dist/templates/angular-xmcloud/src/app/components/richtext/richtext.component.html +7 -12
- package/dist/templates/angular-xmcloud/src/app/components/richtext/richtext.component.ts +6 -1
- package/dist/templates/angular-xmcloud/src/app/components/row-splitter/row-splitter.component.html +11 -0
- package/dist/templates/angular-xmcloud/src/app/components/row-splitter/row-splitter.component.ts +35 -0
- package/dist/templates/angular-xmcloud/src/app/components/sxa.component.ts +3 -3
- package/dist/templates/angular-xmcloud/src/app/components/title/title.component.html +10 -0
- package/dist/templates/angular-xmcloud/src/app/components/title/title.component.ts +56 -0
- package/dist/templates/angular-xmcloud/src/app/jss-link.service.ts +55 -0
- package/dist/templates/angular-xmcloud/src/app/lib/config.ts +2 -0
- package/dist/templates/angular-xmcloud/src/app/lib/graphql-client-factory/config.ts +58 -0
- package/dist/templates/angular-xmcloud/src/app/routing/layout/layout.component.html +38 -0
- package/dist/templates/angular-xmcloud/src/app/routing/layout/layout.component.ts +104 -0
- package/dist/templates/angular-xmcloud/src/app/routing/scripts/cdp-page-view.component.ts +77 -0
- package/dist/templates/angular-xmcloud/src/app/routing/scripts/cloud-sdk-init.component.ts +48 -0
- package/dist/templates/angular-xmcloud/src/app/routing/scripts/scripts.component.html +5 -0
- package/dist/templates/angular-xmcloud/src/app/routing/scripts/scripts.module.ts +12 -0
- package/dist/templates/angular-xmcloud/src/assets/styles/basic/_header.scss +3 -1
- package/dist/templates/angular-xmcloud/src/assets/styles/main.scss +10 -0
- package/dist/templates/nextjs/package.json +5 -5
- package/dist/templates/nextjs/scripts/config/plugins/fallback.ts +0 -1
- package/dist/templates/nextjs/scripts/generate-config.ts +8 -1
- package/dist/templates/nextjs/src/lib/page-props-factory/plugins/component-props.ts +2 -1
- package/dist/templates/nextjs-styleguide/package.json +1 -1
- package/dist/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts +1 -0
- package/dist/templates/nextjs-sxa/src/assets/sass/components/common/_alignment.scss +34 -7
- package/dist/templates/nextjs-sxa/src/components/Container.tsx +6 -14
- package/dist/templates/nextjs-xmcloud/package.json +3 -2
- package/dist/templates/nextjs-xmcloud/src/Bootstrap.tsx +25 -10
- package/dist/templates/nextjs-xmcloud/src/byoc/{index.ts → index.tsx} +25 -8
- package/dist/templates/nextjs-xmcloud/src/components/CdpPageView.tsx +9 -14
- package/dist/templates/nextjs-xmcloud/src/lib/page-props-factory/plugins/component-themes.ts +2 -1
- package/dist/templates/nextjs-xmcloud/src/lib/page-props-factory/plugins/preview-mode.ts +2 -1
- package/dist/templates/node-headless-ssr-experience-edge/gitignore +19 -0
- package/dist/templates/node-headless-ssr-experience-edge/package.json +2 -2
- package/dist/templates/node-headless-ssr-proxy/gitignore +19 -0
- package/dist/templates/node-headless-ssr-proxy/package.json +3 -3
- package/dist/templates/node-headless-ssr-proxy/src/config.ts +3 -3
- package/dist/templates/node-headless-ssr-proxy/src/httpAgents.ts +2 -2
- package/dist/templates/node-headless-ssr-proxy/src/index.ts +9 -2
- package/dist/templates/node-xmcloud-proxy/.env +7 -1
- package/dist/templates/node-xmcloud-proxy/README.md +1 -1
- package/dist/templates/node-xmcloud-proxy/gitignore +33 -0
- package/dist/templates/node-xmcloud-proxy/package.json +3 -2
- package/dist/templates/node-xmcloud-proxy/src/config.ts +9 -3
- package/dist/templates/node-xmcloud-proxy/src/index.ts +54 -5
- package/dist/templates/node-xmcloud-proxy/src/types.ts +10 -42
- package/dist/templates/react/package.json +5 -5
- package/dist/templates/react/scripts/generate-config.js +10 -3
- package/dist/templates/react-native/package.json +4 -4
- package/dist/templates/vue/package.json +4 -4
- package/dist/templates/vue/scripts/generate-config.js +5 -0
- package/package.json +2 -2
- package/dist/templates/angular/scripts/generate-component-factory.ts +0 -166
- package/dist/templates/angular/src/app/lib/graphql-client-factory.ts +0 -28
- package/dist/templates/angular-xmcloud/src/app/lib/graphql-client-factory.ts +0 -44
- package/dist/templates/nextjs-xmcloud/src/lib/context/index.ts +0 -22
- 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,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 {}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "<%- appName %>",
|
|
3
3
|
"description": "Application utilizing Sitecore JavaScript Services and Next.js",
|
|
4
|
-
"version": "22.
|
|
4
|
+
"version": "22.3.0-canary",
|
|
5
5
|
"private": true,
|
|
6
6
|
"config": {
|
|
7
7
|
"appName": "<%- appName %>",
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
},
|
|
26
26
|
"license": "Apache-2.0",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@sitecore-jss/sitecore-jss-nextjs": "~22.
|
|
28
|
+
"@sitecore-jss/sitecore-jss-nextjs": "~22.3.0-canary",
|
|
29
29
|
"graphql": "~15.8.0",
|
|
30
30
|
"graphql-tag": "^2.12.6",
|
|
31
|
-
"next": "^14.
|
|
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",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"@graphql-codegen/typescript-operations": "^4.0.1",
|
|
44
44
|
"@graphql-codegen/typescript-resolvers": "^4.0.1",
|
|
45
45
|
"@graphql-typed-document-node/core": "^3.2.0",
|
|
46
|
-
"@sitecore-jss/sitecore-jss-cli": "~22.
|
|
47
|
-
"@sitecore-jss/sitecore-jss-dev-tools": "~22.
|
|
46
|
+
"@sitecore-jss/sitecore-jss-cli": "~22.3.0-canary",
|
|
47
|
+
"@sitecore-jss/sitecore-jss-dev-tools": "~22.3.0-canary",
|
|
48
48
|
"@types/node": "^20.14.2",
|
|
49
49
|
"@types/react": "^18.2.22",
|
|
50
50
|
"@types/react-dom": "^18.0.5",
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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();
|
|
@@ -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
|
-
|
|
9
|
+
text-align: left !important;
|
|
4
10
|
}
|
|
5
11
|
|
|
6
12
|
.position-right,
|
|
7
13
|
.position-right * {
|
|
8
|
-
|
|
14
|
+
text-align: right !important;
|
|
9
15
|
}
|
|
10
16
|
|
|
11
17
|
.position-center,
|
|
12
18
|
.position-center * {
|
|
13
|
-
|
|
19
|
+
text-align: center !important;
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
.position-left select {
|
|
17
|
-
|
|
23
|
+
direction: ltr !important;
|
|
18
24
|
}
|
|
19
25
|
|
|
20
26
|
.position-right select {
|
|
21
|
-
|
|
27
|
+
direction: rtl !important;
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
.position-center select {
|
|
25
|
-
|
|
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
|
|
29
|
-
|
|
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('${
|
|
26
|
+
backgroundImage: `url('${mediaUrl}')`,
|
|
35
27
|
};
|
|
36
28
|
}
|
|
37
29
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"dependencies": {
|
|
3
|
-
"@sitecore/components": "
|
|
4
|
-
"@sitecore-cloudsdk/
|
|
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 {
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
};
|