Skip to content

Commit 2a8ac6c

Browse files
Eric Huangembbnux
authored andcommitted
Create recent activities panel and recent messages tab (#297)
* create recent activity panel and recent messages view * update NavigationBar docs * update recent activity panel * create recent activity view * Update version & added to incoming call page
1 parent b79f585 commit 2a8ac6c

File tree

27 files changed

+793
-159
lines changed

27 files changed

+793
-159
lines changed

dev-server/Phone.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import ActivityMatcher from 'ringcentral-integration/modules/ActivityMatcher';
5353
import CallLogger from 'ringcentral-integration/modules/CallLogger';
5454
import ConversationMatcher from 'ringcentral-integration/modules/ConversationMatcher';
5555
import ConversationLogger from 'ringcentral-integration/modules/ConversationLogger';
56+
import RecentMessages from 'ringcentral-integration/modules/RecentMessages';
5657

5758
import RouterInteraction from '../src/modules/RouterInteraction';
5859

@@ -563,6 +564,13 @@ export default class Phone extends RcModule {
563564
getState: () => this.state.messages,
564565
}));
565566
reducers.messages = this.messages.reducer;
567+
this.addModule('recentMessages', new RecentMessages({
568+
...options,
569+
client: this.client,
570+
messageStore: this.messageStore,
571+
getState: () => this.state.recentMessages
572+
}));
573+
reducers.recentMessages = this.recentMessages.reducer;
566574
this._reducer = combineReducers({
567575
...reducers,
568576
app: (state = {

dev-server/containers/App/index.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@ import CallHistoryPage from '../../../src/containers/CallHistoryPage';
1919
import IncomingCallPage from '../../../src/containers/IncomingCallPage';
2020
import CallCtrlPage from '../../../src/containers/CallCtrlPage';
2121
import CallBadgeContainer from '../../../src/containers/CallBadgeContainer';
22-
22+
import RecentActivityContainer from '../../../src/containers/RecentActivityContainer';
2323
import MainView from '../MainView';
2424
import AppView from '../AppView';
2525

26-
2726
export default function App({
2827
phone,
2928
}) {
@@ -73,6 +72,14 @@ export default function App({
7372
callingSettingsUrl="/settings/calling"
7473
regionSettingsUrl="/settings/region"
7574
/>
75+
<RecentActivityContainer
76+
locale={phone.locale}
77+
router={phone.router}
78+
dateTimeFormat={phone.dateTimeFormat}
79+
webphone={phone.webphone}
80+
contactMatcher={phone.contactMatcher}
81+
recentMessages={phone.recentMessages}
82+
/>
7683
</IncomingCallPage>
7784
</AppView>
7885
)} >
@@ -126,7 +133,8 @@ export default function App({
126133
regionSettingsUrl="/settings/region"
127134
callingSettingsUrl="/settings/calling"
128135
/>
129-
)} />
136+
)}
137+
/>
130138
<Route
131139
path="/settings/region"
132140
component={() => (
@@ -187,7 +195,16 @@ export default function App({
187195
return avatarUrl;
188196
}
189197
}
190-
/>
198+
>
199+
<RecentActivityContainer
200+
locale={phone.locale}
201+
router={phone.router}
202+
dateTimeFormat={phone.dateTimeFormat}
203+
webphone={phone.webphone}
204+
contactMatcher={phone.contactMatcher}
205+
recentMessages={phone.recentMessages}
206+
/>
207+
</CallCtrlPage>
191208
)} />
192209
<Route
193210
path="/history"

docs/src/app/pages/Components/NavigationBar/Demo.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22
// eslint-disable-next-line
33
import NavigationBar from 'ringcentral-widget/components/NavigationBar';
4+
import TabNavigationButton from 'ringcentral-widget/components/TabNavigationButton';
45
import dynamicsFont from 'ringcentral-widget/assets/DynamicsFont/DynamicsFont.scss';
56

67
const props = {};
@@ -60,6 +61,7 @@ props.tabs = [
6061
props.goTo = (path) => alert(`go to ${path}`)
6162
const NavigationBarDemo = () => (
6263
<NavigationBar
64+
button={TabNavigationButton}
6365
{...props}
6466
/>
6567
);

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"react-router-redux": "^4.0.7",
3333
"ringcentral": "3.1.1",
3434
"ringcentral-client": "^1.0.0-rc1",
35-
"ringcentral-integration": "^0.7.0-rc8",
35+
"ringcentral-integration": "^0.7.0-rc14",
3636
"whatwg-fetch": "^2.0.1"
3737
},
3838
"devDependencies": {
@@ -84,7 +84,7 @@
8484
"redux-thunk": "^2.1.0",
8585
"ringcentral": "^3.1.1",
8686
"ringcentral-client": "^1.0.0-rc1",
87-
"ringcentral-integration": "^0.7.0-rc13",
87+
"ringcentral-integration": "^0.7.0-rc14",
8888
"sass-loader": "^6.0.5",
8989
"source-map-loader": "^0.2.1",
9090
"style-loader": "^0.18.2",

src/components/NavigationBar/index.js

Lines changed: 6 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3,67 +3,11 @@ import PropTypes from 'prop-types';
33
import classnames from 'classnames';
44
import styles from './styles.scss';
55

6-
7-
function NavigationButton({
8-
active,
9-
activeIcon,
10-
icon,
11-
label,
12-
noticeCounts,
13-
onClick,
14-
width,
15-
}) {
16-
let notice = null;
17-
if (noticeCounts && noticeCounts > 0) {
18-
if (noticeCounts > 99) {
19-
notice = <div className={styles.notices}>99+</div>;
20-
} else {
21-
notice = <div className={styles.notice}>{noticeCounts}</div>;
22-
}
23-
}
24-
return (
25-
<div
26-
onClick={onClick}
27-
className={classnames(
28-
styles.navigationButton,
29-
active && styles.active,
30-
)}
31-
style={{
32-
width,
33-
}}
34-
>
35-
<div className={styles.iconHolder} title={label}>
36-
<div className={styles.icon}>
37-
{active ? activeIcon : icon }
38-
</div>
39-
{notice}
40-
</div>
41-
</div>
42-
);
43-
}
44-
NavigationButton.propTypes = {
45-
icon: PropTypes.node.isRequired,
46-
activeIcon: PropTypes.node.isRequired,
47-
active: PropTypes.bool,
48-
label: PropTypes.string,
49-
noticeCounts: PropTypes.number,
50-
width: PropTypes.oneOfType([
51-
PropTypes.number,
52-
PropTypes.string,
53-
]).isRequired,
54-
onClick: PropTypes.func,
55-
};
56-
NavigationButton.defaultProps = {
57-
active: false,
58-
label: undefined,
59-
noticeCounts: undefined,
60-
onClick: undefined,
61-
};
62-
636
function NavigationBar(props) {
647
const tabWidth = props.tabs.length > 0 ?
658
`${(1 / props.tabs.length) * 100}%` :
669
0;
10+
const NavigationButton = props.button;
6711
return (
6812
<nav className={classnames(styles.root, props.className)}>
6913
{
@@ -87,9 +31,13 @@ function NavigationBar(props) {
8731
}
8832
NavigationBar.propTypes = {
8933
className: PropTypes.string,
34+
button: PropTypes.oneOfType([
35+
PropTypes.func.isRequired,
36+
PropTypes.element.isRequired
37+
]).isRequired,
9038
tabs: PropTypes.arrayOf(PropTypes.shape({
9139
icon: PropTypes.node.isRequired,
92-
activeIcon: PropTypes.node.isRequired,
40+
activeIcon: PropTypes.node,
9341
label: PropTypes.string,
9442
path: PropTypes.string.isRequired,
9543
isActive: PropTypes.func,
Lines changed: 0 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
@import '../../lib/commonStyles/vertical-align';
21
@import '../../lib/commonStyles/full-size';
3-
@import '../../lib/commonStyles/no-select';
42
@import '../../lib/commonStyles/colors';
53
@import '../../lib/commonStyles/layout';
64

@@ -10,93 +8,3 @@
108
box-sizing: border-box;
119
background-color: $primary-color;
1210
}
13-
14-
.tab {
15-
display: inline-block;
16-
box-sizing: border-box;
17-
height: 100%;
18-
border-style: solid;
19-
border-color: $border-color;
20-
vertical-align: top;
21-
z-index: 10;
22-
}
23-
24-
.navigationButton {
25-
@include full-size;
26-
@include no-select;
27-
outline: 0;
28-
display: inline-block;
29-
text-align: center;
30-
vertical-align: top;
31-
height: 100%;
32-
text-decoration: none;
33-
cursor: pointer;
34-
opacity: 0.8;
35-
transition: all 0.1s ease;
36-
color: #fff !important;
37-
font-size: 16px;
38-
text-decoration: none !important;
39-
}
40-
/*.navigationButton:hover {
41-
background-color: $lightergray;
42-
}*/
43-
.navigationButton:hover,
44-
.navigationButton:focus {
45-
outline: 0;
46-
opacity: 0.9;
47-
}
48-
.navigationButton.active {
49-
opacity: 1;
50-
}
51-
.iconHolder {
52-
@include full-size;
53-
}
54-
.icon {
55-
@include full-size;
56-
-webkit-font-smoothing: antialiased;
57-
-moz-osx-font-smoothing: grayscale;
58-
font-size: 1.3em;
59-
line-height: $navigation-bar-height;
60-
}
61-
.labelHolder {
62-
@include full-size;
63-
height: 35%;
64-
position: relative;
65-
}
66-
67-
.label {
68-
@include full-size;
69-
@include vertical-align(top);
70-
-webkit-font-smoothing: antialiased;
71-
-moz-osx-font-smoothing: grayscale;
72-
font-size: 0.7em;
73-
}
74-
75-
.notice {
76-
position: absolute;
77-
bottom: 1.9em;
78-
right: calc(50% - 1.6em);
79-
width: 1.4em;
80-
height: 1.4em;
81-
border-radius: 100%;
82-
line-height: 1.4em;
83-
font-family: Lato;
84-
text-align: center;
85-
font-size: 0.7em;
86-
background-color: #f65d60;
87-
overflow: hidden;
88-
}
89-
.notices {
90-
position: absolute;
91-
bottom: 2em;
92-
right: calc(50% - 2em);
93-
width: 2.1em;
94-
height: 1.5em;
95-
border-radius: 3em;
96-
line-height: 1.5em;
97-
font-family: Lato;
98-
text-align: center;
99-
font-size: 0.6em;
100-
background-color: #f65d60;
101-
overflow: hidden;
102-
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
noRecords: 'No recent records found.',
3+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import I18n from 'ringcentral-integration/lib/I18n';
2+
import loadLocale from './loadLocale';
3+
4+
export default new I18n(loadLocale);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/* loadLocale */
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import classNames from 'classnames/bind';
4+
import Spinner from '../Spinner';
5+
import styles from './styles.scss';
6+
import i18n from './i18n';
7+
8+
const cx = classNames.bind(styles);
9+
function MessageItem({ message, navigateTo, dateTimeFormatter }) {
10+
const { subject, lastModifiedTime, readStatus, conversationId } = message;
11+
const isUnread = readStatus !== 'Read';
12+
const time = dateTimeFormatter({ utcTimestamp: lastModifiedTime });
13+
return (
14+
<div
15+
className={cx('messageItem', { localMessageItem: !message.fromRemote })}
16+
onClick={() => !message.fromRemote && navigateTo(`conversations/${conversationId}`)}
17+
>
18+
<dl className={styles.dl}>
19+
<dt className={cx('messageSubject', { unread: isUnread })} title={subject}>{subject}</dt>
20+
<dd className={cx('messageTime', { unread: isUnread })} title={time}>{time}</dd>
21+
</dl>
22+
</div>
23+
);
24+
}
25+
26+
MessageItem.propTypes = {
27+
message: PropTypes.object.isRequired,
28+
navigateTo: PropTypes.func.isRequired,
29+
dateTimeFormatter: PropTypes.func.isRequired
30+
};
31+
32+
export default function RecentActivityMessages({
33+
currentLocale,
34+
messages,
35+
isMessagesLoaded,
36+
navigateTo,
37+
dateTimeFormatter
38+
}) {
39+
let messageListView = null;
40+
if (!isMessagesLoaded) {
41+
messageListView = (<Spinner className={styles.spinner} ringWidth={4} />);
42+
} else if (messages.length > 0) {
43+
messageListView = messages.map(message => (
44+
<MessageItem
45+
key={message.id}
46+
message={message}
47+
navigateTo={navigateTo}
48+
dateTimeFormatter={dateTimeFormatter}
49+
/>
50+
));
51+
} else {
52+
messageListView = (<p className={styles.noRecords}>{i18n.getString('noRecords', currentLocale)}</p>);
53+
}
54+
return (
55+
<div className={styles.messages}>
56+
{ messageListView }
57+
</div>
58+
);
59+
}
60+
61+
RecentActivityMessages.propTypes = {
62+
currentLocale: PropTypes.string.isRequired,
63+
messages: PropTypes.array.isRequired,
64+
isMessagesLoaded: PropTypes.bool.isRequired,
65+
navigateTo: PropTypes.func.isRequired,
66+
dateTimeFormatter: PropTypes.func.isRequired
67+
};

0 commit comments

Comments
 (0)