playbook_ui 12.31.0.pre.alpha.PLAY814removemomentjs935 → 12.31.0.pre.alpha.customiconsfa928

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/custom-icons.js +355 -0
  3. data/app/pb_kits/playbook/index.js +2 -1
  4. data/app/pb_kits/playbook/pb_date/_date.tsx +8 -7
  5. data/app/pb_kits/playbook/pb_date_range_inline/_date_range_inline.tsx +31 -45
  6. data/app/pb_kits/playbook/pb_date_range_stacked/_date_range_stacked.tsx +3 -5
  7. data/app/pb_kits/playbook/pb_date_stacked/_date_stacked.tsx +21 -24
  8. data/app/pb_kits/playbook/pb_date_time/_date_time.tsx +1 -1
  9. data/app/pb_kits/playbook/pb_date_time/dateTime.test.js +1 -1
  10. data/app/pb_kits/playbook/pb_date_time_stacked/_date_time_stacked.tsx +2 -2
  11. data/app/pb_kits/playbook/pb_date_time_stacked/date_time_stacked.test.js +1 -1
  12. data/app/pb_kits/playbook/pb_date_year_stacked/_date_year_stacked.tsx +8 -6
  13. data/app/pb_kits/playbook/pb_icon/_icon.tsx +9 -3
  14. data/app/pb_kits/playbook/pb_icon/icon.rb +8 -2
  15. data/app/pb_kits/playbook/pb_kit/dateTime.ts +67 -139
  16. data/app/pb_kits/playbook/pb_label_value/_label_value.tsx +31 -52
  17. data/app/pb_kits/playbook/pb_logistic/_logistic.jsx +120 -0
  18. data/app/pb_kits/playbook/pb_message/_message.tsx +24 -24
  19. data/app/pb_kits/playbook/pb_time/_time.tsx +11 -9
  20. data/app/pb_kits/playbook/pb_time_range_inline/_time_range_inline.tsx +49 -46
  21. data/app/pb_kits/playbook/pb_time_stacked/_time_stacked.tsx +6 -4
  22. data/app/pb_kits/playbook/pb_timestamp/_timestamp.tsx +11 -11
  23. data/app/pb_kits/playbook/pb_weekday_stacked/_weekday_stacked.tsx +11 -8
  24. data/dist/playbook-rails.js +7 -7
  25. data/lib/playbook/version.rb +1 -1
  26. metadata +4 -2
@@ -89,7 +89,7 @@ describe('DateTime Kit', () => {
89
89
  const kit = screen.getByTestId(testId)
90
90
  const text = kit.querySelector('.pb_time_kit_md.ml_sm')
91
91
 
92
- expect(text.textContent).toEqual('2:00p GMT+9')
92
+ expect(text.textContent).toEqual('2:00p JST')
93
93
  })
