weg-shared-layout 0.0.4 → 0.0.6
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.
|
@@ -23,7 +23,7 @@ const MyComponent = class {
|
|
|
23
23
|
return format(this.first, this.middle, this.last);
|
|
24
24
|
}
|
|
25
25
|
render() {
|
|
26
|
-
return h("div", { key: '
|
|
26
|
+
return h("div", { key: '5452c3b9c97f8879dbc26b788d1fa79409846ff0' }, "Hello, world! I'm ", this.getText());
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
29
|
MyComponent.style = myComponentCss();
|
|
@@ -154,7 +154,7 @@ const WegFooter = class {
|
|
|
154
154
|
return (h("div", { class: "standard__links" }, links.map((l) => (h("a", { class: "footer-link", href: l.href }, l.label)))));
|
|
155
155
|
}
|
|
156
156
|
render() {
|
|
157
|
-
return (h("footer", { key: '
|
|
157
|
+
return (h("footer", { key: 'b5440fe948f8a4207b20d8e380ab50f559890440', class: "footer" }, h("div", { key: '2f4757c3a52203a89b53fa358513d832f153bfa2', class: "container" }, this.renderSocialLinks(), h("div", { key: '4ee53f39a16dab3739c70dadcaadb15602f08ce9', class: "standard" }, this.renderStandardLinks(), this.renderLegalText()))));
|
|
158
158
|
}
|
|
159
159
|
static get watchers() { return {
|
|
160
160
|
"data": [{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "weg-shared-layout",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Shared layout Web Components built with Stencil",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"import": "./loader/index.js",
|
|
26
26
|
"require": "./loader/index.cjs",
|
|
27
27
|
"types": "./loader/index.d.ts"
|
|
28
|
-
}
|
|
28
|
+
},
|
|
29
|
+
"./dummy-data.json": "./src/assets/dummy-data.json"
|
|
29
30
|
},
|
|
30
31
|
"repository": {
|
|
31
32
|
"type": "git",
|
|
@@ -37,7 +38,8 @@
|
|
|
37
38
|
"homepage": "https://github.com/jobsac/weg-shared-layout#readme",
|
|
38
39
|
"files": [
|
|
39
40
|
"dist/",
|
|
40
|
-
"loader/"
|
|
41
|
+
"loader/",
|
|
42
|
+
"src/assets/dummy-data.json"
|
|
41
43
|
],
|
|
42
44
|
"scripts": {
|
|
43
45
|
"build": "stencil build",
|
package/readme.md
CHANGED
|
@@ -12,62 +12,28 @@ npm i weg-shared-layout
|
|
|
12
12
|
|
|
13
13
|
## How it works
|
|
14
14
|
|
|
15
|
-
`<weg-footer>` is a **
|
|
15
|
+
`<weg-footer>` is a **presentational** Web Component: it does **not** fetch data. Your app loads layout data however you like (REST, GraphQL, SSR, etc.), then passes the object into the component via the **`data` property** (not a string HTML attribute).
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
The payload shape matches the sample file **`dummy-data.json`**, shipped with the package:
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
- **Import:** `import layout from 'weg-shared-layout/dummy-data.json'` (enable `resolveJsonModule` in TypeScript if needed).
|
|
20
|
+
- **In this repo:** [`src/assets/dummy-data.json`](src/assets/dummy-data.json)
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
GET https://weg-payload-test.vercel.app/api/layout
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Response shape:
|
|
28
|
-
|
|
29
|
-
```json
|
|
30
|
-
{
|
|
31
|
-
"header": {},
|
|
32
|
-
"footer": {
|
|
33
|
-
"social": [
|
|
34
|
-
{ "platform": "LinkedIn", "href": "https://www.linkedin.com/" },
|
|
35
|
-
{ "platform": "Instagram", "href": "https://www.instagram.com/" },
|
|
36
|
-
{ "platform": "TikTok", "href": "https://www.tiktok.com/" },
|
|
37
|
-
{ "platform": "YouTube", "href": "https://www.youtube.com/" }
|
|
38
|
-
],
|
|
39
|
-
"standardLinks": [
|
|
40
|
-
{ "label": "About Us", "href": "/about" },
|
|
41
|
-
{ "label": "Privacy Policy", "href": "/privacy" },
|
|
42
|
-
{ "label": "Terms of Use", "href": "/terms" },
|
|
43
|
-
{ "label": "Cookie Policy", "href": "/cookies" },
|
|
44
|
-
{ "label": "Accessibility Statement", "href": "/accessibility" }
|
|
45
|
-
],
|
|
46
|
-
"credits": "Warwick Employment Group is a department of the Campus and Commercial Services Group at the University of Warwick.",
|
|
47
|
-
"copyright": "Copyright © Warwick Employment Group."
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Only `social.platform` values of `LinkedIn`, `Instagram`, `TikTok`, and `YouTube` render an icon. Items with missing/invalid fields are silently dropped.
|
|
22
|
+
Use that JSON as fixture data to see the footer working, or as a reference for your own API responses. Only `social.platform` values `LinkedIn`, `Instagram`, `TikTok`, and `YouTube` render an icon; items with missing or invalid fields are dropped.
|
|
53
23
|
|
|
54
24
|
## Using in Angular
|
|
55
25
|
|
|
56
|
-
|
|
26
|
+
Assumes Angular 17+ with **standalone** components (default for `ng new`).
|
|
57
27
|
|
|
58
|
-
### 1. Install
|
|
28
|
+
### 1. Install
|
|
59
29
|
|
|
60
30
|
```bash
|
|
61
31
|
npm i weg-shared-layout
|
|
62
|
-
# or: pnpm add weg-shared-layout
|
|
63
|
-
# or: yarn add weg-shared-layout
|
|
64
32
|
```
|
|
65
33
|
|
|
66
|
-
### 2. Register
|
|
34
|
+
### 2. Register custom elements (once, before bootstrap)
|
|
67
35
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
Edit `src/main.ts`:
|
|
36
|
+
In `src/main.ts`, call `defineCustomElements()` **before** `bootstrapApplication` so the browser recognises `<weg-footer>`.
|
|
71
37
|
|
|
72
38
|
```ts
|
|
73
39
|
import { bootstrapApplication } from '@angular/platform-browser';
|
|
@@ -76,50 +42,26 @@ import { defineCustomElements } from 'weg-shared-layout/loader';
|
|
|
76
42
|
import { appConfig } from './app/app.config';
|
|
77
43
|
import { App } from './app/app';
|
|
78
44
|
|
|
79
|
-
// MUST run before bootstrapApplication so the browser recognises <weg-footer>
|
|
80
|
-
// by the time Angular's renderer touches the DOM.
|
|
81
45
|
defineCustomElements();
|
|
82
46
|
|
|
83
47
|
bootstrapApplication(App, appConfig).catch((err) => console.error(err));
|
|
84
48
|
```
|
|
85
49
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
### 3. Provide `HttpClient`
|
|
50
|
+
### 3. Allow custom elements in templates
|
|
89
51
|
|
|
90
|
-
|
|
52
|
+
Add `schemas: [CUSTOM_ELEMENTS_SCHEMA]` to every `@Component` whose template uses `<weg-footer>` (it does not cascade from the root through `router-outlet` children).
|
|
91
53
|
|
|
92
|
-
|
|
93
|
-
import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
|
|
94
|
-
import { provideHttpClient } from '@angular/common/http';
|
|
95
|
-
import { provideRouter } from '@angular/router';
|
|
96
|
-
|
|
97
|
-
import { routes } from './app.routes';
|
|
98
|
-
|
|
99
|
-
export const appConfig: ApplicationConfig = {
|
|
100
|
-
providers: [
|
|
101
|
-
provideBrowserGlobalErrorListeners(),
|
|
102
|
-
provideRouter(routes),
|
|
103
|
-
provideHttpClient(),
|
|
104
|
-
],
|
|
105
|
-
};
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### 4. Tell Angular to allow unknown elements
|
|
54
|
+
### 4. Pass data with property binding
|
|
109
55
|
|
|
110
|
-
|
|
56
|
+
Use **`[data]="..."`** so Angular sets the element’s JavaScript `data` property (Stencil `@Prop()`), not an HTML attribute.
|
|
111
57
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
In **standalone components** (default in Angular 17+), add `schemas: [CUSTOM_ELEMENTS_SCHEMA]` to the `@Component` decorator of **every component that uses `<weg-footer>` in its template**. Easiest is to add it to your root `App` component:
|
|
58
|
+
Example with the bundled sample payload:
|
|
115
59
|
|
|
116
60
|
```ts
|
|
117
61
|
// src/app/app.ts
|
|
118
|
-
import { Component, CUSTOM_ELEMENTS_SCHEMA,
|
|
119
|
-
import { HttpClient } from '@angular/common/http';
|
|
62
|
+
import { Component, CUSTOM_ELEMENTS_SCHEMA, signal } from '@angular/core';
|
|
120
63
|
import { RouterOutlet } from '@angular/router';
|
|
121
|
-
|
|
122
|
-
const LAYOUT_API = 'https://weg-payload-test.vercel.app/api/layout';
|
|
64
|
+
import layoutFixture from 'weg-shared-layout/dummy-data.json';
|
|
123
65
|
|
|
124
66
|
@Component({
|
|
125
67
|
selector: 'app-root',
|
|
@@ -128,201 +70,79 @@ const LAYOUT_API = 'https://weg-payload-test.vercel.app/api/layout';
|
|
|
128
70
|
templateUrl: './app.html',
|
|
129
71
|
styleUrl: './app.css',
|
|
130
72
|
})
|
|
131
|
-
export class App
|
|
132
|
-
protected readonly layoutData = signal
|
|
133
|
-
|
|
134
|
-
private readonly http = inject(HttpClient);
|
|
135
|
-
|
|
136
|
-
ngOnInit(): void {
|
|
137
|
-
this.http.get(LAYOUT_API).subscribe({
|
|
138
|
-
next: (data) => this.layoutData.set(data),
|
|
139
|
-
error: (err) => console.error('Failed to load layout data', err),
|
|
140
|
-
});
|
|
141
|
-
}
|
|
73
|
+
export class App {
|
|
74
|
+
protected readonly layoutData = signal(layoutFixture);
|
|
142
75
|
}
|
|
143
76
|
```
|
|
144
77
|
|
|
145
|
-
> `CUSTOM_ELEMENTS_SCHEMA` is **per-component** in standalone Angular. If you use `<weg-footer>` inside a child component's template, that child must declare `schemas: [CUSTOM_ELEMENTS_SCHEMA]` too. It does **not** cascade through `<router-outlet />`.
|
|
146
|
-
|
|
147
|
-
### 5. Pass the data into `<weg-footer>` via the `[data]` binding
|
|
148
|
-
|
|
149
|
-
In `src/app/app.html`:
|
|
150
|
-
|
|
151
78
|
```html
|
|
79
|
+
<!-- src/app/app.html -->
|
|
152
80
|
<router-outlet />
|
|
153
|
-
|
|
154
81
|
<weg-footer [data]="layoutData()"></weg-footer>
|
|
155
82
|
```
|
|
156
83
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
#### Why `[data]` and not `data-src` or `[attr.data]`
|
|
160
|
-
|
|
161
|
-
- `[data]="..."` is Angular's **property binding** — it sets the JS property `data` on the underlying DOM element. Stencil exposes `@Prop()` values as JS properties, so this passes the object straight through. **This is what you want.**
|
|
162
|
-
- `[attr.data]="..."` would set an HTML attribute, which is always a string — Angular would call `JSON.stringify(layoutData)` for you, the component would have to parse it back, and you'd lose type fidelity. Avoid unless you have a reason.
|
|
163
|
-
- Plain `data="..."` only works for a static string literal and would have the same parsing cost — fine for testing, not for real data.
|
|
164
|
-
|
|
165
|
-
### 6. Verify it works
|
|
166
|
-
|
|
167
|
-
After running `ng serve`, open the page and check:
|
|
168
|
-
|
|
169
|
-
1. The dark footer bar renders at the bottom of the page.
|
|
170
|
-
2. DevTools → Network tab shows a `200 OK` to `https://weg-payload-test.vercel.app/api/layout`.
|
|
171
|
-
3. DevTools → Elements → click `<weg-footer>` → in the Console, type `$0.data` — you should see the JSON object you fetched.
|
|
172
|
-
4. Expand `<weg-footer>` in the Elements panel — you should see a `#shadow-root (open)` containing the actual `<footer>` markup.
|
|
84
|
+
In production, replace `layoutFixture` with data from your own services; keep the same object shape as `dummy-data.json`.
|
|
173
85
|
|
|
174
86
|
### Troubleshooting
|
|
175
87
|
|
|
176
88
|
| Symptom | Cause / fix |
|
|
177
89
|
| --- | --- |
|
|
178
|
-
| `'weg-footer' is not a known element`
|
|
179
|
-
|
|
|
180
|
-
|
|
|
181
|
-
| `NullInjectorError: No provider for HttpClient` | You forgot `provideHttpClient()` in `app.config.ts`. |
|
|
182
|
-
| CORS error in the console | The API host must allow your origin. Either fix CORS on the backend, or proxy through Angular's dev proxy (`proxy.conf.json`) so the call becomes same-origin. |
|
|
183
|
-
| Footer doesn't update after data changes | Make sure you're using `[data]="layoutData()"` with a signal (or `[data]="layoutData$ | async"` with an Observable) so Angular pushes new values into the element. |
|
|
184
|
-
| Works locally, fails in SSR (`document is not defined`) | `defineCustomElements()` touches `window` / `customElements`. Wrap in `if (typeof window !== 'undefined') { ... }` or use `isPlatformBrowser(platformId)` in `main.ts`. |
|
|
185
|
-
| TypeScript: `Property 'weg-footer' does not exist on type 'HTMLElementTagNameMap'` | See the typings section below. |
|
|
90
|
+
| `'weg-footer' is not a known element` | Add `schemas: [CUSTOM_ELEMENTS_SCHEMA]` on the component whose template contains `<weg-footer>`. |
|
|
91
|
+
| Footer missing or empty box | `defineCustomElements()` not called before bootstrap, or `data` not set / wrong shape — compare with `dummy-data.json`. |
|
|
92
|
+
| SSR: `document is not defined` | Guard `defineCustomElements()` with `typeof window !== 'undefined'` or `isPlatformBrowser`. |
|
|
186
93
|
|
|
187
|
-
### TypeScript typings
|
|
188
|
-
|
|
189
|
-
If your editor / TS service complains about the unknown element or the `[data]` binding, add this to `src/global.d.ts` (creating the file if needed) and make sure it's included by `tsconfig.json`:
|
|
94
|
+
### TypeScript typings
|
|
190
95
|
|
|
191
96
|
```ts
|
|
192
97
|
/// <reference types="weg-shared-layout/dist/types/components" />
|
|
193
98
|
```
|
|
194
99
|
|
|
195
|
-
### Legacy
|
|
196
|
-
|
|
197
|
-
If your app is still using `NgModule` (pre-Angular 17 default), add `CUSTOM_ELEMENTS_SCHEMA` once at the module level instead of per component:
|
|
100
|
+
### Legacy `NgModule`
|
|
198
101
|
|
|
199
|
-
|
|
200
|
-
// src/app/app.module.ts
|
|
201
|
-
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
|
202
|
-
import { HttpClientModule } from '@angular/common/http';
|
|
203
|
-
|
|
204
|
-
@NgModule({
|
|
205
|
-
imports: [HttpClientModule /* ... */],
|
|
206
|
-
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
207
|
-
})
|
|
208
|
-
export class AppModule {}
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
`defineCustomElements()` in `main.ts` is still required either way. Inject `HttpClient` in your component the same way as the standalone example above.
|
|
102
|
+
Add `CUSTOM_ELEMENTS_SCHEMA` once on the module that declares components using `<weg-footer>`. `defineCustomElements()` in `main.ts` is still required.
|
|
212
103
|
|
|
213
104
|
## Using in React
|
|
214
105
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
```bash
|
|
218
|
-
npm i weg-shared-layout
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
Register custom elements (pick one):
|
|
106
|
+
Register the element once (for example in `main.tsx` / your app entry):
|
|
222
107
|
|
|
223
108
|
```ts
|
|
224
|
-
// Option A (recommended): loader registers all components
|
|
225
109
|
import { defineCustomElements } from 'weg-shared-layout/loader';
|
|
226
110
|
|
|
227
111
|
defineCustomElements();
|
|
228
112
|
```
|
|
229
113
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
```ts
|
|
233
|
-
// Option B: import package bundle (also registers, depending on output target configuration)
|
|
234
|
-
import 'weg-shared-layout';
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
Then fetch the data in your component and pass it in via a ref (because the `data` prop is an object, not a string attribute):
|
|
238
|
-
|
|
239
|
-
```tsx
|
|
240
|
-
import { useEffect, useRef, useState } from 'react';
|
|
241
|
-
import 'weg-shared-layout/weg-footer';
|
|
242
|
-
|
|
243
|
-
const LAYOUT_API = 'https://weg-payload-test.vercel.app/api/layout';
|
|
244
|
-
|
|
245
|
-
export function SiteFooter() {
|
|
246
|
-
const ref = useRef<HTMLElement>(null);
|
|
247
|
-
const [layout, setLayout] = useState<unknown>(null);
|
|
248
|
-
|
|
249
|
-
useEffect(() => {
|
|
250
|
-
fetch(LAYOUT_API).then((r) => r.json()).then(setLayout);
|
|
251
|
-
}, []);
|
|
252
|
-
|
|
253
|
-
useEffect(() => {
|
|
254
|
-
if (ref.current) (ref.current as any).data = layout;
|
|
255
|
-
}, [layout]);
|
|
256
|
-
|
|
257
|
-
return <weg-footer ref={ref} />;
|
|
258
|
-
}
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
> React (pre-19) sets unknown JSX attributes as HTML attributes, which would stringify your object. Assigning via a ref guarantees you set the JS property. React 19+ handles this correctly without the ref dance.
|
|
262
|
-
|
|
263
|
-
### Next.js (App Router) note
|
|
264
|
-
|
|
265
|
-
Stencil custom elements must be registered **in the browser**. In Next.js `app/` (App Router), don't import/register Stencil components from a Server Component.
|
|
266
|
-
|
|
267
|
-
Instead, register them in a Client Component, for example:
|
|
114
|
+
Import the fixture (or your own object with the same shape) and pass it on **`data`**:
|
|
268
115
|
|
|
269
116
|
```tsx
|
|
270
|
-
// app/components/SiteFooter.tsx
|
|
271
|
-
"use client";
|
|
272
|
-
|
|
273
|
-
import { useEffect, useRef, useState } from 'react';
|
|
274
117
|
import 'weg-shared-layout/weg-footer';
|
|
118
|
+
import layout from 'weg-shared-layout/dummy-data.json';
|
|
275
119
|
|
|
276
120
|
export function SiteFooter() {
|
|
277
|
-
|
|
278
|
-
const [layout, setLayout] = useState<unknown>(null);
|
|
279
|
-
|
|
280
|
-
useEffect(() => {
|
|
281
|
-
fetch('/api/layout').then((r) => r.json()).then(setLayout);
|
|
282
|
-
}, []);
|
|
283
|
-
|
|
284
|
-
useEffect(() => {
|
|
285
|
-
if (ref.current) (ref.current as any).data = layout;
|
|
286
|
-
}, [layout]);
|
|
287
|
-
|
|
288
|
-
return <weg-footer ref={ref} />;
|
|
121
|
+
return <weg-footer data={layout} />;
|
|
289
122
|
}
|
|
290
123
|
```
|
|
291
124
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
### React TypeScript typings
|
|
125
|
+
Use **React 19 or newer** so `data={...}` is applied as the custom element’s **`data` property** (object), not a string attribute. Register the elements in a **Client Component** only (`"use client"` in the Next.js App Router).
|
|
295
126
|
|
|
296
|
-
|
|
127
|
+
### React TypeScript
|
|
297
128
|
|
|
298
129
|
```ts
|
|
299
130
|
/// <reference types="weg-shared-layout/dist/types/components" />
|
|
300
131
|
```
|
|
301
132
|
|
|
302
|
-
If your app still complains about JSX intrinsic elements, you can also augment `JSX.IntrinsicElements` in that same file (varies by React/TS setup).
|
|
303
|
-
|
|
304
133
|
## Plain HTML / vanilla JS
|
|
305
134
|
|
|
306
|
-
|
|
135
|
+
With a bundler that resolves `node_modules` imports:
|
|
307
136
|
|
|
308
137
|
```html
|
|
309
138
|
<weg-footer id="footer"></weg-footer>
|
|
310
|
-
|
|
311
139
|
<script type="module">
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
</script>
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
You can also pass the JSON as a string attribute — useful for SSR or static HTML where you don't want a runtime fetch:
|
|
140
|
+
import { defineCustomElements } from 'weg-shared-layout/loader';
|
|
141
|
+
import layout from 'weg-shared-layout/dummy-data.json';
|
|
318
142
|
|
|
319
|
-
|
|
320
|
-
|
|
143
|
+
defineCustomElements();
|
|
144
|
+
document.getElementById('footer').data = layout;
|
|
145
|
+
</script>
|
|
321
146
|
```
|
|
322
147
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
Because the host app calls the API directly, **the API must respond with `Access-Control-Allow-Origin` headers** that include your app's origin. If you hit a CORS error in the browser console, either:
|
|
326
|
-
|
|
327
|
-
- Fix CORS on the API host, **or**
|
|
328
|
-
- Proxy the call through your own host. Angular: configure `proxy.conf.json` so `/api/layout` is rewritten to the production URL. Next.js: add a route handler that re-fetches and returns the JSON.
|
|
148
|
+
Otherwise, copy `dummy-data.json` to your static assets, `fetch` it, parse JSON, then assign **`element.data`**. You can also pass a JSON string on the **`data` attribute**; the component parses it the same way as an object `data` property.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"header": {},
|
|
3
|
+
"footer": {
|
|
4
|
+
"social": [
|
|
5
|
+
{ "platform": "LinkedIn", "href": "https://www.linkedin.com/" },
|
|
6
|
+
{ "platform": "Instagram", "href": "https://www.instagram.com/" },
|
|
7
|
+
{ "platform": "TikTok", "href": "https://www.tiktok.com/" },
|
|
8
|
+
{ "platform": "YouTube", "href": "https://www.youtube.com/" }
|
|
9
|
+
],
|
|
10
|
+
"standardLinks": [
|
|
11
|
+
{ "label": "About Us", "href": "/about" },
|
|
12
|
+
{ "label": "Privacy Policy", "href": "/privacy" },
|
|
13
|
+
{ "label": "Terms of Use", "href": "/terms" },
|
|
14
|
+
{ "label": "Cookie Policy", "href": "/cookies" },
|
|
15
|
+
{ "label": "Accessibility Statement", "href": "/accessibility" }
|
|
16
|
+
],
|
|
17
|
+
"credits": "Warwick Employment Group is a department of the Campus and Commercial Services Group at the University of Warwick.",
|
|
18
|
+
"copyright": "Copyright © Warwick Employment Group."
|
|
19
|
+
}
|
|
20
|
+
}
|