@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.
@@ -1,11 +1,16 @@
1
1
  import React from 'react';
2
2
  import get from 'lodash.get';
3
-
4
- import RelatedArticles from '@times-components/related-articles';
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 { getRelatedArticlesSlice } from './formatters';
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 slice = getRelatedArticlesSlice(articles);
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: found ? found.article.headline : '' }
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
- <RelatedArticles
45
- heading={heading}
46
- slice={slice}
47
- isVisible
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/related-articles', () => ({
16
+ jest.mock('@times-components/ts-slices', () => ({
17
17
  __esModule: true,
18
- default: (props: any) => (
18
+ Slice: (props: any) => (
19
19
  <div>
20
20
  RelatedArticles
21
- <div>{props.heading}</div>
22
- {props.slice.items.map(({ article }: any) => (
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 { RelatedArticleSliceType } from '../../types/related-article-slice';
1
+ import { SliceArticle } from '@times-components/ts-slices';
2
2
 
3
3
  // TYPES
4
4
 
5
- export type Byline =
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
- export type SummaryText = { __typename: string; text: string };
17
+ type SummaryText = { __typename: string; text: string };
18
18
  type Summary = { __typename: string; children: SummaryText[] };
19
19
 
20
- export type Article = {
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 getBylineAttr = (byline: Byline) => ({
35
- value: byline.type === 'author' ? byline.name : byline.value
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 getByline = (byline: Byline) => ({
39
- name: byline.type,
40
- children: [{ name: 'text', attributes: getBylineAttr(byline), children: [] }]
41
- });
41
+ const getSummary = (summary?: Summary) =>
42
+ summary && summary.children
43
+ ? summary.children.map(child => child.text).join('') + '...'
44
+ : undefined;
42
45
 
43
- const getBylines = (bylines?: Byline[]) => {
44
- if (bylines) {
45
- return bylines.map((byline: Byline) => ({ byline: [getByline(byline)] }));
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
- const getSummaryText = (summary: Summary) => {
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 getSummary = (summary?: Summary) => {
62
- if (summary && summary.children) {
63
- return [{ name: 'paragraph', children: getSummaryParagraph(summary) }];
64
- }
65
- return [];
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 getImage = (media?: Media) => {
69
- if (media && media.crops) {
70
- const image = media.crops.find(
71
- (crop: MediaCrop) => crop.aspectRatio === '16:9'
72
- );
73
- return image ? { crop169: { url: image.url }, title: image.alt } : null;
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
- // MAIN
79
-
80
- export const getRelatedArticlesSlice = (
81
- articles: any
82
- ): RelatedArticleSliceType => ({
83
- sliceName: 'StandardSlice',
84
- items: articles
85
- .map((article: Article) => ({
86
- article: {
87
- slug: article.slug,
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 dDeBKy"
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 gbnXjW"
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%2C3744%2C0%2C0&resize=80"
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 jkGvyo"
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-06-06T23:01:00.000Z',
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-06-06T16:00:00.000Z',
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-06-07T08:00:00.000Z',
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-06-06T23:01:00.000Z',
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-06-06T21:00:00.000Z',
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-06-06T23:01:00.000Z',
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-06-06T23:01:00.000Z',
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-06-06T23:01:00.000Z',
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-06-06T23:01:00.000Z',
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-06-06T23:01:00.000Z',
334
+ publishedDateTime: '2022-07-26T23:01:00.000Z',
335
335
  bylines: [
336
336
  {
337
337
  type: 'author',