Skip to content

Commit 892e56e

Browse files
authored
Added timestampFormat to default style options (#2295)
* Added timestampConfig to default style options * Updated CHANGELOG.md * Fixed eslint issue in AbsoluteTime component * Added storeDefaultState to test harness * Updated CHANGELOG.md * Changed timestampConfig to timestampFormat * Change storeDefaultState to storeInitialState Co-Authored-By: William Wong <[email protected]> * Change storeDefaultState to storeInitialState Co-Authored-By: William Wong <[email protected]> * Nitpicking changes * Fixed absolute timestamp test * Fixed undefined timestamp issue
1 parent 0ebc227 commit 892e56e

7 files changed

Lines changed: 94 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
8787
- [`MessageChannel`](https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel)/[`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort)
8888
- [`OffscreenCanvas`](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas)
8989
- Specifically [`OffscreenCanvas.getContext('2d')`](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas/getContext)
90+
- Added `timestampFormat` option to the default style options and created `AbsoluteTime` component, by [@tdurnford](https://github.com/tdurnford), in PR [#2295](https://github.com/microsoft/BotFramework-WebChat/pull/2295)
9091

9192
### Samples
9293

18.1 KB
Loading

__tests__/basic.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,51 @@ test('thumbnail card with a long title and richCardWrapTitle set to default valu
144144

145145
expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions);
146146
});
147+
148+
test('absolute timestamp', async () => {
149+
const activities = [
150+
{
151+
type: 'message',
152+
id: '6266x5ZXhXkBfuIH0fNx0h-o|0000000',
153+
timestamp: '2019-08-08T16:41:12.9397263Z',
154+
from: {
155+
id: 'dl_654b35e09ab4149595a70aa6f1af6f50',
156+
name: '',
157+
role: 'user'
158+
},
159+
textFormat: 'plain',
160+
text: 'echo "Hello, World!"'
161+
},
162+
{
163+
type: 'message',
164+
id: '6266x5ZXhXkBfuIH0fNx0h-o|0000001',
165+
timestamp: '2019-08-08T16:41:13.1835518Z',
166+
from: {
167+
id: 'webchat-mockbot',
168+
name: 'webchat-mockbot',
169+
role: 'bot'
170+
},
171+
text: 'Echoing back in a separate activity.'
172+
},
173+
{
174+
type: 'message',
175+
id: '6266x5ZXhXkBfuIH0fNx0h-o|0000002',
176+
timestamp: '2019-08-08T16:41:13.3963019Z',
177+
from: {
178+
id: 'webchat-mockbot',
179+
name: 'webchat-mockbot',
180+
role: 'bot'
181+
},
182+
text: 'Hello, World!'
183+
}
184+
];
185+
const styleOptions = { timestampFormat: 'absolute' };
186+
const { driver } = await setupWebDriver({ storeInitialState: { activities }, props: { styleOptions } });
187+
188+
await driver.wait(uiConnected(), timeouts.directLine);
189+
await driver.wait(minNumActivitiesShown(3), timeouts.directLine);
190+
191+
const base64PNG = await driver.takeScreenshot();
192+
193+
expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions);
194+
});

__tests__/setup/web/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
const PASSTHRU_MIDDLEWARE = store => next => action => next(action);
9393

9494
async function main(options) {
95-
let { createDirectLine, createStyleSet, props, setup, storeMiddleware = PASSTHRU_MIDDLEWARE } = unmarshal(options);
95+
let { createDirectLine, createStyleSet, props, setup, storeInitialState = {}, storeMiddleware = PASSTHRU_MIDDLEWARE } = unmarshal(options);
9696

9797
props = unmarshal(props);
9898

@@ -113,7 +113,7 @@
113113
}
114114
}, 3);
115115

116-
const store = window.WebChatTest.store = window.WebChat.createStore({}, store => {
116+
const store = window.WebChatTest.store = window.WebChat.createStore(storeInitialState, store => {
117117
const setupMiddleware = storeMiddleware(store);
118118

119119
return next => {

packages/component/src/Activity/Timestamp.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,25 @@ import classNames from 'classnames';
22
import PropTypes from 'prop-types';
33
import React from 'react';
44

5+
import AbsoluteTime from '../Utils/AbsoluteTime';
56
import connectToWebChat from '../connectToWebChat';
67
import RelativeTime from '../Utils/RelativeTime';
78

8-
const Timestamp = ({ activity: { timestamp }, className, styleSet }) => (
9-
<span className={classNames(styleSet.timestamp + '', (className || '') + '')}>
10-
<RelativeTime value={timestamp} />
11-
</span>
12-
);
9+
const Timestamp = ({ activity: { timestamp }, className, styleSet }) => {
10+
if (!timestamp) {
11+
return false;
12+
}
13+
14+
return (
15+
<span className={classNames(styleSet.timestamp + '', (className || '') + '')}>
16+
{styleSet.options.timestampFormat === 'relative' ? (
17+
<RelativeTime value={timestamp} />
18+
) : (
19+
<AbsoluteTime value={timestamp} />
20+
)}
21+
</span>
22+
);
23+
};
1324

1425
Timestamp.defaultProps = {
1526
className: ''

packages/component/src/Styles/defaultStyleOptions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ const DEFAULT_OPTIONS = {
9999

100100
// Timestamp
101101
timestampColor: DEFAULT_SUBTLE,
102+
timestampFormat: 'relative', // 'absolute'
102103

103104
// Transcript overlay buttons (e.g. carousel and suggested action flippers, scroll to bottom, etc.)
104105
transcriptOverlayButtonBackground: 'rgba(0, 0, 0, .6)',
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* eslint react/no-unsafe: off */
2+
3+
import PropTypes from 'prop-types';
4+
import React from 'react';
5+
6+
import { getLocaleString, localize } from '../Localization/Localize';
7+
import connectToWebChat from '../connectToWebChat';
8+
import ScreenReaderText from '../ScreenReaderText';
9+
10+
const AbsoluteTime = ({ language, value }) => {
11+
const localizedTime = getLocaleString(value, language);
12+
13+
return (
14+
<React.Fragment>
15+
<ScreenReaderText text={localize('SentAt', language) + localizedTime} />
16+
<span aria-hidden={true}>{localizedTime}</span>
17+
</React.Fragment>
18+
);
19+
};
20+
21+
AbsoluteTime.propTypes = {
22+
language: PropTypes.string.isRequired,
23+
value: PropTypes.string.isRequired
24+
};
25+
26+
export default connectToWebChat(({ language }) => ({ language }))(AbsoluteTime);

0 commit comments

Comments
 (0)