@newskit-render/core 1.77.0 → 1.79.0-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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [1.78.0](https://github.com/newscorp-ghfb/ncu-newskit-render/compare/@newskit-render/core@1.78.0-alpha.0...@newskit-render/core@1.78.0) (2022-07-22)
7
+
8
+ **Note:** Version bump only for package @newskit-render/core
9
+
10
+
11
+
12
+
13
+
14
+ # [1.77.0](https://github.com/newscorp-ghfb/ncu-newskit-render/compare/@newskit-render/core@1.77.0-alpha.0...@newskit-render/core@1.77.0) (2022-07-22)
15
+
16
+ **Note:** Version bump only for package @newskit-render/core
17
+
18
+
19
+
20
+
21
+
6
22
  ## [1.76.4](https://github.com/newscorp-ghfb/ncu-newskit-render/compare/@newskit-render/core@1.76.4-alpha.0...@newskit-render/core@1.76.4) (2022-07-22)
7
23
 
8
24
  **Note:** Version bump only for package @newskit-render/core
package/README.md CHANGED
@@ -105,3 +105,157 @@ In order to publish the contracts you need to execute:
105
105
  ```sh
106
106
  npm run pact:publish
107
107
  ```
108
+
109
+ ## Multi-tenant application
110
+
111
+ A multi-tenant application allows you to run an application from various (sub-)domains and show different content depending on the domain that is used.
112
+
113
+ This means that the titles would be able to load different brands' content and themes, while running the same application. The codebase will be the same across all brands.
114
+
115
+ ### Getting started
116
+
117
+ How to configure your application for multitenancy
118
+
119
+ 1. If you want to build a project from scratch, that will have everything from newskit-render, you need to run `create-render-app` (See [Newskit-Render Getting started](https://github.com/newscorp-ghfb/ncu-newskit-render#getting-started)).
120
+
121
+ When creating a new project a question whether you'd like your application to be multi tenant will prompt in the terminal.
122
+
123
+ 2. If you already have a Next application and you want to make it multi-tenant you need to add the following files:
124
+
125
+ In config folder: `config/multiTenancy.ts`:
126
+
127
+ ```
128
+ import { sharedTheme, timesTheme } from '@newskit-render/shared-components'
129
+ import { Publisher } from '@newskit-render/api'
130
+ import { demoStrings, timesStrings } from '../theme/strings'
131
+
132
+ export const translationsMap = {
133
+ [Publisher.DEMO]: demoStrings,
134
+ [Publisher.TIMES]: timesStrings,
135
+ }
136
+
137
+ export const themesMap = {
138
+ [Publisher.DEMO]: sharedTheme,
139
+ [Publisher.TIMES]: timesTheme,
140
+ }
141
+ ```
142
+
143
+
144
+
145
+ - `translationsMap` is used for re-mapping variables like site title, or any other string for each brand. Example:
146
+
147
+ ```
148
+ export const demoStrings = {
149
+ title: 'Demo Site'
150
+ }
151
+
152
+ export const timesStrings = {
153
+ title: 'Times Site'
154
+ }
155
+ ```
156
+
157
+
158
+
159
+ - `themesMap` is used for mapping the theme for each brand.
160
+ Brand names live in the `PUBLISHER` object
161
+
162
+
163
+ In context folder `context/multi-tenancy`
164
+ Add a multi-tenancy context that will keep the current tenant:
165
+
166
+ ```
167
+ import React, { createContext, useContext } from 'react'
168
+ import get from 'lodash.get'
169
+ import { Publisher } from '@newskit-render/api'
170
+ import { translationsMap } from '../../config'
171
+
172
+ export interface MultiTenancyContextProps {
173
+ tenant?: Publisher
174
+ getTenantString?: (key: string, defaultValue?: string) => string
175
+ }
176
+
177
+ const MultiTenancyContext = createContext<MultiTenancyContextProps>({})
178
+
179
+ const MultiTenancyProvider: React.FC<MultiTenancyContextProps> = ({
180
+ tenant,
181
+ children,
182
+ }) => (
183
+ <MultiTenancyContext.Provider
184
+ value={{
185
+ tenant,
186
+ getTenantString: (key: string, defaultValue: string = ''): string => {
187
+ const data = translationsMap[tenant]
188
+ return get(data, key, defaultValue)
189
+ },
190
+ }}
191
+ >
192
+ {children}
193
+ </MultiTenancyContext.Provider>
194
+ )
195
+
196
+ export const useMultiTenancy = () => useContext(MultiTenancyContext)
197
+ export default MultiTenancyProvider
198
+ ```
199
+
200
+
201
+ Now you need to update `_app.js`. To pass the tenant to the app, you need to wrap it in `MultitenancyProvide`:
202
+
203
+ ```
204
+ interface MyAppProps extends AppProps {
205
+ tenant: Publisher
206
+ }
207
+
208
+ function MyApp({ Component, pageProps, tenant }: MyAppProps) {
209
+ return (
210
+ <MultiTenancyProvider tenant={tenant}>
211
+ <AppContextProvider>
212
+ ………
213
+ </AppContextProvider>
214
+ </MultiTenancyProvider>
215
+ )
216
+ }
217
+
218
+ export default MyApp
219
+ ```
220
+
221
+
222
+ Then call the `getTenant()` helper function in `getInitialProps()`. This function extracts the brands' hostname ( domain name ) from the request headers and then we save the tenant in the context provider:
223
+
224
+ ```
225
+ MyApp.getInitialProps = async ({ Component, ctx }: AppContextType) => {
226
+ let pageProps = {}
227
+ const tenant = getTenant(ctx.req?.headers?.host as string)
228
+
229
+ if (Component.getInitialProps) {
230
+ pageProps = await Component.getInitialProps(ctx)
231
+ }
232
+ return { pageProps, tenant }
233
+ }
234
+ ```
235
+
236
+
237
+ ### How to set the theme for each tenant
238
+
239
+ You can use the `useMultiTenancy` hook anywhere in the code to get the current tenant
240
+
241
+ In `context/app-context.js`:
242
+
243
+ ```
244
+ const AppContext = React.createContext({
245
+ theme: sharedTheme,
246
+ } as AppContextType)
247
+
248
+ const AppContextProvider = ({ children }: { children: JSX.Element }) => {
249
+ const { tenant } = useMultiTenancy()
250
+ const tenantTheme = themesMap[tenant]
251
+ const [theme, setTheme] = useState(tenantTheme)
252
+
253
+ return (
254
+ <AppContext.Provider value={{ theme, setTheme }}>
255
+ {children}
256
+ </AppContext.Provider>
257
+ )
258
+ }
259
+
260
+ export { AppContextProvider, AppContext }
261
+ ```
@@ -0,0 +1,19 @@
1
+ export const terminalLog = (violations) => {
2
+ cy.task(
3
+ 'log',
4
+ `${violations.length} accessibility violation${
5
+ violations.length === 1 ? '' : 's'
6
+ } ${violations.length === 1 ? 'was' : 'were'} detected`
7
+ )
8
+ // pluck specific keys to keep the table readable
9
+ const violationData = violations.map(
10
+ ({ id, impact, description, nodes }) => ({
11
+ id,
12
+ impact,
13
+ description,
14
+ nodes: nodes.length,
15
+ })
16
+ )
17
+
18
+ cy.task('table', violationData)
19
+ }
@@ -1,28 +1,7 @@
1
- function terminalLog(violations) {
2
- cy.task(
3
- 'log',
4
- `${violations.length} accessibility violation${
5
- violations.length === 1 ? '' : 's'
6
- } ${violations.length === 1 ? 'was' : 'were'} detected`
7
- )
8
- // pluck specific keys to keep the table readable
9
- const violationData = violations.map(
10
- ({ id, impact, description, nodes }) => ({
11
- id,
12
- impact,
13
- description,
14
- nodes: nodes.length,
15
- })
16
- )
17
-
18
- cy.task('table', violationData)
19
- }
1
+ import { terminalLog } from '../../axe/terminal-log'
20
2
 
21
3
  const pages = [
22
- {
23
- url: '/account',
24
- name: 'Personal Details',
25
- },
4
+ { url: '/account', name: 'Personal Details' },
26
5
  { url: '/account/edit/name', name: 'Name form' },
27
6
  { url: '/account/edit/displayName', name: 'Display Name form' },
28
7
  { url: '/account/edit/email', name: 'Email form' },
@@ -43,7 +22,8 @@ const pages = [
43
22
  // {
44
23
  // url: '/account/payment',
45
24
  // name: 'Payment form',
46
- // skip: { skipFailures: true }, // error being caused by Stripe, ignore at this time
25
+ // skip: { skipFailures: true },
26
+ // error being caused by Stripe, ignore at this time
47
27
  // },
48
28
  {
49
29
  url: '/account/newsletters-and-alerts',
@@ -0,0 +1,21 @@
1
+ import { terminalLog } from '../../axe/terminal-log'
2
+
3
+ const pages = [
4
+ { url: '/help-hub', name: 'Landing Page' },
5
+ { url: '/help-hub/results?q=google', name: 'Search Page' },
6
+ { url: '/help-hub/article/sign-with-google', name: 'Article Page' },
7
+ ]
8
+
9
+ describe('Page accessibility', () => {
10
+ pages.forEach(({ url, name, skip }) => {
11
+ it(`Should pass a11y tests: ${name}`, () => {
12
+ cy.mockConsentAndVisit(url)
13
+ cy.injectAxe()
14
+ cy.checkA11y(null, null, terminalLog, skip)
15
+
16
+ cy.get('[data-testid="autocomplete-input"]').type('Google')
17
+
18
+ cy.checkA11y(null, null, terminalLog, false)
19
+ })
20
+ })
21
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newskit-render/core",
3
- "version": "1.77.0",
3
+ "version": "1.79.0-alpha.0",
4
4
  "description": "Newskit Render - Core package",
5
5
  "author": "",
6
6
  "license": "UNLICENSED",
@@ -35,12 +35,12 @@
35
35
  "@apollo/client": "3.4.16",
36
36
  "@newskit-render/api": "^0.36.0",
37
37
  "@newskit-render/auth": "^0.44.0",
38
- "@newskit-render/checkout": "^0.51.2",
38
+ "@newskit-render/checkout": "^0.51.4-alpha.0",
39
39
  "@newskit-render/feature-flags": "^0.24.0",
40
40
  "@newskit-render/feed": "^0.24.0",
41
41
  "@newskit-render/my-account": "^0.184.0",
42
42
  "@newskit-render/shared-components": "^0.68.0",
43
- "@newskit-render/standalone-components": "^0.30.0",
43
+ "@newskit-render/standalone-components": "^0.32.0-alpha.0",
44
44
  "@newskit-render/validation": "^0.50.0",
45
45
  "cross-fetch": "3.1.5",
46
46
  "graphql": "15.6.0",
@@ -11,12 +11,12 @@ import { AppContext } from '../../context'
11
11
  import { addCacheHeaders } from '../../helpers/addCacheHeaders'
12
12
 
13
13
  const ResultsPage: React.FC<{
14
- credentilas: AlgoliaCredentials
14
+ credentials: AlgoliaCredentials
15
15
  hits: Hit[]
16
16
  }> = (props) => {
17
17
  const { theme, setTheme } = useContext(AppContext)
18
18
  const themeDropdownObject = createThemeDropdownObject(setTheme)
19
- const credentials = { props }
19
+ const { credentials } = props
20
20
  return (
21
21
  <HelpHubResultsPage
22
22
  {...props}