@newskit-render/core 1.66.0 → 1.68.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 (51) hide show
  1. package/CHANGELOG.md +133 -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/jest.config.js +1 -2
  32. package/package.json +11 -9
  33. package/pages/[section]/[articleId]/[articleSlug].tsx +17 -10
  34. package/pages/[section]/[articleId]/relatedArticles.tsx +49 -40
  35. package/pages/_app.tsx +42 -257
  36. package/pages/account/cancellation/index.tsx +1 -1
  37. package/pages/account/edit/[field].tsx +1 -1
  38. package/pages/account/index.tsx +1 -1
  39. package/pages/account/newsletters-and-alerts/index.tsx +1 -1
  40. package/pages/account/payment/index.tsx +1 -1
  41. package/pages/account/subscription-and-billing/index.tsx +1 -1
  42. package/pages/api/auth/[...nextauth].ts +5 -1
  43. package/pages/api/recommendations/[...slug].ts +21 -0
  44. package/pages/checkout/account-creation/index.tsx +1 -1
  45. package/pages/checkout/payment-details/index.tsx +1 -1
  46. package/pages/help-hub/[id]/index.tsx +22 -9
  47. package/pages/help-hub/index.tsx +22 -9
  48. package/pages/help-hub/results.tsx +24 -0
  49. package/theme/strings/demo.ts +1 -0
  50. package/theme/strings/index.ts +1 -0
  51. package/components/header/index.test.tsx +0 -73
@@ -1,6 +1,8 @@
1
1
  import React, { useState } from 'react'
2
2
  import { UncompiledTheme } from 'newskit'
3
3
  import { sharedTheme } from '@newskit-render/shared-components'
4
+ import { useMultiTenancy } from '../multi-tenancy'
5
+ import { themesMap } from '../../config'
4
6
 
