Skip to content

Commit 543fe75

Browse files
authored
Enhance conversation ui (#142)
* enhance conversation ui * show selected matched name * support hot key on recipients input
1 parent 2fdbf31 commit 543fe75

File tree

13 files changed

+151
-33
lines changed

13 files changed

+151
-33
lines changed

src/components/ComposeTextPanel/index.js

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,6 @@ class ComposeTextPanel extends Component {
5757
this.props.cleanTypingToNumber();
5858
};
5959

60-
this.onReceiverInputKeyDown = (e) => {
61-
if (e.key === ',' || e.key === ';' || e.key === 'Enter') {
62-
e.preventDefault();
63-
if (this.props.typingToNumber.length === 0) {
64-
return;
65-
}
66-
this.props.addToNumber({
67-
name: this.props.typingToNumber,
68-
phoneNumber: this.props.typingToNumber,
69-
});
70-
this.props.cleanTypingToNumber();
71-
}
72-
};
73-
7460
this.onReceiverInputKeyUp = (e) => {
7561
this.props.searchContact(e.currentTarget.value);
7662
};
@@ -156,7 +142,6 @@ class ComposeTextPanel extends Component {
156142
removeFromRecipients={this.removeFromRecipients}
157143
searchContactList={this.props.searchContactList}
158144
onKeyUp={this.onReceiverInputKeyUp}
159-
onKeyDown={this.onReceiverInputKeyDown}
160145
formatContactPhone={this.props.formatContactPhone}
161146
/>
162147
</div>

src/components/ContactDropdownList/index.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ import styles from './styles.scss';
55
import phoneTypes from '../../lib/phoneTypes';
66

77
function ContactItem(props) {
8+
const className = classnames(
9+
styles.contactItem,
10+
props.active ? styles.active : null,
11+
);
812
return (
9-
<li className={styles.contactItem}>
13+
<li className={className} onMouseOver={props.onHover}>
1014
<a href="#select-contact-item" onClick={props.onClick}>
1115
<div>
1216
<span className={styles.name}>
@@ -38,10 +42,16 @@ ContactItem.propTypes = {
3842
entityType: PropTypes.string.isRequired,
3943
phoneType: PropTypes.string.isRequired,
4044
phoneNumber: PropTypes.string.isRequired,
45+
active: PropTypes.bool.isRequired,
46+
onHover: PropTypes.func.isRequired,
4147
};
4248

4349
function ContactDropdownList(props) {
44-
const items = props.items;
50+
let items = props.items;
51+
// MAX 5
52+
if (items.length > 5) {
53+
items = items.slice(0, 5);
54+
}
4555
let listClassName = null;
4656
let hiddenClassName = null;
4757
if (items.length === 0 || !props.visibility) {
@@ -51,13 +61,15 @@ function ContactDropdownList(props) {
5161
return (
5262
<ul className={listClassName}>
5363
{
54-
items.map(item => (
64+
items.map((item, index) => (
5565
<ContactItem
66+
active={props.selectedIndex === index}
5667
name={item.name}
5768
entityType={item.entityType}
5869
phoneType={item.phoneType}
5970
phoneNumber={item.phoneNumber}
6071
formatContactPhone={props.formatContactPhone}
72+
onHover={() => props.setSelectedIndex(index)}
6173
onClick={() => props.addToRecipients({
6274
name: item.name,
6375
phoneNumber: item.phoneNumber,
@@ -81,6 +93,8 @@ ContactDropdownList.propTypes = {
8193
})).isRequired,
8294
formatContactPhone: PropTypes.func.isRequired,
8395
addToRecipients: PropTypes.func.isRequired,
96+
active: PropTypes.bool.isRequired,
97+
setSelectedIndex: PropTypes.func.isRequired,
8498
};
8599

86100
ContactDropdownList.defaultProps = {

src/components/ContactDropdownList/styles.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
border: 1px solid #efefef;
2828
border-radius: 4px;
2929
box-shadow: 0 4px 12px rgba(0,0,0,.175);
30-
max-height: 200px;
30+
max-height: 265px;
3131
overflow-y: auto;
3232
overflow-x: hidden;
3333

@@ -40,7 +40,7 @@
4040
}
4141
}
4242

43-
li:hover {
43+
li.active {
4444
color: $rc-blue;
4545

4646
.name {

src/components/ConversationMessageList/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ function MessageItem(props) {
77
const messageClassName = classnames(
88
styles.messageBody,
99
props.direction === 'Outbound' ? styles.outbound : styles.inbound,
10+
props.subject && props.subject.length > 500 ? styles.big : null,
1011
);
1112
const fromName = props.senderName && props.direction === 'Inbound' ?
1213
(

src/components/ConversationMessageList/styles.scss

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
position: relative;
4343
display: inline-block;
4444
margin-bottom: 10px;
45-
width: 60%;
45+
min-width: 50%;
46+
max-width: 60%;
4647
text-align: left;
4748
word-break: break-word;
4849
hyphens: auto;
@@ -115,6 +116,11 @@
115116
}
116117
}
117118

119+
.messageBody.big {
120+
width: 85%;
121+
max-width: 85%;
122+
}
123+
118124
.clear {
119125
clear: both;
120126
margin: 0;

src/components/ConversationPanel/styles.scss

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@
8686
}
8787

8888
.submitButton:disabled {
89-
background-color: #888888!important;
89+
background-color: #fff!important;
90+
border: #c9c9c9 1px solid;
91+
color: #a9a9a9;
9092
}
9193

9294
.spinerContainer {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export default {
2-
selectMatchedName: 'Select a matching record'
2+
selectMatchedName: 'Select a record'
33
};

src/components/RecipientHeader/index.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React, { PropTypes, Component } from 'react';
22
import classnames from 'classnames';
33

4+
import dynamicsFont from '../../assets/DynamicsFont/DynamicsFont.scss';
5+
46
import styles from './styles.scss';
57
import i18n from './i18n';
68

@@ -27,6 +29,17 @@ function MatchedNameList(props) {
2729
const matchedNames = props.matchedNames;
2830
return (
2931
<div className={props.className}>
32+
{
33+
this.props.isSelected ?
34+
<RecipientName
35+
name={i18n.getString('selectMatchedName', this.props.currentLocale)}
36+
className={styles.noClick}
37+
onClick={
38+
() => null
39+
}
40+
/> :
41+
null
42+
}
3043
{
3144
matchedNames.map(matchedName => (
3245
<RecipientName
@@ -43,6 +56,8 @@ function MatchedNameList(props) {
4356
}
4457

4558
MatchedNameList.propTypes = {
59+
currentLocale: PropTypes.string.isRequired,
60+
isSelected: PropTypes.bool.isRequired,
4661
className: PropTypes.string.isRequired,
4762
matchedNames: PropTypes.arrayOf(PropTypes.string).isRequired,
4863
};
@@ -95,12 +110,14 @@ class RecipientHeader extends Component {
95110
}
96111
const phoneNumber = recipient.phoneNumber || recipient.extensionNumber;
97112
let matchedNames = this.context.getMatcherContactList(phoneNumber);
98-
let defaultRecipient = i18n.getString('selectMatchedName', this.props.currentLocale);
113+
let defaultRecipient = matchedNames.join('&');
99114
// if it have old data
115+
let isSelected = false;
100116
if (recipient.matchedNames && recipient.matchedNames[0]) {
101117
const firstMatchedName = recipient.matchedNames[0];
102118
const isFind = matchedNames.find(name => name === firstMatchedName);
103119
if (isFind) {
120+
isSelected = true;
104121
defaultRecipient = firstMatchedName;
105122
}
106123
const oldMatchedNames = recipient.matchedNames.slice().sort();
@@ -115,11 +132,16 @@ class RecipientHeader extends Component {
115132
onClick={this.toggleDropdown}
116133
className={styles.dropdownButton}
117134
/>
118-
{this.props.dropdownIcon}
135+
<i
136+
className={classnames(dynamicsFont.arrow, styles.dropdownIcon)}
137+
onClick={this.toggleDropdown}
138+
/>
119139
<MatchedNameList
120140
matchedNames={matchedNames}
121141
className={dropdownClass}
122142
setDefaultMatchedName={this.setDefaultMatchedName}
143+
isSelected={isSelected}
144+
currentLocale={this.props.currentLocale}
123145
/>
124146
</div>
125147
);
@@ -134,7 +156,6 @@ RecipientHeader.propTypes = {
134156
matchedNames: PropTypes.array,
135157
}).isRequired,
136158
currentLocale: PropTypes.string.isRequired,
137-
dropdownIcon: PropTypes.node.isRequired,
138159
dropdownClassName: PropTypes.string.isRequired,
139160
};
140161

src/components/RecipientHeader/styles.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@
2626
}
2727
}
2828

29+
.noClick {
30+
cursor: default;
31+
&:hover {
32+
background: transparent;
33+
}
34+
}
35+
2936
.active {
3037
display: block!important;
3138
}
@@ -37,3 +44,11 @@
3744
background: transparent;
3845
}
3946
}
47+
48+
.dropdownIcon {
49+
font-size: 12px;
50+
position: absolute;
51+
top: 12px;
52+
right: 0;
53+
cursor: pointer;
54+
}

src/components/RecipientsHeader/index.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,13 @@ class RecipientsHeader extends Component {
7575
if (recipients.length === 0) {
7676
return null;
7777
}
78-
const dropdownIcon = (
79-
<i className={classnames(dynamicsFont.arrow, styles.dropdownIcon)} />
80-
);
8178
let dropdownClass = styles.dropdownList;
8279
if (recipients.length === 1) {
8380
return (
8481
<h1 className={styles.container}>
8582
<RecipientHeader
8683
recipient={recipients[0]}
8784
currentLocale={this.props.currentLocale}
88-
dropdownIcon={dropdownIcon}
8985
dropdownClassName={dropdownClass}
9086
/>
9187
</h1>
@@ -101,7 +97,10 @@ class RecipientsHeader extends Component {
10197
name={this.context.getRecipientName(defaultRecipient)}
10298
onClick={this.toggleDropdown}
10399
/>
104-
{dropdownIcon}
100+
<i
101+
className={classnames(dynamicsFont.arrow, styles.dropdownIcon)}
102+
onClick={this.toggleDropdown}
103+
/>
105104
<RecipientList
106105
recipients={recipients}
107106
className={dropdownClass}

0 commit comments

Comments
 (0)