@newskit-render/core 1.63.2 → 1.68.1-alpha.0

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 (54) hide show
  1. package/CHANGELOG.md +168 -0
  2. package/README.md +16 -0
  3. package/__tests__/pages/[articleSlug].test.tsx +1 -55
  4. package/__tests__/pages/__snapshots__/home.test.tsx.snap +657 -626
  5. package/__tests__/pages/__snapshots__/relatedArticles.test.tsx.snap +651 -0
  6. package/__tests__/pages/relatedArticles.test.tsx +23 -11
  7. package/components/article/__tests__/__snapshots__/index.test.tsx.snap +1091 -1060
  8. package/components/footer/index.tsx +1 -1
  9. package/components/header/banner-messages.ts +45 -0
  10. package/components/header/index.tsx +31 -287
  11. package/components/header/navigation-links.ts +20 -0
  12. package/components/layout/LayoutTemplate.tsx +4 -1
  13. package/config/__tests__/index.test.ts +53 -0
  14. package/config/environment.ts +67 -0
  15. package/config/index.ts +2 -85
  16. package/config/multiTenancy.ts +12 -0
  17. package/{app-context → context/app-context}/AppContext.test.tsx +7 -3
  18. package/{app-context/AppContext.tsx → context/app-context/index.tsx} +5 -1
  19. package/context/index.tsx +2 -0
  20. package/context/multi-tenancy/MultiTenancy.test.tsx +47 -0
  21. package/context/multi-tenancy/index.tsx +31 -0
  22. package/css/index.ts +224 -0
  23. package/cypress/support/commands.js +8 -4
  24. package/helpers/__tests__/createThemeDropdownObject.test.ts +3 -3
  25. package/helpers/__tests__/getRecommendation.test.ts +62 -0
  26. package/helpers/createThemeDropdownObject.ts +3 -3
  27. package/helpers/getRecommendations.ts +29 -0
  28. package/helpers/global-types.ts +8 -0
  29. package/{__tests__/pages/mocks.ts → helpers/mocks/getRecommendationsMock.ts} +2 -6
  30. package/helpers/multiTenancy.ts +19 -0
  31. package/infrastructure/helm/values-dev.yaml +1 -1
  32. package/infrastructure/helm/values-pr.yaml +1 -1
  33. package/infrastructure/helm/values-prod.yaml +1 -1
  34. package/jest.config.js +1 -2
  35. package/package.json +13 -11
  36. package/pages/[section]/[articleId]/[articleSlug].tsx +17 -10
  37. package/pages/[section]/[articleId]/relatedArticles.tsx +49 -40
  38. package/pages/_app.tsx +43 -257
  39. package/pages/account/cancellation/index.tsx +1 -1
  40. package/pages/account/edit/[field].tsx +1 -1
  41. package/pages/account/index.tsx +1 -1
  42. package/pages/account/newsletters-and-alerts/index.tsx +1 -1
  43. package/pages/account/payment/index.tsx +1 -1
  44. package/pages/account/subscription-and-billing/index.tsx +1 -1
  45. package/pages/api/auth/[...nextauth].ts +5 -1
  46. package/pages/api/recommendations/[...slug].ts +21 -0
  47. package/pages/checkout/account-creation/index.tsx +1 -1
  48. package/pages/checkout/payment-details/index.tsx +1 -1
  49. package/pages/help-hub/[id]/index.tsx +22 -9
  50. package/pages/help-hub/index.tsx +22 -9
  51. package/pages/help-hub/results.tsx +24 -0
  52. package/theme/strings/demo.ts +1 -0
  53. package/theme/strings/index.ts +1 -0
  54. package/components/header/index.test.tsx +0 -73
@@ -1,16 +1,13 @@
1
1
  import React from 'react'
2
+ import useSWR from 'swr'
2
3
  import newrelic from 'newrelic'