5
7
  type AppContextType = {
6
8
  theme: UncompiledTheme
@@ -12,7 +14,9 @@ const AppContext = React.createContext({
12
14
  } as AppContextType)
13
15
 
14
16
  const AppContextProvider = ({ children }: { children: JSX.Element }) => {
15
- const [theme, setTheme] = useState(sharedTheme)
17
+ const { tenant } = useMultiTenancy()
18
+ const tenantTheme = themesMap[tenant]
19
+ const [theme, setTheme] = useState(tenantTheme)
16
20
 
17
21
  return (
18
22
  <AppContext.Provider value={{ theme, setTheme }}>
@@ -0,0 +1,2 @@
1
+ export * from './app-context'
2
+ export * from './multi-tenancy'
@@ -0,0 +1,47 @@
1
+ import React from 'react'
2
+ import { render } from 'react-dom'
3
+ import { timesTheme } from '@newskit-render/shared-components'
4
+ import { Publisher } from '@newskit-render/api'
5
+ import { AppContext, AppContextProvider } from '../app-context'
6
+ import MultiTenancyProvider, { useMultiTenancy } from '.'
7
+
8
+ const container = document.createElement('div')
9
+ document.body.appendChild(container)
10
+
11
+ const TestComponent = ({ mockFunction }) => {
12
+ const accountData = useMultiTenancy()
13
+ mockFunction(accountData)
14
+ return null
15
+ }
16
+
17
+ describe('Multi-Tenancy context', () => {
18
+ it('should select the correct theme based on the tenant', () => {
19
+ render(
20
+ <MultiTenancyProvider tenant={Publisher.TIMES}>
21
+ <AppContextProvider>
22
+ <AppContext.Consumer>
23
+ {({ theme }) => <div>{JSON.stringify(theme)}</div>}
24
+ </AppContext.Consumer>
25
+ </AppContextProvider>
26
+ </MultiTenancyProvider>,
27
+ container
28
+ )
29
+
30
+ expect(container.textContent).toBe(JSON.stringify(timesTheme))
31
+ })
32
+
33
+ it('should receive proper context', () => {
34
+ const mockFunction = jest.fn()
35
+ render(
36
+ <MultiTenancyProvider tenant={Publisher.DEMO}>
37
+ <TestComponent mockFunction={mockFunction} />
38
+ </MultiTenancyProvider>,
39
+ container
40
+ )
41
+
42
+ expect(mockFunction).toHaveBeenCalledWith({
43
+ tenant: Publisher.DEMO,
44
+ getTenantString: expect.any(Function),
45
+ })
46
+ })
47
+ })
@@ -0,0 +1,31 @@
1
+ import React, { createContext, useContext } from 'react'
2
+ import get from 'lodash.get'
3
+ import { Publisher } from '@newskit-render/api'
4
+ import { translationsMap } from '../../config'
5
+
6
+ export interface MultiTenancyContextProps {
7
+ tenant?: Publisher
8
+ getTenantString?: (key: string, defaultValue?: string) => string
9
+ }
10
+
11
+ const MultiTenancyContext = createContext<MultiTenancyContextProps>({})
12
+
13
+ const MultiTenancyProvider: React.FC<MultiTenancyContextProps> = ({
14
+ tenant,
15
+ children,
16
+ }) => (
17
+ <MultiTenancyContext.Provider
18
+ value={{
19
+ tenant,
20
+ getTenantString: (key: string, defaultValue: string = ''): string => {
21
+ const data = translationsMap[tenant]
22
+ return get(data, key, defaultValue)
23
+ },
24
+ }}
25
+ >
26
+ {children}
27
+ </MultiTenancyContext.Provider>
28
+ )
29
+
30
+ export const useMultiTenancy = () => useContext(MultiTenancyContext)
31
+ export default MultiTenancyProvider
package/css/index.ts ADDED
@@ -0,0 +1,224 @@
1
+ import { css } from 'newskit'
2
+
3
+ export const GlobalStyling = css`
4
+ @font-face {
5
+ font-family: GillSansMTStd-Medium;
6
+ src: url('/fonts/GillSansMTStd-Medium.otf');
7
+ }
8
+ @font-face {
9
+ font-family: TimesModern-Bold;
10
+ src: url('/fonts/TimesDigital-Bold.ttf') format('truetype');
11
+ }
12
+ @font-face {
13
+ font-family: TimesModern-Regular;
14
+ src: url('/fonts/TimesDigital-Regular.ttf') format('truetype');
15
+ }
16
+ @font-face {
17
+ font-family: TimesDigitalW04-Regular;
18
+ src: url('/fonts/TimesDigitalW04-Regular.ttf') format('truetype');
19
+ }
20
+ @font-face {
21
+ font-family: Montserrat;
22
+ src: url('/fonts/Montserrat-Regular.ttf') format('truetype');
23
+ }
24
+ @font-face {
25
+ font-family: TheSun-Bold;
26
+ src: url('/fonts/TheSun-Bold.ttf') format('truetype');
27
+ }
28
+ @font-face {
29
+ font-family: TheSun-HeavyNarrow;
30
+ src: url('/fonts/TheSun-HeavyNarrow.ttf') format('truetype');
31
+ }
32
+ @font-face {
33
+ font-family: TheSun-Regular;
34
+ src: url('/fonts/TheSun-Regular.ttf') format('truetype');
35
+ }
36
+ @font-face {
37
+ font-family: TheSun-Medium;
38
+ src: url('/fonts/TheSun-Medium.ttf') format('truetype');
39
+ }
40
+ @font-face {
41
+ font-family: 'DM Sans';
42
+ src: url('/fonts/dmsans-regular-webfont.woff2') format('woff2'),
43
+ url('/fonts/dmsans-regular-webfont.woff') format('woff');
44
+ font-style: normal;
45
+ font-weight: 400;
46
+ font-display: swap;
47
+ }
48
+ @font-face {
49
+ font-family: 'DM Sans';
50
+ src: url('/fonts/dmsans-italic-webfont.woff2') format('woff2'),
51
+ url('/fonts/dmsans-italic-webfont.woff') format('woff');
52
+ font-style: italic;
53
+ font-weight: 400;
54
+ font-display: swap;
55
+ }
56
+ @font-face {
57
+ font-family: 'DM Sans';
58
+ src: url('/fonts/dmsans-medium-webfont.woff2') format('woff2'),
59
+ url('/fonts/dmsans-medium-webfont.woff') format('woff');
60
+ font-style: normal;
61
+ font-weight: 500;
62
+ font-display: swap;
63
+ }
64
+ @font-face {
65
+ font-family: 'DM Sans';
66
+ src: url('/fonts/dmsans-mediumitalic-webfont.woff2') format('woff2'),
67
+ url('/fonts/dmsans-mediumitalic-webfont.woff') format('woff');
68
+ font-style: italic;
69
+ font-weight: 500;
70
+ font-display: swap;
71
+ }
72
+ @font-face {
73
+ font-family: 'DM Sans';
74
+ src: url('/fonts/dmsans-bold-webfont.woff2') format('woff2'),
75
+ url('/fonts/dmsans-bold-webfont.woff') format('woff');
76
+ font-style: normal;
77
+ font-weight: 700;
78
+ font-display: swap;
79
+ }
80
+ @font-face {
81
+ font-family: 'DM Sans';
82
+ src: url('/fonts/dmsans-bolditalic-webfont.woff2') format('woff2'),
83
+ url('/fonts/dmsans-bolditalic-webfont.woff') format('woff');
84
+ font-style: italic;
85
+ font-weight: 700;
86
+ font-display: swap;
87
+ }
88
+ @font-face {
89
+ font-family: 'Poppins';
90
+ src: url('/fonts/poppins-bold-webfont.woff2') format('woff2'),
91
+ url('/fonts/poppins-bold-webfont.woff') format('woff');
92
+ font-weight: 700;
93
+ font-style: normal;
94
+ }
95
+ @font-face {
96
+ font-family: 'Poppins';
97
+ src: url('/fonts/poppins-bolditalic-webfont.woff2') format('woff2'),
98
+ url('/fonts/poppins-bolditalic-webfont.woff') format('woff');
99
+ font-weight: normal;
100
+ font-style: italic;
101
+ }
102
+ @font-face {
103
+ font-family: 'Poppins';
104
+ src: url('/fonts/poppins-extrabold-webfont.woff2') format('woff2'),
105
+ url('/fonts/poppins-extrabold-webfont.woff') format('woff');
106
+ font-weight: 800;
107
+ font-style: normal;
108
+ }
109
+ @font-face {
110
+ font-family: 'Poppins';
111
+ src: url('/fonts/poppins-extrabolditalic-webfont.woff2') format('woff2'),
112
+ url('/fonts/poppins-extrabolditalic-webfont.woff') format('woff');
113
+ font-weight: 800;
114
+ font-style: italic;
115
+ }
116
+ @font-face {
117
+ font-family: 'Poppins';
118
+ src: url('/fonts/poppins-italic-webfont.woff2') format('woff2'),
119
+ url('/fonts/poppins-italic-webfont.woff') format('woff');
120
+ font-weight: 400;
121
+ font-style: italic;
122
+ }
123
+ @font-face {
124
+ font-family: 'Poppins';
125
+ src: url('/fonts/poppins-light-webfont.woff2') format('woff2'),
126
+ url('/fonts/poppins-light-webfont.woff') format('woff');
127
+ font-weight: 300;
128
+ font-style: normal;
129
+ }
130
+ @font-face {
131
+ font-family: 'Poppins';
132
+ src: url('/fonts/poppins-lightitalic-webfont.woff2') format('woff2'),
133
+ url('/fonts/poppins-lightitalic-webfont.woff') format('woff');
134
+ font-weight: 300;
135
+ font-style: italic;
136
+ }
137
+ @font-face {
138
+ font-family: 'Poppins';
139
+ src: url('/fonts/poppins-medium-webfont.woff2') format('woff2'),
140
+ url('/fonts/poppins-medium-webfont.woff') format('woff');
141
+ font-weight: 500;
142
+ font-style: normal;
143
+ }
144
+ @font-face {
145
+ font-family: 'Poppins';
146
+ src: url('/fonts/poppins-mediumitalic-webfont.woff2') format('woff2'),
147
+ url('/fonts/poppins-mediumitalic-webfont.woff') format('woff');
148
+ font-weight: 500;
149
+ font-style: italic;
150
+ }
151
+ @font-face {
152
+ font-family: 'Poppins';
153
+ src: url('/fonts/poppins-regular-webfont.woff2') format('woff2'),
154
+ url('/fonts/poppins-regular-webfont.woff') format('woff');
155
+ font-weight: 400;
156
+ font-style: normal;
157
+ }
158
+ @font-face {
159
+ font-family: 'Poppins';
160
+ src: url('/fonts/poppins-semibold-webfont.woff2') format('woff2'),
161
+ url('/fonts/poppins-semibold-webfont.woff') format('woff');
162
+ font-weight: 600;
163
+ font-style: normal;
164
+ }
165
+ @font-face {
166
+ font-family: 'Poppins';
167
+ src: url('/fonts/poppins-semibolditalic-webfont.woff2') format('woff2'),
168
+ url('/fonts/poppins-semibolditalic-webfont.woff') format('woff');
169
+ font-weight: 600;
170
+ font-style: italic;
171
+ }
172
+ @font-face {
173
+ font-family: 'DM Mono';
174
+ src: url('/fonts/dmmono-medium.woff2') format('woff2'),
175
+ url('/fonts/dmmono-medium.woff') format('woff');
176
+ font-style: normal;
177
+ font-weight: 500;
178
+ font-display: swap;
179
+ }
180
+ @font-face {
181
+ font-family: 'Bitter';
182
+ src: url('/fonts/bitter-regular.woff2') format('woff2'),
183
+ url('/fonts/bitter-regular.woff') format('woff');
184
+ font-style: normal;
185
+ font-weight: 400;
186
+ font-display: swap;
187
+ }
188
+ @font-face {
189
+ font-family: 'Bitter';
190
+ src: url('/fonts/bitter-medium.woff2') format('woff2'),
191
+ url('/fonts/bitter-medium.woff') format('woff');
192
+ font-style: normal;
193
+ font-weight: 500;
194
+ font-display: swap;
195
+ }
196
+ @font-face {
197
+ font-family: 'Bitter';
198
+ src: url('/fonts/bitter-mediumitalic.woff2') format('woff2'),
199
+ url('/fonts/bitter-mediumitalic.woff') format('woff');
200
+ font-style: italic;
201
+ font-weight: 500;
202
+ font-display: swap;
203
+ }
204
+ @font-face {
205
+ font-family: 'Bitter';
206
+ src: url('/fonts/bitter-semibold.woff2') format('woff2'),
207
+ url('/fonts/bitter-semibold.woff') format('woff');
208
+ font-style: normal;
209
+ font-weight: 600;
210
+ font-display: swap;
211
+ }
212
+
213
+ html,
214
+ body {
215
+ padding: 0;
216
+ margin: 0;
217
+ font-family: 'Noto Sans', -apple-system, BlinkMacSystemFont, Segoe UI,
218
+ Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue,
219
+ sans-serif;
220
+ }
221
+ * {
222
+ box-sizing: border-box;
223
+ }
224
+ `
@@ -1,12 +1,16 @@
1
+ //Note: Check periodically if these consent cookie values exprire
2
+ const nuktSPConsentValue = 'JABCDEFGHI'
3
+ const consentUUIDValue = 'ff8ac797-02c4-4fb4-81f2-22f8ba2e8723_8'
4
+
1
5
  Cypress.Commands.add('mockConsentAndVisit', (url) => {
2
- cy.setCookie('nukt_sp_consent', 'JABCDEFGHI')
3
- cy.setCookie('consentUUID', '28cfcd1e-6916-4488-9d84-54f2618eaa14')
6
+ cy.setCookie('nukt_sp_consent', nuktSPConsentValue)
7
+ cy.setCookie('consentUUID', consentUUIDValue)
4
8
  cy.visit(url)
5
9
  })
6
10
 
7
11
  Cypress.Commands.add('mockConsent', () => {
8
- cy.setCookie('nukt_sp_consent', 'JABCDEFGHI')
9
- cy.setCookie('consentUUID', '28cfcd1e-6916-4488-9d84-54f2618eaa14')
12
+ cy.setCookie('nukt_sp_consent', nuktSPConsentValue)
13
+ cy.setCookie('consentUUID', consentUUIDValue)
10
14
  })
11
15
 
12
16
  const userMap = {
@@ -13,17 +13,17 @@ describe('createThemeDropdownObject', () => {
13
13
  },
14
14
  clientNavigationLogos: {
15
15
  'The-Sun': {
16
- src: 'navigationPrimary-brandMark-sun.svg',
16
+ src: '/MyAccount/navigationPrimary-brandMark-sun.svg',
17
17
  width: '115px',
18
18
  top: '0',
19
19
  },
20
20
  'Virgin-Radio': {
21
- src: 'navigationPrimary-brandMark-vr.svg',
21
+ src: '/MyAccount/navigationPrimary-brandMark-vr.svg',
22
22
  width: '150px',
23
23
  top: '0',
24
24
  },
25
25
  'The-Times': {
26
- src: 'navigationPrimary-brandMark-times.svg',
26
+ src: '/MyAccount/navigationPrimary-brandMark-times.svg',
27
27
  width: '150px',
28
28
  top: '0',
29
29
  },
@@ -0,0 +1,62 @@
1
+ import { getRecommendations, fetcher } from '../getRecommendations'
2
+ import { recomendationsMock } from '../mocks/getRecommendationsMock'
3
+
4
+ jest.mock('../getRecommendations', () => {
5
+ return {
6
+ fetcher: jest.fn().mockImplementationOnce(() => {
7
+ return recomendationsMock
8
+ }),
9
+ getRecommendations: jest.fn().mockImplementationOnce(() => {
10
+ return recomendationsMock
11
+ }),
12
+ }
13
+ })
14
+ jest.mock('@newskit-render/standalone-components', () => {
15
+ return {
16
+ recommendationsProvider: jest.fn().mockResolvedValueOnce([
17
+ {
18
+ href:
19
+ 'https://www.thesun.co.uk/wp-content/uploads/2022/03/image-656eaa885d.jpg?strip=all&w=600&h=338&crop=1',
20
+ tag: 'FOOT ON THE GAZ',
21
+ text:
22
+ 'Bale considering short deal with new club before RETIRING after World Cup',
23
+ title: 'FOOT ON THE GAZ',
24
+ },
25
+ {
26
+ href:
27
+ 'https://www.thesun.co.uk/wp-content/uploads/2022/03/image-a21f115694-1.jpg?strip=all&w=600&h=338&crop=1',
28
+ tag: 'TOUGH TIMES',
29
+ text:
30
+ 'I only made £5k last year - I sold £801k villa for cash, says Claire Sweeney',
31
+ title: 'TOUGH TIMES',
32
+ },
33
+ {
34
+ href: null,
35
+ tag: 'TOUGH TIMES',
36
+ text:
37
+ 'I only made £5k last year - I sold £801k villa for cash, says Claire Sweeney',
38
+ title: 'TOUGH TIMES',
39
+ },
40
+ ]),
41
+ }
42
+ })
43
+
44
+ describe('getRecommendations function', () => {
45
+ it('should return recomendations', async () => {
46
+ const result = await getRecommendations({
47
+ articleId: 'test-1',
48
+ publisher: 'nukapi',
49
+ userId: 'user-1',
50
+ })
51
+ expect(result).toEqual(recomendationsMock)
52
+ })
53
+ })
54
+ describe('fetcher function', () => {
55
+ it('should retun json object', async () => {
56
+ const result = await fetcher({
57
+ url: 'http://localhost:3000',
58
+ args: { articleId: 'test-2' },
59
+ })
60
+ expect(result).toEqual(recomendationsMock)
61
+ })
62
+ })
@@ -15,17 +15,17 @@ const clientHeaderImages = {
15
15
 
16
16
  const clientNavigationLogos = {
17
17
  'The-Sun': {
18
- src: 'navigationPrimary-brandMark-sun.svg',
18
+ src: '/MyAccount/navigationPrimary-brandMark-sun.svg',
19
19
  width: '115px',
20
20
  top: '0',
21
21
  },
22
22
  'Virgin-Radio': {
23
- src: 'navigationPrimary-brandMark-vr.svg',
23
+ src: '/MyAccount/navigationPrimary-brandMark-vr.svg',
24
24
  width: '150px',
25
25
  top: '0',
26
26
  },
27
27
  'The-Times': {
28
- src: 'navigationPrimary-brandMark-times.svg',
28
+ src: '/MyAccount/navigationPrimary-brandMark-times.svg',
29
29
  width: '150px',
30
30
  top: '0',
31
31
  },
@@ -0,0 +1,29 @@
1
+ import { Fetcher } from 'swr'
2
+ import {
3
+ recommendationsProvider,
4
+ Article,
5
+ } from '@newskit-render/standalone-components'
6
+
7
+ interface Recommendations {
8
+ publisher: string
9
+ articleId: string
10
+ userId?: string
11
+ }
12
+
13
+ export const fetcher: Fetcher<Article[]> = async (url): Promise<Article[]> => {
14
+ const res = await fetch(url)
15
+ return res.json()
16
+ }
17
+
18
+ export const getRecommendations = async ({
19
+ articleId,
20
+ publisher,
21
+ userId,
22
+ }: Recommendations): Promise<Article[]> => {
23
+ const recommendations = await recommendationsProvider({
24
+ articleId,
25
+ publisher,
26
+ userId,
27
+ })
28
+ return recommendations
29
+ }
@@ -1,3 +1,11 @@
1
+ declare global {
2
+ interface Window {
3
+ utag: Record<string, TealiumData>
4
+ }
5
+ }
6
+ interface TealiumData {
7
+ data: Record<string, string>
8
+ }
1
9
  export enum ContentType {
2
10
  article,
3
11
  post,
@@ -1,8 +1,4 @@
1
- import { Article } from '@newskit-render/standalone-components'
2
-
3
- test.skip('Workaround', () => 1)
4
-
5
- export const mockArticles: Article[] = [
1
+ export const recomendationsMock = [
6
2
  {
7
3
  href:
8
4
  'https://www.thesun.co.uk/wp-content/uploads/2022/03/image-656eaa885d.jpg?strip=all&w=600&h=338&crop=1',
@@ -24,6 +20,6 @@ export const mockArticles: Article[] = [
24
20
  tag: 'TOUGH TIMES',
25
21
  text:
26
22
  'I only made £5k last year - I sold £801k villa for cash, says Claire Sweeney',
27
- title: 'TOUGH TIMES',
23
+ title: 'TOUGH TIME',
28
24
  },
29
25
  ]
@@ -0,0 +1,19 @@
1
+ import { Publisher } from '@newskit-render/api'
2
+
3
+ const demoTenantRegex = /(newskit-render|localhost)/
4
+ const timesTenantRegex = /times/
5
+
6
+ const isDemoTenant = (host: string) => demoTenantRegex.test(host)
7
+ const isTimesTenant = (host: string) => timesTenantRegex.test(host)
8
+
9
+ export const getTenant = (host: string): Publisher => {
10
+ switch (true) {
11
+ case isTimesTenant(host):
12
+ return Publisher.TIMES
13
+ case isDemoTenant(host):
14
+ return Publisher.DEMO
15
+
16
+ default:
17
+ return Publisher.DEMO
18
+ }
19
+ }
package/jest.config.js CHANGED
@@ -30,8 +30,7 @@ const customJestConfig = {
30
30
  testPathIgnorePatterns: [
31
31
  '<rootDir>/cypress/',
32
32
  '<rootDir>/node_modules/',
33
- '<rootDir>/.next/',
34
- '<rootDir>/config/'
33
+ '<rootDir>/.next/'
35
34
  ],
36
35
  }
37
36
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newskit-render/core",
3
- "version": "1.66.0",
3
+ "version": "1.68.0",
4
4
  "description": "Newskit Render - Core package",
5
5
  "author": "",
6
6
  "license": "UNLICENSED",
@@ -33,24 +33,26 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@apollo/client": "3.4.16",
36
- "@newskit-render/api": "^0.32.0",
37
- "@newskit-render/auth": "^0.41.0",
38
- "@newskit-render/checkout": "^0.41.0",
36
+ "@newskit-render/api": "^0.34.0",
37
+ "@newskit-render/auth": "^0.42.0",
38
+ "@newskit-render/checkout": "^0.44.0",
39
39
  "@newskit-render/feature-flags": "^0.22.0",
40
- "@newskit-render/feed": "^0.20.0",
41
- "@newskit-render/my-account": "^0.171.0",
42
- "@newskit-render/shared-components": "^0.58.0",
43
- "@newskit-render/standalone-components": "^0.18.0",
40
+ "@newskit-render/feed": "^0.23.0",
41
+ "@newskit-render/my-account": "^0.174.0",
42
+ "@newskit-render/shared-components": "^0.61.0",
43
+ "@newskit-render/standalone-components": "^0.21.0",
44
44
  "@newskit-render/validation": "^0.48.0",
45
45
  "cross-fetch": "3.1.5",
46
46
  "graphql": "15.6.0",
47
+ "lodash.get": "4.4.2",
47
48
  "newrelic": "7.1.0",
48
49
  "newskit": "5.4.5",
49
50
  "next": "12.1.0",
50
51
  "react": "17.0.2",
51
52
  "react-dom": "17.0.2",
52
53
  "react-helmet": "6.1.0",
53
- "react-hook-form": "7.8.4"
54
+ "react-hook-form": "7.8.4",
55
+ "swr": "1.3.0"
54
56
  },
55
57
  "devDependencies": {
56
58
  "@apollo/react-testing": "4.0.0",
@@ -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
  }