@times-components/ts-components 1.48.13 → 1.48.16
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 +27 -0
- package/dist/components/recommended-articles/RecommendedArticles.js +7 -9
- package/dist/components/recommended-articles/__tests__/RecommendedArticles.test.js +4 -5
- package/dist/components/recommended-articles/formatters.d.ts +10 -5
- package/dist/components/recommended-articles/formatters.js +43 -50
- package/dist/components/recommended-articles/styles.d.ts +1 -0
- package/dist/components/recommended-articles/styles.js +15 -0
- package/dist/fixtures/preview-data/recommended-articles.js +10 -10
- package/package.json +5 -5
- package/rnw.js +1 -1
- package/src/components/recommended-articles/RecommendedArticles.tsx +14 -18
- package/src/components/recommended-articles/__tests__/RecommendedArticles.test.tsx +4 -7
- package/src/components/recommended-articles/__tests__/__snapshots__/RecommendedArticles.test.tsx.snap +15 -9
- package/src/components/recommended-articles/formatters.ts +50 -60
- package/src/components/recommended-articles/styles.ts +15 -0
- package/src/components/related-article-slice/__tests__/__snapshots__/RelatedArticleSlice.test.tsx.snap +4 -4
- package/src/fixtures/preview-data/recommended-articles.ts +10 -10
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import get from 'lodash.get';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
Slice,
|
|
5
|
+
SliceArticle,
|
|
6
|
+
MouseEventType
|
|
7
|
+
} from '@times-components/ts-slices';
|
|
5
8
|
|
|
6
9
|
import { useFetch } from '../../helpers/fetch/FetchProvider';
|
|
7
10
|
import { useTrackingContext } from '../../helpers/tracking/TrackingContextProvider';
|
|
8
|
-
import {
|
|
11
|
+
import { getRecommendedArticlesSlice } from './formatters';
|
|
12
|
+
|
|
13
|
+
import { Header } from './styles';
|
|
9
14
|
|
|
10
15
|
export const RecommendedArticles: React.FC<{
|
|
11
16
|
heading: string;
|
|
@@ -24,30 +29,21 @@ export const RecommendedArticles: React.FC<{
|
|
|
24
29
|
|
|
25
30
|
const { fireAnalyticsEvent } = useTrackingContext();
|
|
26
31
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
const onClickHandler = (__: MouseEvent, article: { url: string }) => {
|
|
30
|
-
const found = slice.items.find(
|
|
31
|
-
item => item.article.shortIdentifier === article.url.slice(-9)
|
|
32
|
-
);
|
|
33
|
-
|
|
32
|
+
const onClickHandler = (__: MouseEventType, article: SliceArticle) => {
|
|
34
33
|
if (fireAnalyticsEvent) {
|
|
35
34
|
fireAnalyticsEvent({
|
|
36
35
|
action: 'Clicked',
|
|
37
|
-
attrs: { article_parent_name:
|
|
36
|
+
attrs: { article_parent_name: article.headline }
|
|
38
37
|
});
|
|
39
38
|
}
|
|
40
39
|
};
|
|
41
40
|
|
|
42
41
|
return (
|
|
43
42
|
<div id="recommended-articles">
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
slice={
|
|
47
|
-
|
|
48
|
-
onPress={onClickHandler}
|
|
49
|
-
// tslint:disable-next-line: no-empty
|
|
50
|
-
analyticsStream={() => {}}
|
|
43
|
+
<Header>{heading}</Header>
|
|
44
|
+
<Slice
|
|
45
|
+
slice={getRecommendedArticlesSlice(articles)}
|
|
46
|
+
clickHandler={onClickHandler}
|
|
51
47
|
/>
|
|
52
48
|
</div>
|
|
53
49
|
);
|
|
@@ -13,16 +13,13 @@ jest.mock('../../../helpers/fetch/FetchProvider', () => ({
|
|
|
13
13
|
useFetch: jest.fn()
|
|
14
14
|
}));
|
|
15
15
|
|
|
16
|
-
jest.mock('@times-components/
|
|
16
|
+
jest.mock('@times-components/ts-slices', () => ({
|
|
17
17
|
__esModule: true,
|
|
18
|
-
|
|
18
|
+
Slice: (props: any) => (
|
|
19
19
|
<div>
|
|
20
20
|
RelatedArticles
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<div
|
|
24
|
-
onClick={() => props.onPress(null, { url: article.shortIdentifier })}
|
|
25
|
-
>
|
|
21
|
+
{props.slice.children.map(({ article }: any) => (
|
|
22
|
+
<div onClick={() => props.clickHandler(null, article)}>
|
|
26
23
|
{article.headline}
|
|
27
24
|
</div>
|
|
28
25
|
))}
|
|
@@ -5,11 +5,13 @@ exports[`<RecommendedArticles> should render RelatedArticles correctly with 1 ar
|
|
|
5
5
|
<div
|
|
6
6
|
id="recommended-articles"
|
|
7
7
|
>
|
|
8
|
+
<div
|
|
9
|
+
class="sc-bdVaJa layBAg"
|
|
10
|
+
>
|
|
11
|
+
Today's news
|
|
12
|
+
</div>
|
|
8
13
|
<div>
|
|
9
14
|
RelatedArticles
|
|
10
|
-
<div>
|
|
11
|
-
Today's news
|
|
12
|
-
</div>
|
|
13
15
|
<div>
|
|
14
16
|
Save or splurge: what experts spend their own money on
|
|
15
17
|
</div>
|
|
@@ -23,11 +25,13 @@ exports[`<RecommendedArticles> should render RelatedArticles correctly with 2 ar
|
|
|
23
25
|
<div
|
|
24
26
|
id="recommended-articles"
|
|
25
27
|
>
|
|
28
|
+
<div
|
|
29
|
+
class="sc-bdVaJa layBAg"
|
|
30
|
+
>
|
|
31
|
+
Today's news
|
|
32
|
+
</div>
|
|
26
33
|
<div>
|
|
27
34
|
RelatedArticles
|
|
28
|
-
<div>
|
|
29
|
-
Today's news
|
|
30
|
-
</div>
|
|
31
35
|
<div>
|
|
32
36
|
Save or splurge: what experts spend their own money on
|
|
33
37
|
</div>
|
|
@@ -44,11 +48,13 @@ exports[`<RecommendedArticles> should render RelatedArticles correctly with 3 ar
|
|
|
44
48
|
<div
|
|
45
49
|
id="recommended-articles"
|
|
46
50
|
>
|
|
51
|
+
<div
|
|
52
|
+
class="sc-bdVaJa layBAg"
|
|
53
|
+
>
|
|
54
|
+
Today's news
|
|
55
|
+
</div>
|
|
47
56
|
<div>
|
|
48
57
|
RelatedArticles
|
|
49
|
-
<div>
|
|
50
|
-
Today's news
|
|
51
|
-
</div>
|
|
52
58
|
<div>
|
|
53
59
|
Save or splurge: what experts spend their own money on
|
|
54
60
|
</div>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SliceArticle } from '@times-components/ts-slices';
|
|
2
2
|
|
|
3
3
|
// TYPES
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
type Byline =
|
|
6
6
|
| { __typename: string; type: 'author'; name: string }
|
|
7
7
|
| { __typename: string; type: 'inline'; value: string };
|
|
8
8
|
|
|
@@ -14,10 +14,10 @@ type MediaCrop = {
|
|
|
14
14
|
};
|
|
15
15
|
type Media = { __typename: string; crops: MediaCrop[] };
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
type SummaryText = { __typename: string; text: string };
|
|
18
18
|
type Summary = { __typename: string; children: SummaryText[] };
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
type Article = {
|
|
21
21
|
__typename: string;
|
|
22
22
|
url: string;
|
|
23
23
|
slug: string;
|
|
@@ -31,68 +31,58 @@ export type Article = {
|
|
|
31
31
|
|
|
32
32
|
// HELPERS
|
|
33
33
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
const getBylines = (bylines?: Byline[]) =>
|
|
35
|
+
bylines
|
|
36
|
+
? bylines
|
|
37
|
+
.map(byline => (byline.type === 'author' ? byline.name : byline.value))
|
|
38
|
+
.join('')
|
|
39
|
+
: undefined;
|
|
37
40
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
const getSummary = (summary?: Summary) =>
|
|
42
|
+
summary && summary.children
|
|
43
|
+
? summary.children.map(child => child.text).join('') + '...'
|
|
44
|
+
: undefined;
|
|
42
45
|
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return undefined;
|
|
48
|
-
};
|
|
46
|
+
const getImageCrops = (media?: Media) =>
|
|
47
|
+
media && media.crops
|
|
48
|
+
? media.crops.map(crop => ({ url: crop.url, ratio: crop.aspectRatio }))
|
|
49
|
+
: [];
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
const text = summary.children
|
|
52
|
-
.map((child: SummaryText) => child.text)
|
|
53
|
-
.join('');
|
|
54
|
-
return { value: text.slice(0, text.slice(0, 125).lastIndexOf(' ')) };
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const getSummaryParagraph = (summary: Summary) => [
|
|
58
|
-
{ name: 'text', attributes: getSummaryText(summary), children: [] }
|
|
59
|
-
];
|
|
51
|
+
// MAIN
|
|
60
52
|
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
53
|
+
const formatArticle = (article: Article): SliceArticle => {
|
|
54
|
+
return {
|
|
55
|
+
url: article.url,
|
|
56
|
+
label: article.label,
|
|
57
|
+
byline: getBylines(article.bylines),
|
|
58
|
+
headline: article.headline,
|
|
59
|
+
summary: getSummary(article.summary),
|
|
60
|
+
datePublished: article.publishedDateTime,
|
|
61
|
+
images: {
|
|
62
|
+
alt: article.headline,
|
|
63
|
+
crops: getImageCrops(article.media)
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
const getSliceName = (numOfArticles: number) => {
|
|
69
|
+
switch (numOfArticles) {
|
|
70
|
+
case 1:
|
|
71
|
+
return 'RELATED_ARTICLE_1';
|
|
72
|
+
case 2:
|
|
73
|
+
return 'RELATED_ARTICLE_2';
|
|
74
|
+
default:
|
|
75
|
+
return 'RELATED_ARTICLE_3';
|
|
74
76
|
}
|
|
75
|
-
return {};
|
|
76
77
|
};
|
|
77
78
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
shortIdentifier: article.url.slice(-9),
|
|
89
|
-
label: article.label,
|
|
90
|
-
headline: article.headline,
|
|
91
|
-
publishedTime: article.publishedDateTime,
|
|
92
|
-
bylines: getBylines(article.bylines),
|
|
93
|
-
summary125: getSummary(article.summary),
|
|
94
|
-
leadAsset: getImage(article.media)
|
|
95
|
-
}
|
|
96
|
-
}))
|
|
97
|
-
.slice(0, 3)
|
|
98
|
-
});
|
|
79
|
+
export const getRecommendedArticlesSlice = (articles: Article[]) => {
|
|
80
|
+
return {
|
|
81
|
+
name: getSliceName(articles.length),
|
|
82
|
+
children: articles
|
|
83
|
+
.map((article: Article) => ({
|
|
84
|
+
article: formatArticle(article)
|
|
85
|
+
}))
|
|
86
|
+
.slice(0, 3)
|
|
87
|
+
};
|
|
88
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
import { colours, fonts } from '@times-components/ts-styleguide';
|
|
3
|
+
|
|
4
|
+
export const Header = styled.div`
|
|
5
|
+
margin-bottom: 12px;
|
|
6
|
+
padding: 12px;
|
|
7
|
+
color: ${colours.functional.brandColour};
|
|
8
|
+
font-family: ${fonts.headline};
|
|
9
|
+
font-size: 24px;
|
|
10
|
+
line-height: 24px;
|
|
11
|
+
font-weight: normal;
|
|
12
|
+
text-align: center;
|
|
13
|
+
border-top: 1px solid #dbdbdb;
|
|
14
|
+
border-bottom: 1px solid #dbdbdb;
|
|
15
|
+
`;
|
|
@@ -15,7 +15,7 @@ exports[`RelatedArticleSlice renders 1 1`] = `
|
|
|
15
15
|
Related Articles
|
|
16
16
|
</div>
|
|
17
17
|
<div
|
|
18
|
-
class="shared-styles__SliceContainer-ismxwo-0 styles__SliceContainer-b33h2c-0
|
|
18
|
+
class="shared-styles__SliceContainer-ismxwo-0 styles__SliceContainer-b33h2c-0 bJHjPH"
|
|
19
19
|
>
|
|
20
20
|
<div
|
|
21
21
|
class="shared-styles__SlotContainer-ismxwo-1 styles__SlotContainer-b33h2c-1 cKwigu"
|
|
@@ -33,14 +33,14 @@ exports[`RelatedArticleSlice renders 1 1`] = `
|
|
|
33
33
|
href="https://www.thetimes.co.uk/article/how-to-recruit-the-best-young-people-to-your-business-5kksq826t"
|
|
34
34
|
>
|
|
35
35
|
<div
|
|
36
|
-
class="styles__ImageRatio-sc-8lglkt-1
|
|
36
|
+
class="styles__ImageRatio-sc-8lglkt-1 kDSgGC"
|
|
37
37
|
>
|
|
38
38
|
<div
|
|
39
39
|
class="styles__LazyContainer-qsbah5-0 jRxzJB"
|
|
40
40
|
>
|
|
41
41
|
<img
|
|
42
42
|
alt=""
|
|
43
|
-
src="https://www.thetimes.co.uk/imageserver/image/%2Fmethode%2Ftimes%2Fprod%2Fweb%2Fbin%2F7547ab46-ace4-11eb-bda6-057976012425.jpg?crop=5616%
|
|
43
|
+
src="https://www.thetimes.co.uk/imageserver/image/%2Fmethode%2Ftimes%2Fprod%2Fweb%2Fbin%2F7547ab46-ace4-11eb-bda6-057976012425.jpg?crop=5616%2C3159%2C0%2C293&resize=80"
|
|
44
44
|
/>
|
|
45
45
|
</div>
|
|
46
46
|
</div>
|
|
@@ -56,7 +56,7 @@ exports[`RelatedArticleSlice renders 1 1`] = `
|
|
|
56
56
|
Comment
|
|
57
57
|
</p>
|
|
58
58
|
<div
|
|
59
|
-
class="styles__HeadlineContainer-k0mgwi-0
|
|
59
|
+
class="styles__HeadlineContainer-k0mgwi-0 ghKmOQ"
|
|
60
60
|
>
|
|
61
61
|
<a
|
|
62
62
|
href="https://www.thetimes.co.uk/article/how-to-recruit-the-best-young-people-to-your-business-5kksq826t"
|
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
slug: 'save-or-splurge-what-experts-spend-their-own-money-on',
|
|
8
8
|
label: null,
|
|
9
9
|
headline: 'Save or splurge: what experts spend their own money on',
|
|
10
|
-
publishedDateTime: '2022-
|
|
10
|
+
publishedDateTime: '2022-07-26T23:01:00.000Z',
|
|
11
11
|
bylines: [
|
|
12
12
|
{
|
|
13
13
|
type: 'inline',
|
|
@@ -54,7 +54,7 @@ export default {
|
|
|
54
54
|
slug: 'lieutenant-colonel-ian-crooke-obituary',
|
|
55
55
|
label: 'Obituary',
|
|
56
56
|
headline: 'Lieutenant Colonel Ian Crooke',
|
|
57
|
-
publishedDateTime: '2022-
|
|
57
|
+
publishedDateTime: '2022-07-27T16:00:00.000Z',
|
|
58
58
|
bylines: [],
|
|
59
59
|
summary: {
|
|
60
60
|
children: [
|
|
@@ -81,7 +81,7 @@ export default {
|
|
|
81
81
|
slug: 'is-the-party-over-for-boris-johnson',
|
|
82
82
|
label: 'RED BOX | PATRICK MAGUIRE',
|
|
83
83
|
headline: 'Is the party over for Johnson?',
|
|
84
|
-
publishedDateTime: '2022-
|
|
84
|
+
publishedDateTime: '2022-07-27T08:00:00.000Z',
|
|
85
85
|
bylines: [
|
|
86
86
|
{
|
|
87
87
|
type: 'author',
|
|
@@ -121,7 +121,7 @@ export default {
|
|
|
121
121
|
label: 'Political Sketch',
|
|
122
122
|
headline:
|
|
123
123
|
'A PM, his party and the country left firmly in limp-on territory',
|
|
124
|
-
publishedDateTime: '2022-
|
|
124
|
+
publishedDateTime: '2022-07-26T23:01:00.000Z',
|
|
125
125
|
bylines: [
|
|
126
126
|
{
|
|
127
127
|
type: 'author',
|
|
@@ -153,7 +153,7 @@ export default {
|
|
|
153
153
|
slug: 'boris-johnson-should-look-for-an-honourable-exit',
|
|
154
154
|
label: 'WILLIAM HAGUE | COMMENT',
|
|
155
155
|
headline: 'Hague: Johnson should look for an honourable exit',
|
|
156
|
-
publishedDateTime: '2022-
|
|
156
|
+
publishedDateTime: '2022-07-26T21:00:00.000Z',
|
|
157
157
|
bylines: [
|
|
158
158
|
{
|
|
159
159
|
type: 'author',
|
|
@@ -185,7 +185,7 @@ export default {
|
|
|
185
185
|
slug: 'carrie-johnson-and-hard-times-at-no-10',
|
|
186
186
|
label: 'POLITICS',
|
|
187
187
|
headline: 'Carrie Johnson and hard times at No 10',
|
|
188
|
-
publishedDateTime: '2022-
|
|
188
|
+
publishedDateTime: '2022-07-26T23:01:00.000Z',
|
|
189
189
|
bylines: [
|
|
190
190
|
{
|
|
191
191
|
type: 'author',
|
|
@@ -218,7 +218,7 @@ export default {
|
|
|
218
218
|
'dead-man-walking-times-commentators-give-their-verdicts-boris-johnson-confidence-vote',
|
|
219
219
|
label: 'Politics',
|
|
220
220
|
headline: 'Dead man walking? Times commentators give their verdicts',
|
|
221
|
-
publishedDateTime: '2022-
|
|
221
|
+
publishedDateTime: '2022-07-26T23:01:00.000Z',
|
|
222
222
|
bylines: [
|
|
223
223
|
{
|
|
224
224
|
type: 'inline',
|
|
@@ -270,7 +270,7 @@ export default {
|
|
|
270
270
|
slug: 'margot-heuman-obituary',
|
|
271
271
|
label: 'Obituary',
|
|
272
272
|
headline: 'Margot Heuman',
|
|
273
|
-
publishedDateTime: '2022-
|
|
273
|
+
publishedDateTime: '2022-07-26T23:01:00.000Z',
|
|
274
274
|
bylines: [],
|
|
275
275
|
summary: {
|
|
276
276
|
children: [
|
|
@@ -298,7 +298,7 @@ export default {
|
|
|
298
298
|
'the-times-view-on-tory-confidence-in-boris-johnson-pyrrhic-victory',
|
|
299
299
|
label: 'LEADING ARTICLE',
|
|
300
300
|
headline: 'Pyrrhic Victory',
|
|
301
|
-
publishedDateTime: '2022-
|
|
301
|
+
publishedDateTime: '2022-07-26T23:01:00.000Z',
|
|
302
302
|
bylines: [
|
|
303
303
|
{
|
|
304
304
|
type: 'author',
|
|
@@ -331,7 +331,7 @@ export default {
|
|
|
331
331
|
'boris-johnson-allies-took-time-saving-big-dog-leadership-contest',
|
|
332
332
|
label: 'Politics',
|
|
333
333
|
headline: 'Allies took their time in campaign to save Big Dog',
|
|
334
|
-
publishedDateTime: '2022-
|
|
334
|
+
publishedDateTime: '2022-07-26T23:01:00.000Z',
|
|
335
335
|
bylines: [
|
|
336
336
|
{
|
|
337
337
|
type: 'author',
|