@times-components/ts-components 1.104.1-alpha.58 → 1.104.1-alpha.67
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 +41 -0
- package/dist/components/article-sidebar/ArticleSidebar.js +2 -2
- package/dist/components/article-sidebar/styles.js +3 -3
- package/dist/components/newsletter-puff/InlineNewsletterPuff.js +23 -25
- package/dist/components/newsletter-puff/NewsletterPuff.stories.js +2 -20
- package/dist/components/newsletter-puff/__tests__/AutoNewsletterPuff.test.js +2 -20
- package/dist/components/newsletter-puff/__tests__/InlineNewsletterPuff.test.js +24 -33
- package/dist/components/newsletter-puff/newsletter/Newsletter.d.ts +4 -5
- package/dist/components/newsletter-puff/newsletter/Newsletter.js +13 -10
- package/dist/components/recommended-articles/__tests__/formatters.test.js +4 -4
- package/dist/components/recommended-articles/formatters.d.ts +1 -0
- package/dist/components/recommended-articles/formatters.js +2 -2
- package/dist/components/social-embed/BlockedEmbedMessage.d.ts +8 -0
- package/dist/components/social-embed/BlockedEmbedMessage.js +32 -0
- package/dist/components/social-embed/SocialMediaEmbed.d.ts +10 -9
- package/dist/components/social-embed/SocialMediaEmbed.js +44 -42
- package/dist/components/social-embed/constants.d.ts +12 -0
- package/dist/components/social-embed/constants.js +13 -0
- package/dist/components/social-embed/helpers/__tests__/vendorConsent.test.d.ts +1 -0
- package/dist/components/social-embed/helpers/__tests__/vendorConsent.test.js +53 -0
- package/dist/components/social-embed/helpers/enableCookies.d.ts +1 -1
- package/dist/components/social-embed/helpers/enableCookies.js +3 -3
- package/dist/components/social-embed/helpers/privacyModal.d.ts +1 -4
- package/dist/components/social-embed/helpers/privacyModal.js +1 -6
- package/dist/components/social-embed/helpers/vendorConsent.d.ts +2 -1
- package/dist/components/social-embed/helpers/vendorConsent.js +3 -5
- package/dist/components/social-embed/types.d.ts +9 -0
- package/dist/components/social-embed/types.js +2 -0
- package/dist/fixtures/preview-data/recommended-articles.d.ts +3 -0
- package/dist/fixtures/preview-data/recommended-articles.js +11 -1
- package/package.json +4 -5
- package/rnw.js +1 -1
- package/src/components/article-sidebar/ArticleSidebar.tsx +1 -1
- package/src/components/article-sidebar/__tests__/__snapshots__/index.test.tsx.snap +5 -5
- package/src/components/article-sidebar/styles.ts +3 -3
- package/src/components/newsletter-puff/InlineNewsletterPuff.tsx +34 -46
- package/src/components/newsletter-puff/NewsletterPuff.stories.tsx +1 -22
- package/src/components/newsletter-puff/__tests__/AutoNewsletterPuff.test.tsx +1 -22
- package/src/components/newsletter-puff/__tests__/InlineNewsletterPuff.test.tsx +31 -40
- package/src/components/newsletter-puff/__tests__/__snapshots__/InlineNewsletterPuff.test.tsx.snap +18 -35
- package/src/components/newsletter-puff/newsletter/Newsletter.tsx +26 -26
- package/src/components/recommended-articles/__tests__/formatters.test.tsx +3 -5
- package/src/components/recommended-articles/formatters.ts +2 -1
- package/src/components/social-embed/BlockedEmbedMessage.tsx +67 -0
- package/src/components/social-embed/SocialMediaEmbed.tsx +71 -87
- package/src/components/social-embed/constants.ts +14 -0
- package/src/components/social-embed/helpers/__tests__/vendorConsent.test.ts +77 -0
- package/src/components/social-embed/helpers/enableCookies.ts +2 -5
- package/src/components/social-embed/helpers/privacyModal.ts +1 -5
- package/src/components/social-embed/helpers/vendorConsent.ts +5 -8
- package/src/components/social-embed/types.ts +13 -0
- package/src/fixtures/preview-data/recommended-articles.ts +19 -0
- package/src/types/externs.d.ts +1 -1
|
@@ -1,55 +1,74 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
AllowButton,
|
|
4
|
-
CardContainer,
|
|
5
|
-
EnableButton,
|
|
6
|
-
LinkPrivacyManager,
|
|
7
|
-
Paragraph,
|
|
8
|
-
Title,
|
|
9
|
-
CustomIconContainer,
|
|
10
|
-
Header
|
|
11
|
-
} from './styles';
|
|
12
|
-
import { InfoIcon } from '../inline-message/InfoIcon';
|
|
13
|
-
import { openPrivacyModal, ModalType } from './helpers/privacyModal';
|
|
14
|
-
// @ts-ignore
|
|
15
|
-
import InteractiveWrapper from '@times-components/interactive-wrapper';
|
|
1
|
+
import React, { FC, useEffect, useState } from 'react';
|
|
2
|
+
import { BlockedEmbedMessage } from './BlockedEmbedMessage';
|
|
16
3
|
import { checkVendorConsent } from './helpers/vendorConsent';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { socialMediaVendors } from './helpers/socialMediaVendors';
|
|
20
|
-
|
|
21
|
-
export declare type SocialEmbedProps = {
|
|
22
|
-
element: any;
|
|
23
|
-
url?: string;
|
|
24
|
-
vendorName: string;
|
|
25
|
-
id: string;
|
|
26
|
-
};
|
|
4
|
+
import { eventStatus } from './constants';
|
|
5
|
+
import { TcData, VendorName } from './types';
|
|
27
6
|
|
|
28
7
|
declare global {
|
|
29
8
|
interface Window {
|
|
30
9
|
__tcfapi?: (
|
|
31
10
|
command: string,
|
|
32
11
|
version: number,
|
|
33
|
-
callback: (data:
|
|
12
|
+
callback: (data: TcData, success: boolean) => void,
|
|
13
|
+
listenerId?: number
|
|
34
14
|
) => void;
|
|
35
15
|
}
|
|
36
16
|
}
|
|
37
17
|
|
|
38
|
-
export
|
|
39
|
-
element
|
|
40
|
-
|
|
18
|
+
export type SocialMediaEmbedProps = {
|
|
19
|
+
element?: any;
|
|
20
|
+
url: string;
|
|
21
|
+
vendorName: VendorName;
|
|
22
|
+
id: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const SocialMediaEmbed: FC<SocialMediaEmbedProps> = ({
|
|
26
|
+
vendorName,
|
|
27
|
+
url
|
|
41
28
|
}) => {
|
|
42
|
-
const [
|
|
43
|
-
const [
|
|
29
|
+
const [isSocialEmbedAllowed, setIsSocialEmbedAllowed] = useState(false);
|
|
30
|
+
const [data, setData] = useState<TcData | null>(null);
|
|
44
31
|
|
|
45
|
-
useEffect(
|
|
46
|
-
()
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (window.__tcfapi) {
|
|
34
|
+
window.__tcfapi('addEventListener', 2, (tcData, success) => {
|
|
35
|
+
if (success && tcData.eventStatus === eventStatus.tcLoaded) {
|
|
36
|
+
setData({
|
|
37
|
+
cmpStatus: tcData.cmpStatus,
|
|
38
|
+
eventStatus: tcData.eventStatus,
|
|
39
|
+
listenerId: tcData.listenerId
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
checkVendorConsent(vendorName, setIsSocialEmbedAllowed);
|
|
43
|
+
}
|
|
44
|
+
if (success && tcData.eventStatus === eventStatus.userActionComplete) {
|
|
45
|
+
setData({
|
|
46
|
+
cmpStatus: tcData.cmpStatus,
|
|
47
|
+
eventStatus: tcData.eventStatus,
|
|
48
|
+
listenerId: tcData.listenerId
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
checkVendorConsent(vendorName, setIsSocialEmbedAllowed);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return () => {
|
|
57
|
+
if (window.__tcfapi && data && data.listenerId) {
|
|
58
|
+
window.__tcfapi(
|
|
59
|
+
'removeEventListener',
|
|
60
|
+
2,
|
|
61
|
+
success => {
|
|
62
|
+
if (success) {
|
|
63
|
+
// tslint:disable-next-line:no-console
|
|
64
|
+
console.log(success);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
data.listenerId
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}, []);
|
|
53
72
|
|
|
54
73
|
useEffect(
|
|
55
74
|
() => {
|
|
@@ -63,62 +82,27 @@ export const SocialMediaEmbed: React.FC<SocialEmbedProps> = ({
|
|
|
63
82
|
script.async = true;
|
|
64
83
|
script.src = 'https://platform.twitter.com/widgets.js';
|
|
65
84
|
|
|
85
|
+
let link = document.createElement('a');
|
|
86
|
+
link.href = `${url}?ref_src=twsrc%5Etfw`;
|
|
87
|
+
|
|
66
88
|
socialEmbedContainer.appendChild(script);
|
|
89
|
+
socialEmbedContainer.appendChild(link);
|
|
67
90
|
}
|
|
68
91
|
},
|
|
69
|
-
[
|
|
92
|
+
[isSocialEmbedAllowed]
|
|
70
93
|
);
|
|
71
94
|
|
|
72
|
-
const allowCookiesOnce = () => {
|
|
73
|
-
setAllowedOnce(true);
|
|
74
|
-
setIsSocialAllowed(true);
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const handlePrivacyManagerClick = (
|
|
78
|
-
e: React.MouseEvent<HTMLAnchorElement>
|
|
79
|
-
) => {
|
|
80
|
-
e.preventDefault();
|
|
81
|
-
openPrivacyModal(
|
|
82
|
-
ModalType.GDPR,
|
|
83
|
-
window.__TIMES_CONFIG__.sourcepoint.gdprMessageId
|
|
84
|
-
);
|
|
85
|
-
};
|
|
86
|
-
// tslint:disable-next-line:no-console
|
|
87
|
-
console.log('allowedOnce', allowedOnce);
|
|
88
95
|
// tslint:disable-next-line:no-console
|
|
89
|
-
console.log('
|
|
96
|
+
console.log('tcData', data);
|
|
90
97
|
// tslint:disable-next-line:no-console
|
|
91
|
-
console.log('
|
|
98
|
+
console.log('isSocialEmbedAllowed', isSocialEmbedAllowed);
|
|
92
99
|
|
|
93
|
-
return
|
|
94
|
-
<
|
|
95
|
-
<blockquote className="twitter-tweet">
|
|
96
|
-
<a href={`${element.attributes.url}?ref_src=twsrc%5Etfw`} />
|
|
97
|
-
</blockquote>
|
|
98
|
-
</div>
|
|
100
|
+
return isSocialEmbedAllowed ? (
|
|
101
|
+
<blockquote className="social-embed" />
|
|
99
102
|
) : (
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
</CustomIconContainer>
|
|
105
|
-
<Title>
|
|
106
|
-
{getVendorTitle(vendorName, socialMediaVendors)} content blocked
|
|
107
|
-
</Title>
|
|
108
|
-
</Header>
|
|
109
|
-
<Paragraph>
|
|
110
|
-
Please enable cookies and other technologies to view this content. You
|
|
111
|
-
can update your cookies preferences any time using{' '}
|
|
112
|
-
<LinkPrivacyManager href="#" onClick={handlePrivacyManagerClick}>
|
|
113
|
-
privacy manager.
|
|
114
|
-
</LinkPrivacyManager>
|
|
115
|
-
</Paragraph>
|
|
116
|
-
<EnableButton
|
|
117
|
-
onClick={() => enableCookies(vendorName, setIsSocialAllowed)}
|
|
118
|
-
>
|
|
119
|
-
Enable cookies
|
|
120
|
-
</EnableButton>
|
|
121
|
-
<AllowButton onClick={allowCookiesOnce}>Allow cookies once</AllowButton>
|
|
122
|
-
</CardContainer>
|
|
103
|
+
<BlockedEmbedMessage
|
|
104
|
+
vendorName={vendorName}
|
|
105
|
+
setIsSocialEmbedAllowed={setIsSocialEmbedAllowed}
|
|
106
|
+
/>
|
|
123
107
|
);
|
|
124
108
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const modalType = {
|
|
2
|
+
GDPR: 'gdpr',
|
|
3
|
+
CCPA: 'ccpa'
|
|
4
|
+
} as const;
|
|
5
|
+
|
|
6
|
+
export const eventStatus = {
|
|
7
|
+
tcLoaded: 'tcloaded',
|
|
8
|
+
cmpIsShown: 'cmpuishown',
|
|
9
|
+
userActionComplete: 'useractioncomplete'
|
|
10
|
+
} as const;
|
|
11
|
+
|
|
12
|
+
export const vendors = {
|
|
13
|
+
twitter: 'twitter'
|
|
14
|
+
} as const;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { checkVendorConsent } from '../vendorConsent';
|
|
2
|
+
import { VendorName } from '../../types';
|
|
3
|
+
|
|
4
|
+
describe('checkVendorConsent', () => {
|
|
5
|
+
let setIsSocialEmbedAllowed: jest.Mock;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
setIsSocialEmbedAllowed = jest.fn();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
jest.resetAllMocks();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('calls setIsSocialEmbedAllowed with true if vendor consent is found', () => {
|
|
16
|
+
const mockVendorName: VendorName = 'twitter';
|
|
17
|
+
// Mock window.__tcfapi function
|
|
18
|
+
(window as any).__tcfapi = jest.fn((command, version, callback) => {
|
|
19
|
+
// tslint:disable-next-line:no-console
|
|
20
|
+
console.log('command, version', command, version);
|
|
21
|
+
callback(
|
|
22
|
+
{ consentedVendors: [{ name: 'twitter' }] },
|
|
23
|
+
true // success
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
checkVendorConsent(mockVendorName, setIsSocialEmbedAllowed);
|
|
28
|
+
|
|
29
|
+
expect(setIsSocialEmbedAllowed).toHaveBeenCalledWith(true);
|
|
30
|
+
expect((window as any).__tcfapi).toHaveBeenCalledWith(
|
|
31
|
+
'getCustomVendorConsents',
|
|
32
|
+
2,
|
|
33
|
+
expect.any(Function)
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('calls setIsSocialEmbedAllowed with false if vendor consent is not found', () => {
|
|
38
|
+
const mockVendorName: VendorName = 'twitter';
|
|
39
|
+
(window as any).__tcfapi = jest.fn((command, version, callback) => {
|
|
40
|
+
// tslint:disable-next-line:no-console
|
|
41
|
+
console.log('command, version', command, version);
|
|
42
|
+
callback({ consentedVendors: [{ name: 'Other Vendor' }] }, true);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
checkVendorConsent(mockVendorName, setIsSocialEmbedAllowed);
|
|
46
|
+
|
|
47
|
+
expect(setIsSocialEmbedAllowed).toHaveBeenCalledWith(false);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('logs an error message if fetching consent data fails', () => {
|
|
51
|
+
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
52
|
+
const mockVendorName: VendorName = 'twitter';
|
|
53
|
+
(window as any).__tcfapi = jest.fn((command, version, callback) => {
|
|
54
|
+
// tslint:disable-next-line:no-console
|
|
55
|
+
console.log('command, version', command, version);
|
|
56
|
+
callback(null, false); // indicate failure
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
checkVendorConsent(mockVendorName, setIsSocialEmbedAllowed);
|
|
60
|
+
|
|
61
|
+
expect(setIsSocialEmbedAllowed).not.toHaveBeenCalled();
|
|
62
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
63
|
+
`Error fetching consent data or ${mockVendorName} embed not allowed`
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
consoleSpy.mockRestore();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('does nothing if window.__tcfapi is undefined', () => {
|
|
70
|
+
delete (window as any).__tcfapi;
|
|
71
|
+
const mockVendorName: VendorName = 'twitter';
|
|
72
|
+
|
|
73
|
+
checkVendorConsent(mockVendorName, setIsSocialEmbedAllowed);
|
|
74
|
+
|
|
75
|
+
expect(setIsSocialEmbedAllowed).not.toHaveBeenCalled();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { socialMediaVendors } from './socialMediaVendors';
|
|
2
2
|
|
|
3
|
-
export const enableCookies = (
|
|
4
|
-
vendorName: string,
|
|
5
|
-
setIsSocialAllowed: (allowed: boolean) => void
|
|
6
|
-
) => {
|
|
3
|
+
export const enableCookies = (vendorName: string) => {
|
|
7
4
|
const onCustomConsent = (_: any, success: boolean) => {
|
|
8
5
|
if (success) {
|
|
9
|
-
|
|
6
|
+
return true;
|
|
10
7
|
}
|
|
11
8
|
return null;
|
|
12
9
|
};
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import get from 'lodash.get';
|
|
2
|
-
|
|
3
|
-
export enum ModalType {
|
|
4
|
-
GDPR = 'gdpr',
|
|
5
|
-
CCPA = 'ccpa'
|
|
6
|
-
}
|
|
2
|
+
import { ModalType } from '../types';
|
|
7
3
|
|
|
8
4
|
export const openPrivacyModal = (type: ModalType, messageId: string) => {
|
|
9
5
|
const loadModal = get(window, `_sp_.${type}.loadPrivacyManagerModal`);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { VendorName } from '../types';
|
|
2
|
+
|
|
1
3
|
export const checkVendorConsent = (
|
|
2
|
-
vendorName:
|
|
3
|
-
|
|
4
|
+
vendorName: VendorName,
|
|
5
|
+
setIsSocialEmbedAllowed: (isSocialVendorAllowed: boolean) => void
|
|
4
6
|
) => {
|
|
5
7
|
if (window.__tcfapi) {
|
|
6
8
|
window.__tcfapi(
|
|
@@ -12,12 +14,7 @@ export const checkVendorConsent = (
|
|
|
12
14
|
(vendor: { name: string }) =>
|
|
13
15
|
vendor.name.toLowerCase() === vendorName.toLowerCase()
|
|
14
16
|
);
|
|
15
|
-
|
|
16
|
-
// tslint:disable-next-line:no-console
|
|
17
|
-
console.log(
|
|
18
|
-
`Consent check for ${vendorName}:`,
|
|
19
|
-
isSocialVendorAllowed
|
|
20
|
-
);
|
|
17
|
+
setIsSocialEmbedAllowed(isSocialVendorAllowed);
|
|
21
18
|
} else {
|
|
22
19
|
// tslint:disable-next-line:no-console
|
|
23
20
|
console.log(
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { eventStatus, vendors, modalType } from './constants';
|
|
2
|
+
|
|
3
|
+
export type EventStatus = typeof eventStatus[keyof typeof eventStatus];
|
|
4
|
+
|
|
5
|
+
export type TcData = {
|
|
6
|
+
cmpStatus: string;
|
|
7
|
+
eventStatus: EventStatus;
|
|
8
|
+
listenerId: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type VendorName = typeof vendors[keyof typeof vendors];
|
|
12
|
+
|
|
13
|
+
export type ModalType = typeof modalType[keyof typeof modalType];
|
|
@@ -4,6 +4,8 @@ export default {
|
|
|
4
4
|
{
|
|
5
5
|
url:
|
|
6
6
|
'https://www.thetimes.co.uk/article/save-or-splurge-what-experts-spend-their-own-money-on-tdd65qlj6',
|
|
7
|
+
categoryPath:
|
|
8
|
+
'l1/l2/article/save-or-splurge-what-experts-spend-their-own-money-on-tdd65qlj6',
|
|
7
9
|
slug: 'save-or-splurge-what-experts-spend-their-own-money-on',
|
|
8
10
|
label: null,
|
|
9
11
|
headline: 'Save or splurge: what experts spend their own money on',
|
|
@@ -51,6 +53,8 @@ export default {
|
|
|
51
53
|
{
|
|
52
54
|
url:
|
|
53
55
|
'https://www.thetimes.co.uk/article/lieutenant-colonel-ian-crooke-obituary-t0b890wgp',
|
|
56
|
+
categoryPath:
|
|
57
|
+
'l1/l2/article/lieutenant-colonel-ian-crooke-obituary-t0b890wgp',
|
|
54
58
|
slug: 'lieutenant-colonel-ian-crooke-obituary',
|
|
55
59
|
label: 'Obituary',
|
|
56
60
|
headline: 'Lieutenant Colonel Ian Crooke',
|
|
@@ -78,6 +82,8 @@ export default {
|
|
|
78
82
|
{
|
|
79
83
|
url:
|
|
80
84
|
'https://www.thetimes.co.uk/article/is-the-party-over-for-boris-johnson-k8s0jxv6r',
|
|
85
|
+
categoryPath:
|
|
86
|
+
'l1/l2/article/is-the-party-over-for-boris-johnson-k8s0jxv6r',
|
|
81
87
|
slug: 'is-the-party-over-for-boris-johnson',
|
|
82
88
|
label: 'RED BOX | PATRICK MAGUIRE',
|
|
83
89
|
headline: 'Is the party over for Johnson?',
|
|
@@ -118,6 +124,8 @@ export default {
|
|
|
118
124
|
{
|
|
119
125
|
url:
|
|
120
126
|
'https://www.thetimes.co.uk/article/quentin-letts-a-pm-his-party-and-the-country-left-firmly-in-limp-on-territory-klvfgrj8g',
|
|
127
|
+
categoryPath:
|
|
128
|
+
'l1/l2/article/quentin-letts-a-pm-his-party-and-the-country-left-firmly-in-limp-on-territory-klvfgrj8g',
|
|
121
129
|
slug:
|
|
122
130
|
'quentin-letts-a-pm-his-party-and-the-country-left-firmly-in-limp-on-territory',
|
|
123
131
|
label: 'Political Sketch',
|
|
@@ -152,6 +160,8 @@ export default {
|
|
|
152
160
|
{
|
|
153
161
|
url:
|
|
154
162
|
'https://www.thetimes.co.uk/article/boris-johnson-should-look-for-an-honourable-exit-7fkgkl2rq',
|
|
163
|
+
categoryPath:
|
|
164
|
+
'l1/l2/article/boris-johnson-should-look-for-an-honourable-exit-7fkgkl2rq',
|
|
155
165
|
slug: 'boris-johnson-should-look-for-an-honourable-exit',
|
|
156
166
|
label: 'WILLIAM HAGUE | COMMENT',
|
|
157
167
|
headline: 'Hague: Johnson should look for an honourable exit',
|
|
@@ -184,6 +194,8 @@ export default {
|
|
|
184
194
|
{
|
|
185
195
|
url:
|
|
186
196
|
'https://www.thetimes.co.uk/article/carrie-johnson-and-hard-times-at-no-10-hfmkr8ssn',
|
|
197
|
+
categoryPath:
|
|
198
|
+
'l1/l2/article/carrie-johnson-and-hard-times-at-no-10-hfmkr8ssn',
|
|
187
199
|
slug: 'carrie-johnson-and-hard-times-at-no-10',
|
|
188
200
|
label: 'POLITICS',
|
|
189
201
|
headline: 'Carrie Johnson and hard times at No 10',
|
|
@@ -216,6 +228,8 @@ export default {
|
|
|
216
228
|
{
|
|
217
229
|
url:
|
|
218
230
|
'https://www.thetimes.co.uk/article/dead-man-walking-times-commentators-give-their-verdicts-boris-johnson-confidence-vote-0f59md3bt',
|
|
231
|
+
categoryPath:
|
|
232
|
+
'l1/l2/article/dead-man-walking-times-commentators-give-their-verdicts-boris-johnson-confidence-vote-0f59md3bt',
|
|
219
233
|
slug:
|
|
220
234
|
'dead-man-walking-times-commentators-give-their-verdicts-boris-johnson-confidence-vote',
|
|
221
235
|
label: 'Politics',
|
|
@@ -269,6 +283,7 @@ export default {
|
|
|
269
283
|
{
|
|
270
284
|
url:
|
|
271
285
|
'https://www.thetimes.co.uk/article/margot-heuman-obituary-9fdm8h3hr',
|
|
286
|
+
categoryPath: 'l1/l2/article/margot-heuman-obituary-9fdm8h3hr',
|
|
272
287
|
slug: 'margot-heuman-obituary',
|
|
273
288
|
label: 'Obituary',
|
|
274
289
|
headline: 'Margot Heuman',
|
|
@@ -296,6 +311,8 @@ export default {
|
|
|
296
311
|
{
|
|
297
312
|
url:
|
|
298
313
|
'https://www.thetimes.co.uk/article/the-times-view-on-tory-confidence-in-boris-johnson-pyrrhic-victory-wl5fl2jb2',
|
|
314
|
+
categoryPath:
|
|
315
|
+
'l1/l2/article/the-times-view-on-tory-confidence-in-boris-johnson-pyrrhic-victory-wl5fl2jb2',
|
|
299
316
|
slug:
|
|
300
317
|
'the-times-view-on-tory-confidence-in-boris-johnson-pyrrhic-victory',
|
|
301
318
|
label: 'LEADING ARTICLE',
|
|
@@ -329,6 +346,8 @@ export default {
|
|
|
329
346
|
{
|
|
330
347
|
url:
|
|
331
348
|
'https://www.thetimes.co.uk/article/boris-johnson-allies-took-time-saving-big-dog-leadership-contest-rn5dzbw8h',
|
|
349
|
+
categoryPath:
|
|
350
|
+
'l1/l2/article/boris-johnson-allies-took-time-saving-big-dog-leadership-contest-rn5dzbw8h',
|
|
332
351
|
slug:
|
|
333
352
|
'boris-johnson-allies-took-time-saving-big-dog-leadership-contest',
|
|
334
353
|
label: 'Politics',
|
package/src/types/externs.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ declare module '@times-components/ts-slices' {
|
|
|
24
24
|
export type SliceArticle = {
|
|
25
25
|
id?: string;
|
|
26
26
|
url?: string;
|
|
27
|
+
categoryPath?: string;
|
|
27
28
|
label?: string;
|
|
28
29
|
byline?: string;
|
|
29
30
|
headline: string;
|
|
@@ -194,7 +195,6 @@ declare module '@times-components/provider' {
|
|
|
194
195
|
declare module '@times-components/provider-queries' {
|
|
195
196
|
import { DocumentNode } from 'graphql';
|
|
196
197
|
export const getNewsletter: DocumentNode;
|
|
197
|
-
export const subscribeNewsletter: DocumentNode;
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
declare module '@times-components/provider-test-tools' {
|