3
4
  import {
4
5
  createApolloClient,
5
6
  ClientTypes,
6
7
  getAcsCookie,
7
- Publisher,
8
8
  } from '@newskit-render/api'
9
9
  import { UserData } from '@newskit-render/my-account'
10
- import {
11
- recommendationsProvider,
12
- Article,
13
- } from '@newskit-render/standalone-components'
10
+ import { Article } from '@newskit-render/standalone-components'
14
11
  import { GET_UNIVERSAL_ARTICLE } from '../../../queries'
15
12
  import ArticlePage, { UniversalArticle } from '../../../components/article'
16
13
  import { fetchUser } from '../../../helpers/getUser'
@@ -21,6 +18,7 @@ import {
21
18
  twitterUsername as configTwitterUsername,
22
19
  gscId as configGscId,
23
20
  } from '../../../config'
21
+ import { fetcher } from '../../../helpers/getRecommendations'
24
22
 
25
23
  export type ArticleSlug = {
26
24
  universalArticle: UniversalArticle
@@ -29,8 +27,9 @@ export type ArticleSlug = {
29
27
  siteHost: string
30
28
  gscId?: string
31
29
  user?: UserData
32
- recommendations: Article[]
30
+ articleId: string
33
31
  }
32
+
34
33
  const Article: React.FC<ArticleSlug> = ({
35
34
  universalArticle,
36
35
  articleURL,
@@ -38,8 +37,17 @@ const Article: React.FC<ArticleSlug> = ({
38
37
  siteHost,
39
38
  gscId,
40
39
  user,
41
- recommendations,
40
+ articleId,
42
41
  }) => {
42
+ let userId
43
+ if (typeof window !== 'undefined') {
44
+ userId = window?.utag?.data['cp.utag_main_v_id']
45
+ }
46
+
47
+ const { data: recommendations = [] } = useSWR<Article[]>(
48
+ `/api/recommendations/${articleId}/${userId}`,
49
+ fetcher
50
+ )
43
51
  const highlitedArticles = recommendations.slice(0, 4)
44
52
  const relatedArticles = recommendations.slice(4, 12)
45
53
 
@@ -71,12 +79,11 @@ export async function getServerSideProps(context) {
71
79
  `Article: /${section}/${articleId}/${articleSlug}`
72
80
  )
73
81
 
74
- const [{ data }, recommendations, user] = await Promise.all([
82
+ const [{ data }, user] = await Promise.all([
75
83
  apolloClient.query({
76
84
  query: GET_UNIVERSAL_ARTICLE,
77
85
  variables: { publisher: 'DEMO', id: articleId },
78
86
  }),
79
- await recommendationsProvider({ articleId, publisher: Publisher.SUN_UK }),
80
87
  await fetchUser(acsCookie, ACCOUNT_QUERY_URL),
81
88
  ])
82
89
 
@@ -89,8 +96,8 @@ export async function getServerSideProps(context) {
89
96
  siteHost: configSiteHost || '',
90
97
  gscId: configGscId || '',
91
98
  showAds: true,
92
- recommendations,
93
99
  user,
100
+ articleId,
94
101
  },
95
102
  }
96
103
  }
@@ -1,10 +1,8 @@
1
1
  import React from 'react'
2
2
  import newrelic from 'newrelic'
3
- import { getAcsCookie, ClientTypes, Publisher } from '@newskit-render/api'
4
- import {
5
- recommendationsProvider,
6
- Article,
7
- } from '@newskit-render/standalone-components'
3
+ import useSWR from 'swr'
4
+ import { getAcsCookie, ClientTypes } from '@newskit-render/api'
5
+ import { Article } from '@newskit-render/standalone-components'
8
6
  import { Block, Cell, TitleBar } from 'newskit'
9
7
  import { UserData } from '@newskit-render/my-account'
10
8
  import { fetchUser } from '../../../helpers/getUser'
@@ -12,45 +10,58 @@ import { ACCOUNT_QUERY_URL } from '../../../constants'
12
10
  import { addCacheHeaders } from '../../../helpers/addCacheHeaders'
13
11
  import Layout from '../../../components/layout'
14
12
  import { BasicRow } from '../../../components/section/layouts'
13
+ import { fetcher } from '../../../helpers/getRecommendations'
15
14
 
16
15
  export type RelatedArticles = {
17
16
  user?: UserData
18
- recommendations: Article[]
17
+ articleId
19
18
  }
20
19
 
21
20
  const RelatedArticlesPage: React.FC<RelatedArticles> = ({
22
21
  user,
23
- recommendations,
24
- }) => (
25
- <Layout dataTestId="SectionGrid" user={user}>
26
- <Cell xs={12} md={10} mdOffset={1} data-testid="SectionCell">
27
- <Block spaceStack="space080" />
28
- <Block spaceStack="space080">
29
- <TitleBar
30
- overrides={{
31
- spaceInset: {
32
- xs: 'spaceInsetSquish000',
33
- },
34
- heading: {
35
- typographyPreset: {
36
- xs: 'editorialHeadline050',
37
- md: 'editorialHeadline060',
38
- xl: 'editorialHeadline070',
22
+ articleId,
23
+ }) => {
24
+ let userId: string
25
+ if (typeof window !== 'undefined') {
26
+ userId = window?.utag?.data['cp.utag_main_v_id']
27
+ }
28
+
29
+ const { data: recommendationData = [] } = useSWR<Article[]>(
30
+ `/api/recommendations/${articleId}/${userId}`,
31
+ fetcher
32
+ )
33
+ const recommendations = recommendationData.slice(0, 18)
34
+ return (
35
+ <Layout dataTestId="SectionGrid" user={user}>
36
+ <Cell xs={12} md={10} mdOffset={1} data-testid="SectionCell">
37
+ <Block spaceStack="space080" />
38
+ <Block spaceStack="space080">
39
+ <TitleBar
40
+ overrides={{
41
+ spaceInset: {
42
+ xs: 'spaceInsetSquish000',
39
43
  },
40
- stylePreset: 'inkContrast',
41
- },
42
- }}
43
- >
44
- Related Articles
45
- </TitleBar>
46
- </Block>
47
- <BasicRow
48
- colums={{ xs: '1fr', md: '1fr 1fr', lg: '1fr 1fr 1fr' }}
49
- articles={recommendations}
50
- />
51
- </Cell>
52
- </Layout>
53
- )
44
+ heading: {
45
+ typographyPreset: {
46
+ xs: 'editorialHeadline050',
47
+ md: 'editorialHeadline060',
48
+ xl: 'editorialHeadline070',
49
+ },
50
+ stylePreset: 'inkContrast',
51
+ },
52
+ }}
53
+ >
54
+ Related Articles
55
+ </TitleBar>
56
+ </Block>
57
+ <BasicRow
58
+ colums={{ xs: '1fr', md: '1fr 1fr', lg: '1fr 1fr 1fr' }}
59
+ articles={recommendations}
60
+ />
61
+ </Cell>
62
+ </Layout>
63
+ )
64
+ }
54
65
 
55
66
  export async function getServerSideProps(context) {
56
67
  newrelic.setTransactionName('RelatedArticlesPage')
@@ -65,19 +76,17 @@ export async function getServerSideProps(context) {
65
76
  ? getAcsCookie(ClientTypes.main, context.req.headers.cookie)
66
77
  : ''
67
78
 
68
- const [recommendations, user] = await Promise.all([
69
- await recommendationsProvider({ articleId, publisher: Publisher.SUN_UK }),
79
+ const [user] = await Promise.all([
70
80
  await fetchUser(acsCookie, ACCOUNT_QUERY_URL),
71
81
  ])
72
82
 
73
83
  addCacheHeaders(context.res)
74
84
 
75
- const recommendationsToShow = recommendations.slice(0, 18)
76
85
  return {
77
86
  props: {
78
- recommendations: recommendationsToShow,
79
87
  showAds: true,
80
88
  user,
89
+ articleId,
81
90
  },
82
91
  }
83
92
  }
package/pages/_app.tsx CHANGED
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { AppProps } from 'next/app'
2
+ import { AppContext as AppContextType, AppProps } from 'next/app'
3
3
  import Head from 'next/head'
4
4
  import { ThemeProvider, Global, css, styled } from 'newskit'
5
5
  import { SessionProvider } from '@newskit-render/auth'
@@ -9,9 +9,14 @@ import {
9
9
  FeatureFlag,
10
10
  createFeatureFlagsInstance,
11
11
  } from '@newskit-render/feature-flags'
12
- import { AppContextProvider, AppContext } from '../app-context/AppContext'
12
+ import { Publisher } from '@newskit-render/api'
13
+ import { AppContextProvider, AppContext } from '../context/app-context'
13
14
  import { logger } from '../helpers/logger'
15
+
14
16
  import { optimizelysdkKey } from '../config'
17
+ import { getTenant } from '../helpers/multiTenancy'
18
+ import { GlobalStyling } from '../css'
19
+ import MultiTenancyProvider from '../context/multi-tenancy'
15
20
 
16
21
  if (!process.browser) {
17
22
  // eslint-disable-next-line global-require
@@ -25,229 +30,6 @@ if (optimizelysdkKey) {
25
30
  })
26
31
  }
27
32
 
28
- const GlobalStyling = css`
29
- @font-face {
30
- font-family: GillSansMTStd-Medium;
31
- src: url('/fonts/GillSansMTStd-Medium.otf');
32
- }
33
- @font-face {
34
- font-family: TimesModern-Bold;
35
- src: url('/fonts/TimesDigital-Bold.ttf') format('truetype');
36
- }
37
- @font-face {
38
- font-family: TimesModern-Regular;
39
- src: url('/fonts/TimesDigital-Regular.ttf') format('truetype');
40
- }
41
- @font-face {
42
- font-family: TimesDigitalW04-Regular;
43
- src: url('/fonts/TimesDigitalW04-Regular.ttf') format('truetype');
44
- }
45
- @font-face {
46
- font-family: Montserrat;
47
- src: url('/fonts/Montserrat-Regular.ttf') format('truetype');
48
- }
49
- @font-face {
50
- font-family: TheSun-Bold;
51
- src: url('/fonts/TheSun-Bold.ttf') format('truetype');
52
- }
53
- @font-face {
54
- font-family: TheSun-HeavyNarrow;
55
- src: url('/fonts/TheSun-HeavyNarrow.ttf') format('truetype');
56
- }
57
- @font-face {
58
- font-family: TheSun-Regular;
59
- src: url('/fonts/TheSun-Regular.ttf') format('truetype');
60
- }
61
- @font-face {
62
- font-family: TheSun-Medium;
63
- src: url('/fonts/TheSun-Medium.ttf') format('truetype');
64
- }
65
- @font-face {
66
- font-family: 'DM Sans';
67
- src: url('/fonts/dmsans-regular-webfont.woff2') format('woff2'),
68
- url('/fonts/dmsans-regular-webfont.woff') format('woff');
69
- font-style: normal;
70
- font-weight: 400;
71
- font-display: swap;
72
- }
73
- @font-face {
74
- font-family: 'DM Sans';
75
- src: url('/fonts/dmsans-italic-webfont.woff2') format('woff2'),
76
- url('/fonts/dmsans-italic-webfont.woff') format('woff');
77
- font-style: italic;
78
- font-weight: 400;
79
- font-display: swap;
80
- }
81
- @font-face {
82
- font-family: 'DM Sans';
83
- src: url('/fonts/dmsans-medium-webfont.woff2') format('woff2'),
84
- url('/fonts/dmsans-medium-webfont.woff') format('woff');
85
- font-style: normal;
86
- font-weight: 500;
87
- font-display: swap;
88
- }
89
- @font-face {
90
- font-family: 'DM Sans';
91
- src: url('/fonts/dmsans-mediumitalic-webfont.woff2') format('woff2'),
92
- url('/fonts/dmsans-mediumitalic-webfont.woff') format('woff');
93
- font-style: italic;
94
- font-weight: 500;
95
- font-display: swap;
96
- }
97
- @font-face {
98
- font-family: 'DM Sans';
99
- src: url('/fonts/dmsans-bold-webfont.woff2') format('woff2'),
100
- url('/fonts/dmsans-bold-webfont.woff') format('woff');
101
- font-style: normal;
102
- font-weight: 700;
103
- font-display: swap;
104
- }
105
- @font-face {
106
- font-family: 'DM Sans';
107
- src: url('/fonts/dmsans-bolditalic-webfont.woff2') format('woff2'),
108
- url('/fonts/dmsans-bolditalic-webfont.woff') format('woff');
109
- font-style: italic;
110
- font-weight: 700;
111
- font-display: swap;
112
- }
113
- @font-face {
114
- font-family: 'Poppins';
115
- src: url('/fonts/poppins-bold-webfont.woff2') format('woff2'),
116
- url('/fonts/poppins-bold-webfont.woff') format('woff');
117
- font-weight: 700;
118
- font-style: normal;
119
- }
120
- @font-face {
121
- font-family: 'Poppins';
122
- src: url('/fonts/poppins-bolditalic-webfont.woff2') format('woff2'),
123
- url('/fonts/poppins-bolditalic-webfont.woff') format('woff');
124
- font-weight: normal;
125
- font-style: italic;
126
- }
127
- @font-face {
128
- font-family: 'Poppins';
129
- src: url('/fonts/poppins-extrabold-webfont.woff2') format('woff2'),
130
- url('/fonts/poppins-extrabold-webfont.woff') format('woff');
131
- font-weight: 800;
132
- font-style: normal;
133
- }
134
- @font-face {
135
- font-family: 'Poppins';
136
- src: url('/fonts/poppins-extrabolditalic-webfont.woff2') format('woff2'),
137
- url('/fonts/poppins-extrabolditalic-webfont.woff') format('woff');
138
- font-weight: 800;
139
- font-style: italic;
140
- }
141
- @font-face {
142
- font-family: 'Poppins';
143
- src: url('/fonts/poppins-italic-webfont.woff2') format('woff2'),
144
- url('/fonts/poppins-italic-webfont.woff') format('woff');
145
- font-weight: 400;
146
- font-style: italic;
147
- }
148
- @font-face {
149
- font-family: 'Poppins';
150
- src: url('/fonts/poppins-light-webfont.woff2') format('woff2'),
151
- url('/fonts/poppins-light-webfont.woff') format('woff');
152
- font-weight: 300;
153
- font-style: normal;
154
- }
155
- @font-face {
156
- font-family: 'Poppins';
157
- src: url('/fonts/poppins-lightitalic-webfont.woff2') format('woff2'),
158
- url('/fonts/poppins-lightitalic-webfont.woff') format('woff');
159
- font-weight: 300;
160
- font-style: italic;
161
- }
162
- @font-face {
163
- font-family: 'Poppins';
164
- src: url('/fonts/poppins-medium-webfont.woff2') format('woff2'),
165
- url('/fonts/poppins-medium-webfont.woff') format('woff');
166
- font-weight: 500;
167
- font-style: normal;
168
- }
169
- @font-face {
170
- font-family: 'Poppins';
171
- src: url('/fonts/poppins-mediumitalic-webfont.woff2') format('woff2'),
172
- url('/fonts/poppins-mediumitalic-webfont.woff') format('woff');
173
- font-weight: 500;
174
- font-style: italic;
175
- }
176
- @font-face {
177
- font-family: 'Poppins';
178
- src: url('/fonts/poppins-regular-webfont.woff2') format('woff2'),
179
- url('/fonts/poppins-regular-webfont.woff') format('woff');
180
- font-weight: 400;
181
- font-style: normal;
182
- }
183
- @font-face {
184
- font-family: 'Poppins';
185
- src: url('/fonts/poppins-semibold-webfont.woff2') format('woff2'),
186
- url('/fonts/poppins-semibold-webfont.woff') format('woff');
187
- font-weight: 600;
188
- font-style: normal;
189
- }
190
- @font-face {
191
- font-family: 'Poppins';
192
- src: url('/fonts/poppins-semibolditalic-webfont.woff2') format('woff2'),
193
- url('/fonts/poppins-semibolditalic-webfont.woff') format('woff');
194
- font-weight: 600;
195
- font-style: italic;
196
- }
197
- @font-face {
198
- font-family: 'DM Mono';
199
- src: url('/fonts/dmmono-medium.woff2') format('woff2'),
200
- url('/fonts/dmmono-medium.woff') format('woff');
201
- font-style: normal;
202
- font-weight: 500;
203
- font-display: swap;
204
- }
205
- @font-face {
206
- font-family: 'Bitter';
207
- src: url('/fonts/bitter-regular.woff2') format('woff2'),
208
- url('/fonts/bitter-regular.woff') format('woff');
209
- font-style: normal;
210
- font-weight: 400;
211
- font-display: swap;
212
- }
213
- @font-face {
214
- font-family: 'Bitter';
215
- src: url('/fonts/bitter-medium.woff2') format('woff2'),
216
- url('/fonts/bitter-medium.woff') format('woff');
217
- font-style: normal;
218
- font-weight: 500;
219
- font-display: swap;
220
- }
221
- @font-face {
222
- font-family: 'Bitter';
223
- src: url('/fonts/bitter-mediumitalic.woff2') format('woff2'),
224
- url('/fonts/bitter-mediumitalic.woff') format('woff');
225
- font-style: italic;
226
- font-weight: 500;
227
- font-display: swap;
228
- }
229
- @font-face {
230
- font-family: 'Bitter';
231
- src: url('/fonts/bitter-semibold.woff2') format('woff2'),
232
- url('/fonts/bitter-semibold.woff') format('woff');
233
- font-style: normal;
234
- font-weight: 600;
235
- font-display: swap;
236
- }
237
-
238
- html,
239
- body {
240
- padding: 0;
241
- margin: 0;
242
- font-family: 'Noto Sans', -apple-system, BlinkMacSystemFont, Segoe UI,
243
- Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue,
244
- sans-serif;
245
- }
246
- * {
247
- box-sizing: border-box;
248
- }
249
- `
250
-
251
33
  const PageContainer = styled.div`
252
34
  position: relative;
253
35
  min-height: 100vh;
@@ -255,52 +37,56 @@ const PageContainer = styled.div`
255
37
 
256
38
  interface MyAppProps extends AppProps {
257
39
  featureFlags?: FeatureFlag
40
+ tenant: Publisher
258
41
  }
259
42
 
260
- function MyApp({ Component, pageProps, featureFlags }: MyAppProps) {
43
+ function MyApp({ Component, pageProps, featureFlags, tenant }: MyAppProps) {
261
44
  return (
262
- <AppContextProvider>
263
- <>
264
- <Head>
265
- <meta name="robots" content="max-image-preview:standard" />
266
- <meta name="robots" content="max-video-preview:0" />
267
- <meta google-site-verification="google-site-verification=9IZcsqYKeNo_Wlkwq6WBqgpqZuiwPGJw90Ug_LAENt4" />
268
- <meta
269
- name="viewport"
270
- content="initial-scale=1.0, width=device-width"
271
- key="viewport"
272
- />
273
- </Head>
274
- <FeatureFlagsContextProvider context={featureFlags}>
275
- <SessionProvider pageProps={pageProps}>
276
- <AppContext.Consumer>
277
- {({ theme }) => (
278
- <ThemeProvider theme={theme}>
279
- <Global styles={GlobalStyling} />
280
- <PageContainer>
281
- <Component {...pageProps} />
282
- </PageContainer>
283
- </ThemeProvider>
284
- )}
285
- </AppContext.Consumer>
286
- </SessionProvider>
287
- </FeatureFlagsContextProvider>
288
- </>
289
- </AppContextProvider>
45
+ <MultiTenancyProvider tenant={tenant}>
46
+ <AppContextProvider>
47
+ <>
48
+ <Head>
49
+ <meta name="robots" content="max-image-preview:standard" />
50
+ <meta name="robots" content="max-video-preview:0" />
51
+ <meta google-site-verification="google-site-verification=9IZcsqYKeNo_Wlkwq6WBqgpqZuiwPGJw90Ug_LAENt4" />
52
+ <meta
53
+ name="viewport"
54
+ content="initial-scale=1.0, width=device-width"
55
+ key="viewport"
56
+ />
57
+ </Head>
58
+ <FeatureFlagsContextProvider context={featureFlags}>
59
+ <SessionProvider pageProps={pageProps}>
60
+ <AppContext.Consumer>
61
+ {({ theme }) => (
62
+ <ThemeProvider theme={theme}>
63
+ <Global styles={GlobalStyling} />
64
+ <PageContainer>
65
+ <Component {...pageProps} />
66
+ </PageContainer>
67
+ </ThemeProvider>
68
+ )}
69
+ </AppContext.Consumer>
70
+ </SessionProvider>
71
+ </FeatureFlagsContextProvider>
72
+ </>
73
+ </AppContextProvider>
74
+ </MultiTenancyProvider>
290
75
  )
291
76
  }
292
77
 
293
- MyApp.getInitialProps = async ({ Component, ctx }) => {
78
+ MyApp.getInitialProps = async ({ Component, ctx }: AppContextType) => {
294
79
  let pageProps = {}
80
+ const tenant = getTenant(ctx.req?.headers?.host)
295
81
  if (Component.getInitialProps) {
296
82
  pageProps = await Component.getInitialProps(ctx)
297
83
  }
298
84
 
299
85
  if (optimizelysdkKey) {
300
86
  const featureFlags = await getFeatureFlags()
301
- return { featureFlags, pageProps }
87
+ return { featureFlags, pageProps, tenant }
302
88
  }
303
- return { pageProps }
89
+ return { pageProps, tenant }
304
90
  }
305
91
 
306
92
  export default MyApp
@@ -1,7 +1,7 @@
1
1
  import React, { useContext } from 'react'
2
2
  import { Cancellation, getProviderProps } from '@newskit-render/my-account'
3
3
  import newrelic from 'newrelic'
4
- import { AppContext } from '../../../app-context/AppContext'
4
+ import { AppContext } from '../../../context/app-context'
5
5
  import { createThemeDropdownObject } from '../../../helpers/createThemeDropdownObject'
6
6
  import validation from '../../../validation'
7
7
 
@@ -7,7 +7,7 @@ import {
7
7
  componentMap,
8
8
  } from '@newskit-render/my-account'
9
9
  import validation from '../../../validation'
10
- import { AppContext } from '../../../app-context/AppContext'
10
+ import { AppContext } from '../../../context/app-context'
11
11
  import { createThemeDropdownObject } from '../../../helpers/createThemeDropdownObject'
12
12
 
13
13
  const AccountEditField = (props) => {
@@ -1,7 +1,7 @@
1
1
  import newrelic from 'newrelic'
2
2
  import { PersonalDetails, getProviderProps } from '@newskit-render/my-account'
3
3
  import React, { useContext } from 'react'
4
- import { AppContext } from '../../app-context/AppContext'
4
+ import { AppContext } from '../../context/app-context'
5
5
  import { createThemeDropdownObject } from '../../helpers/createThemeDropdownObject'
6
6
 
7
7
  const AccountPersonalDetails = (props) => {
@@ -4,7 +4,7 @@ import {
4
4
  } from '@newskit-render/my-account'
5
5
  import newrelic from 'newrelic'
6
6
  import React, { useContext } from 'react'
7
- import { AppContext } from '../../../app-context/AppContext'
7
+ import { AppContext } from '../../../context/app-context'
8
8
  import { createThemeDropdownObject } from '../../../helpers/createThemeDropdownObject'
9
9
 
10
10
  const AccountNewslettersAndAlerts = (props) => {
@@ -5,7 +5,7 @@ import {
5
5
  PaymentProvider,
6
6
  } from '@newskit-render/my-account'
7
7
  import React, { useContext } from 'react'
8
- import { AppContext } from '../../../app-context/AppContext'
8
+ import { AppContext } from '../../../context/app-context'
9
9
  import { createThemeDropdownObject } from '../../../helpers/createThemeDropdownObject'
10
10
 
11
11
  const AccountCancellation = (props) => {
@@ -4,7 +4,7 @@ import {
4
4
  } from '@newskit-render/my-account'
5
5
  import newrelic from 'newrelic'
6
6
  import React, { useContext } from 'react'
7
- import { AppContext } from '../../../app-context/AppContext'
7
+ import { AppContext } from '../../../context/app-context'
8
8
  import { createThemeDropdownObject } from '../../../helpers/createThemeDropdownObject'
9
9
 
10
10
  const AccountSubscriptionAndBilling = (props) => {
@@ -3,4 +3,8 @@ import { NextApiRequest, NextApiResponse } from 'next'
3
3
  import { oktaClientId, oktaClientSecret, oktaDomain } from '../../../config'
4
4
 
5
5
  export default (req: NextApiRequest, res: NextApiResponse) =>
6
- createAuthRoute(req, res, { oktaClientId, oktaClientSecret, oktaDomain })
6
+ createAuthRoute(req, res, {
7
+ clientId: oktaClientId,
8
+ clientSecret: oktaClientSecret,
9
+ issuer: oktaDomain,
10
+ })
@@ -0,0 +1,21 @@
1
+ import { NextApiRequest, NextApiResponse } from 'next'
2
+ import { Publisher } from '@newskit-render/api'
3
+ import { getRecommendations } from '../../../helpers/getRecommendations'
4
+
5
+ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
6
+ try {
7
+ const [articleId, userId] = req.query.slug as string[]
8
+ const result = await getRecommendations({
9
+ articleId,
10
+ publisher: Publisher.SUN_UK,
11
+ userId,
12
+ })
13
+ res.setHeader('Content-Type', 'application/json')
14
+ res.end(JSON.stringify(result))
15
+ } catch (error) {
16
+ res.json(error)
17
+ res.status(405).end()
18
+ }
19
+ }
20
+
21
+ export default handler
@@ -1,6 +1,6 @@
1
1
  import { AccountCreation, getProviderProps } from '@newskit-render/checkout'
2
2
  import React, { useContext } from 'react'
3
- import { AppContext } from '../../../app-context/AppContext'
3
+ import { AppContext } from '../../../context/app-context'
4
4
  import validation from '../../../validation'
5
5
  import { createThemeDropdownObject } from '../../../helpers/createThemeDropdownObject'
6
6
 
@@ -1,6 +1,6 @@
1
1
  import { PaymentDetails, getProviderProps } from '@newskit-render/checkout'
2
2
  import React, { useContext } from 'react'
3
- import { AppContext } from '../../../app-context/AppContext'
3
+ import { AppContext } from '../../../context/app-context'
4
4
  import { createThemeDropdownObject } from '../../../helpers/createThemeDropdownObject'
5
5
 
6
6
  const PaymentDetailsPage = (props) => {