94
94
  test('renders DatePicker size', () => {
95
95
  render(
@@ -12,8 +12,8 @@ import DateStacked from '../pb_date_stacked/_date_stacked'
12
12
 
13
13
  type DateTimeStackedProps = {
14
14
  id?: string,
15
- date: Date,
16
- datetime: Date,
15
+ date: string,
16
+ datetime: string,
17
17
  dark: boolean,
18
18
  timeZone?: string,
19
19
  }
@@ -34,7 +34,7 @@ test('renders time in default timezone', () => {
34
34
  test('renders time in timezone', () => {
35
35
  props.timeZone = 'Asia/Tokyo'
36
36
  const kit = renderKit(DateTimeStacked, props)
37
- expect(kit).toHaveTextContent(`${monthDayYear}2:00aGMT+9`)
37
+ expect(kit).toHaveTextContent(`${monthDayYear}2:00aJST`)
38
38
  })
39
39
 
40
40
  test('renders time in timezone', () => {
@@ -1,9 +1,9 @@
1
1
  import React from 'react'
2
2
  import classnames from 'classnames'
3
3
 
4
+ import DateTime from '../pb_kit/dateTime'
4
5
  import { buildCss, buildDataProps } from '../utilities/props'
5
6
  import { globalProps } from '../utilities/globalProps'
6
- import DateTime from '../pb_kit/dateTime';
7
7
 
8
8
  import Body from '../pb_body/_body'
9
9
  import Title from '../pb_title/_title'
@@ -13,12 +13,13 @@ type DateYearStackedProps = {
13
13
  className?: string | string[],
14
14
  dark?: boolean,
15
15
  data?: string,
16
- date: Date,
16
+ date: string,
17
17
  id?: string,
18
18
  }
19
19
 
20
20
  const DateYearStacked = (props: DateYearStackedProps) => {
21
21
  const { align = 'left', className, dark = false, date, data={} } = props
22
+ const dateTimestamp = new DateTime({ value: date })
22
23
  const css = classnames(
23
24
  buildCss('pb_date_year_stacked', align),
24
25
  globalProps(props),
@@ -28,14 +29,15 @@ const DateYearStacked = (props: DateYearStackedProps) => {
28
29
 
29
30
  return (
30
31
  <div {...dataProps}
31
- className={css}
32
- >
32
+ className={css}>
33
33
  <Title
34
34
  dark={dark}
35
35
  size={4}
36
- text={`${DateTime.toDay(date)} ${DateTime.toMonth(date).toUpperCase()}`}
36
+ text={`${dateTimestamp.toDay()} ${dateTimestamp
37
+ .toMonth()
38
+ .toUpperCase()}`}
37
39
  />
38
- <Body color="light">{DateTime.toYear(date)}</Body>
40
+ <Body color="light">{dateTimestamp.toYear()}</Body>
39
41
  </div>
40
42
  )
41
43
  }
@@ -34,7 +34,7 @@ type IconProps = {
34
34
  pulse?: boolean,
35
35
  rotation?: 90 | 180 | 270,
36
36
  size?: IconSizes,
37
- fontStyle?: 'far' | 'fas' | 'fab',
37
+ fontStyle?: 'far' | 'fas' | 'fab' | 'fak',
38
38
  spin?: boolean,
39
39
  } & GlobalProps
40
40
 
@@ -76,6 +76,7 @@ const Icon = (props: IconProps) => {
76
76
  [`fa-${size}`]: size,
77
77
  [`fa-pull-${pull}`]: pull,
78
78
  [`fa-rotate-${rotation}`]: rotation,
79
+
79
80
  }
80
81
 
81
82
  // Lets check and see if the icon prop is referring to a custom Power icon...
@@ -83,11 +84,15 @@ const Icon = (props: IconProps) => {
83
84
  // this ensures the JS will not do any further operations
84
85
  // faClasses[`fa-${icon}`] = customIcon ? 'custom' : icon
85
86
  if (!customIcon) faClasses[`fa-${icon}`] = icon
86
-
87
+
88
+ const whiteList = [
89
+ 'greensky', 'powergon'
90
+ ]
91
+
87
92
  const classes = classnames(
88
93
  flipMap[flip],
89
94
  'pb_icon_kit',
90
- customIcon ? '' : fontStyle,
95
+ customIcon ? '' : whiteList.includes(icon) ? `fak` : fontStyle,
91
96
  faClasses,
92
97
  globalProps(props),
93
98
  className
@@ -110,6 +115,7 @@ const Icon = (props: IconProps) => {
110
115
  return emojiRegex.test(emoji);
111
116
  };
112
117
 
118
+
113
119
  // Add a conditional here to show only the SVG if custom
114
120
  const displaySVG = (customIcon: any) => {
115
121
  if (customIcon)
@@ -33,7 +33,7 @@ module Playbook
33
33
  values: ["lg", "xs", "sm", "1x", "2x", "3x", "4x", "5x", "6x", "7x", "8x", "9x", "10x", nil],
34
34
  default: nil
35
35
  prop :font_style, type: Playbook::Props::Enum,
36
- values: %w[far fas fab],
36
+ values: %w[far fas fab fak],
37
37
  default: "far"
38
38
  prop :spin, type: Playbook::Props::Boolean,
39
39
  default: false
@@ -140,7 +140,13 @@ module Playbook
140
140
  end
141
141
 
142
142
  def font_style_class
143
- font_style ? font_style.to_s : "far"
143
+ white_list = %w[powergon greensky]
144
+
145
+ if white_list.include?(icon)
146
+ "fak"
147
+ elsif font_style
148
+ font_style.to_s
149
+ end
144
150
  end
145
151
 
146
152
  def spin_class
@@ -1,162 +1,90 @@
1
+
2
+ import moment, { Moment } from 'moment'
3
+ import 'moment-strftime'
4
+ import 'moment-timezone'
5
+
6
+ type DateTimeType = {
7
+ value: string | Date,
8
+ zone?: string,
9
+ }
10
+
1
11
  const ABBR_DAYS = ['SU', 'M', 'T', 'W', 'TH', 'F', 'S']
2
12
 
3
- const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
13
+ export default class DateTime {
14
+ value: Moment & any
15
+ constructor({ value, zone = 'America/New_York' }: DateTimeType) {
16
+ this.value = this.convertToTimestampZone(value, zone)
17
+ }
4
18
 
5
- const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
19
+ convertToTimestampZone(value: string | Date, zone: string) {
20
+ return moment(value).tz(zone)
21
+ }
6
22
 
7
- export const toMinute = (newDate: Date | string, timeZone?: string): string => {
8
- const date = new Date(newDate)
9
- if (timeZone) {
10
- return date.toLocaleTimeString(undefined, {timeZone, hour: "2-digit", minute: "2-digit"}).slice(3, 5);
11
- } else {
12
- return date.toLocaleTimeString(undefined, {hour: "2-digit", minute: "2-digit"}).slice(3, 5);
23
+ convertToTimezone() {
24
+ return this.value.strftime('%Z')
13
25
  }
14
- }
15
26
 
16
- export const toHour = (newDate: Date | string, timeZone?: string): string => {
17
- const date = new Date(newDate)
18
- if (timeZone) {
19
- return date.toLocaleTimeString(undefined, {timeZone, hour: "numeric"}).split(' ')[0];
20
- } else {
21
- return date.toLocaleTimeString(undefined, {hour: "numeric"}).split(' ')[0];
27
+ toCustomFormat(format = '%-m/%-d') {
28
+ return this.value.strftime(format)
22
29
  }
23
- }
24
30
 
25
- export const toDay = (newDate: Date | string, timeZone?: string): number => {
26
- if (timeZone) {
27
- const date = new Date(newDate.toLocaleString(undefined, { timeZone }));
28
- return date.getDate()
29
- } else {
30
- const date = new Date(newDate)
31
- return date.getDate()
32
- }
33
- }
31
+ toYear() {
32
+ return this.value.strftime('%Y')
33
+ }
34
34
 
35
- export const toDayAbbr = (newDate: Date | string): string => {
36
- const date = new Date(newDate)
37
- return ABBR_DAYS[date.getUTCDay()]
38
- }
35
+ toMonth() {
36
+ return this.value.strftime('%b')
37
+ }
39
38
 
40
- export const toWeekday = (newDate: Date | string): string => {
41
- const date = new Date(newDate)
42
- return days[date.getUTCDay()]
43
- }
39
+ toMonthNum() {
40
+ return this.value.strftime('%-m')
41
+ }
44
42
 
45
- export const toMonth = (newDate: Date | string, timeZone?: string): string => {
46
- if (timeZone) {
47
- const date = new Date(newDate.toLocaleString(undefined, { timeZone }));
48
- return months[date.getUTCMonth()]
49
- } else {
50
- const date = new Date(newDate)
51
- return months[date.getUTCMonth()]
52
- }
53
- }
43
+ toMonthFull() {
44
+ return this.value.strftime('%B')
45
+ }
54
46
 
55
- export const toMonthNum = (newDate: Date | string): number => {
56
- const date = new Date(newDate)
57
- return date.getUTCMonth() +1
58
- }
47
+ toDay() {
48
+ return this.value.strftime('%e')
49
+ }
59
50
 
60
- export const toYear = (newDate: Date | string, timeZone?: string): number => {
61
- if (timeZone) {
62
- const date = new Date(newDate.toLocaleString(undefined, { timeZone }));
63
- return date.getUTCFullYear()
64
- } else {
65
- const date = new Date(newDate)
66
- return date.getUTCFullYear()
67
- }
68
- }
51
+ toDayAbbr() {
52
+ return ABBR_DAYS[this.value.day()]
53
+ }
69
54
 
70
- export const toTime = (newDate: Date | string, timeZone?: string): string => {
71
- const date = new Date(newDate)
72
- if (timeZone) {
73
- return date.toLocaleTimeString(undefined, {timeZone, timeStyle: "short"}).split(' ')[0];
74
- } else {
75
- return date.toLocaleTimeString(undefined, {timeStyle: "short"}).split(' ')[0];
55
+ toWeekday() {
56
+ return this.value.strftime('%a')
76
57
  }
77
- }
78
58
 
79
- export const toMeridiem = (newDate: Date | string, timeZone?: string): string => {
80
- const date = new Date(newDate)
81
- if (timeZone) {
82
- return date.toLocaleString(undefined, {timeZone, hour12: true }).slice(-2).charAt(0).toLocaleLowerCase();
83
- } else {
84
- return date.toLocaleString(undefined, {hour12: true }).slice(-2).charAt(0).toLocaleLowerCase();
85
- }
86
- }
59
+ toHour() {
60
+ return this.value.strftime('%l')
61
+ }
87
62
 
88
- export const toTimeZone = (newDate: Date | string, timeZone?: string): string => {
89
- const date = new Date(newDate)
90
- if (timeZone) {
91
- return date.toLocaleString(undefined, {timeZone, timeZoneName: "short"}).split(' ')[3];
92
- } else {
93
- return date.toLocaleString(undefined, {timeZoneName: "short"}).split(' ')[3];
94
- }
95
- }
63
+ toMinute() {
64
+ return this.value.strftime('%M')
65
+ }
96
66
 
97
- export const toTimeWithMeridiem = (newDate: Date | string, timeZone: string): string => {
98
- const date = new Date(newDate)
99
- return `${toTime(date, timeZone)}${toMeridiem(date, timeZone)}`;
100
- }
67
+ toMeridian() {
68
+ return this.value.strftime('%P')[0]
69
+ }
101
70
 
102
- export const toIso = (newDate: Date | string): string => {
103
- const date = new Date(newDate)
104
- return date.toISOString()
105
- }
71
+ toIso() {
72
+ return this.value.toISOString()
73
+ }
106
74
 
107
- export const fromNow = (newDate: Date | string): string => {
108
-
109
- const startDate = new Date(newDate).getTime()
110
- const endDate = new Date().getTime()
111
- const elapsedTime = endDate - startDate
112
- let elapsedTimeString = `${Math.round(elapsedTime / (365.25 * 24 * 60 * 60 * 1000))} years ago.`; // 730+ days
113
-
114
- const elapsedTimeData = [
115
- { min: 0, max: 44999, value: "a few seconds ago" }, // 0-44 seconds
116
- { min: 45000, max: 89999, value: "a minute ago" }, // 45-89 seconds
117
- { min: 90000, max: 2649999, value: `${Math.round(elapsedTime / 60000)} minutes ago`}, // 90s-44 minutes
118
- { min: 2650000, max: 7299999, value: "an hour ago" }, // 45-120 minutes
119
- { min: 7300000, max: 75699999, value: `${Math.round(elapsedTime / 3600000)} hours ago`}, // 2-21 hours
120
- { min: 75700000, max: 172899999, value: "a day ago" }, // 22-48 hours
121
- { min: 172900000, max: 2169999999, value: `${Math.round(elapsedTime / 86400000)} days ago`}, // 2-25 days
122
- { min: 2170000000, max: 5184999999, value: "a month ago"}, // 26-60 days
123
- { min: 5185000000, max: 27561699999, value: `${Math.round(elapsedTime / 30.44 * 24 * 60 * 60 * 1000)} months ago`}, // 60-319 days
124
- { min: 27561700000, max: 63072999999, value: "a year ago"}, // 320-730 days
125
- ];
126
-
127
- for (const timeDate of elapsedTimeData) {
128
- if (elapsedTime >= timeDate.min && elapsedTime <= timeDate.max) {
129
- elapsedTimeString = timeDate.value;
130
- break;
131
- }
132
- }
133
-
134
- return elapsedTimeString
135
- }
75
+ toTime() {
76
+ const time = this.value.strftime('%I:%M')
136
77
 
137
- export const toCustomFormat = (newDate: Date | string, format = 'month_day'): string => {
138
- const date = new Date(newDate)
139
- if (format == "month_day") {
140
- return `${toMonthNum(date)}/${toDay(date)}`
141
- } else {
142
- return `${date.toLocaleString(undefined, {month: "short"})} ${toDay(date)}`
78
+ // strftime adds a leading 0 on single hour times. ie 08:31.
79
+ // this removes that 0 to match the rails kit.
80
+ return time.charAt() === '0' ? time.slice(1) : time
143
81
  }
144
- }
145
82
 
146
- export default {
147
- toMinute,
148
- toHour,
149
- toDay,
150
- toDayAbbr,
151
- toWeekday,
152
- toMonth,
153
- toMonthNum,
154
- toYear,
155
- toTime,
156
- toMeridiem,
157
- toTimeZone,
158
- toTimeWithMeridiem,
159
- toIso,
160
- fromNow,
161
- toCustomFormat,
162
- }
83
+ toTimezone() {
84
+ return this.value.strftime('%Z')
85
+ }
86
+
87
+ toTimeWithMeridian() {
88
+ return this.toTime() + this.toMeridian()
89
+ }
90
+ }
@@ -1,8 +1,8 @@
1
1
  import React from "react";
2
2
  import classnames from "classnames";
3
+ import DateTime from "../pb_kit/dateTime";
3
4
  import { buildAriaProps, buildCss, buildDataProps } from "../utilities/props";
4
5
  import { globalProps } from "../utilities/globalProps";
5
- import DateTime from '../pb_kit/dateTime';
6
6
 
7
7
  import Body from "../pb_body/_body";
8
8
  import Caption from "../pb_caption/_caption";
@@ -26,9 +26,9 @@ type LabelValueProps = {
26
26
  title?: string;
27
27
  };
28
28
 
29
- const dateString = (value: Date) => {
30
- const month = DateTime.toMonthNum(value);
31
- const day = DateTime.toDay(value);
29
+ const dateString = (value: DateTime) => {
30
+ const month = value.toMonthNum();
31
+ const day = value.toDay();
32
32
 
33
33
  return ` · ${month}/${day}`;
34
34
  };
@@ -52,6 +52,7 @@ const LabelValue = (props: LabelValueProps) => {
52
52
 
53
53
  const ariaProps = buildAriaProps(aria);
54
54
  const dataProps = buildDataProps(data);
55
+ const formattedDate = new DateTime({ value: date });
55
56
  const variantClass = variant === "details" ? "details" : "";
56
57
  const classes = classnames(
57
58
  buildCss("pb_label_value_kit", variantClass),
@@ -61,81 +62,59 @@ const LabelValue = (props: LabelValueProps) => {
61
62
 
62
63
  return (
63
64
  <div
64
- {...ariaProps}
65
- {...dataProps}
66
- className={classes}
67
- id={id}
68
- title={title}
65
+ {...ariaProps}
66
+ {...dataProps}
67
+ className={classes}
68
+ id={id}
69
+ title={title}
69
70
  >
70
- <Caption dark={dark}
71
- text={label}
72
- />
71
+ <Caption dark={dark} text={label} />
73
72
  {variant === "details" ? (
74
- <Flex inline
75
- vertical="center"
76
- >
73
+ <Flex inline vertical="center">
77
74
  {icon && (
78
- <Body color="light"
79
- dark={dark}
80
- marginRight="xs"
81
- >
82
- <Icon dark={dark}
83
- fixedWidth
84
- icon={icon}
85
- />
75
+ <Body color="light" dark={dark} marginRight="xs">
76
+ <Icon dark={dark} fixedWidth icon={icon} />
86
77
  </Body>
87
78
  )}
88
79
  {description && (
89
80
  <Body
90
- color="light"
91
- dark={dark}
92
- marginRight="xs"
93
- text={description}
81
+ color="light"
82
+ dark={dark}
83
+ marginRight="xs"
84
+ text={description}
94
85
  />
95
86
  )}
96
87
  {active === true ? (
97
- <Flex inline
98
- vertical="center"
99
- >
88
+ <Flex inline vertical="center">
100
89
  {title && (
101
- <Title dark={dark}
102
- size={4}
103
- text={title}
104
- variant="link"
105
- />
90
+ <Title dark={dark} size={4} text={title} variant="link" />
106
91
  )}
107
92
  {date && (
108
93
  <Title
109
- dark={dark}
110
- marginLeft="xs"
111
- size={4}
112
- text={" " + dateString(date)}
113
- variant="link"
94
+ dark={dark}
95
+ marginLeft="xs"
96
+ size={4}
97
+ text={" " + dateString(formattedDate)}
98
+ variant="link"
114
99
  />
115
100
  )}
116
101
  </Flex>
117
102
  ) : (
118
103
  <>
119
- {title && <Title dark={dark}
120
- size={4}
121
- text={title}
122
- />
123
- }
104
+ {title && <Title dark={dark} size={4} text={title} />}
124
105
  {date && (
125
106
  <Title
126
- dark={dark}
127
- marginLeft="xs"
128
- size={4}
129
- text={" " + dateString(date)}
107
+ dark={dark}
108
+ marginLeft="xs"
109
+ size={4}
110
+ text={" " + dateString(formattedDate)}
130
111
  />
131
112
  )}
132
113
  </>
133
114
  )}
134
115
  </Flex>
135
116
  ) : (
136
- <Body dark={dark}
137
- text={value}
138
- />
117
+ <Body dark={dark} text={value} />
139
118
  )}
140
119
  </div>
141
120
  );
@@ -0,0 +1,120 @@
1
+ /* @flow */
2
+
3
+ import React from 'react'
4
+ import classnames from 'classnames'
5
+
6
+ import DateTime from '../pb_kit/dateTime'
7
+ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
8
+ import { globalProps } from '../utilities/globalProps'
9
+
10
+ import Body from '../pb_body/_body'
11
+ import Caption from '../pb_caption/_caption'
12
+ import Icon from '../pb_icon/_icon'
13
+ import Title from '../pb_title/_title'
14
+
15
+ const dateString = (value: DateTime) => {
16
+ const month = value.toMonthNum()
17
+ const day = value.toDay()
18
+
19
+ return ` · ${month}/${day}`
20
+ }
21
+
22
+ type LogisticProps = {
23
+ aria?: object,
24
+ className?: string,
25
+ dark?: boolean,
26
+ data?: object,
27
+ date: string,
28
+ id?: string,
29
+ link?: string,
30
+ projectName?: string,
31
+ projectNumber?: number,
32
+ }
33
+
34
+ const Logistic = (props: LogisticProps) => {
35
+ const { aria = {},
36
+ className,
37
+ dark = false,
38
+ data = {},
39
+ date,
40
+ id,
41
+ link,
42
+ projectName,
43
+ projectNumber } = props
44
+
45
+ const ariaProps = buildAriaProps(aria)
46
+ const dataProps = buildDataProps(data)
47
+ const formattedDate = new DateTime({ value: date })
48
+ const classes = classnames(
49
+ buildCss('pb_logistic_kit', { dark }),
50
+ globalProps(props),
51
+ className
52
+ )
53
+
54
+ return (
55
+ <div
56
+ {...ariaProps}
57
+ {...dataProps}
58
+ className={classes}
59
+ id={id}
60
+ >
61
+ <Body color="light">
62
+ <Caption text="Project" />
63
+ <Icon
64
+ fixedWidth
65
+ icon="home"
66
+ />
67
+
68
+ {` ${projectNumber}`}
69
+
70
+ <Choose>
71
+ <When condition={link}>
72
+ <a
73
+ className="pb_logistic_kit_links"
74
+ href={link}
75
+ >
76
+ <Choose>
77
+ <When condition={date}>
78
+ <Title
79
+ size={4}
80
+ tag="span"
81
+ text={' ' + projectName + dateString(formattedDate)}
82
+ />
83
+ </When>
84
+ <Otherwise>
85
+ <Title
86
+ size={4}
87
+ tag="span"
88
+ text={' ' + projectName}
89
+ />
90
+ </Otherwise>
91
+ </Choose>
92
+ </a>
93
+ </When>
94
+ <Otherwise>
95
+ <Choose>
96
+ <When condition={date}>
97
+ <Title
98
+ dark={dark}
99
+ size={4}
100
+ tag="span"
101
+ text={' ' + projectName + dateString(formattedDate)}
102
+ />
103
+ </When>
104
+ <Otherwise>
105
+ <Title
106
+ dark={dark}
107
+ size={4}
108
+ tag="span"
109
+ text={' ' + projectName}
110
+ />
111
+ </Otherwise>
112
+ </Choose>
113
+ </Otherwise>
114
+ </Choose>
115
+ </Body>
116
+ </div>
117
+ )
118
+ }
119
+
120
+ export default Logistic