wire up searchbox filtering, and some minor overall tweaks
This commit is contained in:
parent
90ae024a4e
commit
26d12bebe4
5 changed files with 92 additions and 24 deletions
|
@ -31,6 +31,7 @@ var LeftPanel = React.createClass({
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
showCallElement: null,
|
showCallElement: null,
|
||||||
|
searchFilter: '',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -84,6 +85,10 @@ var LeftPanel = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onSearch: function(term) {
|
||||||
|
this.setState({ searchFilter: term });
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var RoomList = sdk.getComponent('rooms.RoomList');
|
var RoomList = sdk.getComponent('rooms.RoomList');
|
||||||
var BottomLeftMenu = sdk.getComponent('structures.BottomLeftMenu');
|
var BottomLeftMenu = sdk.getComponent('structures.BottomLeftMenu');
|
||||||
|
@ -111,12 +116,13 @@ var LeftPanel = React.createClass({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className={classes} style={{ opacity: this.props.opacity }}>
|
<aside className={classes} style={{ opacity: this.props.opacity }}>
|
||||||
<SearchBox collapsed={ this.props.collapsed } />
|
<SearchBox collapsed={ this.props.collapsed } onSearch={ this.onSearch } />
|
||||||
{ collapseButton }
|
{ collapseButton }
|
||||||
{ callPreview }
|
{ callPreview }
|
||||||
<RoomList
|
<RoomList
|
||||||
selectedRoom={this.props.selectedRoom}
|
selectedRoom={this.props.selectedRoom}
|
||||||
collapsed={this.props.collapsed}
|
collapsed={this.props.collapsed}
|
||||||
|
searchFilter={this.state.searchFilter}
|
||||||
ConferenceHandler={VectorConferenceHandler} />
|
ConferenceHandler={VectorConferenceHandler} />
|
||||||
<BottomLeftMenu collapsed={this.props.collapsed}/>
|
<BottomLeftMenu collapsed={this.props.collapsed}/>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
|
@ -65,16 +65,12 @@ var RoomSubList = React.createClass({
|
||||||
selectedRoom: React.PropTypes.string.isRequired,
|
selectedRoom: React.PropTypes.string.isRequired,
|
||||||
startAsHidden: React.PropTypes.bool,
|
startAsHidden: React.PropTypes.bool,
|
||||||
showSpinner: React.PropTypes.bool, // true to show a spinner if 0 elements when expanded
|
showSpinner: React.PropTypes.bool, // true to show a spinner if 0 elements when expanded
|
||||||
|
collapsed: React.PropTypes.bool.isRequired, // is LeftPanel collapsed?
|
||||||
// TODO: Fix the name of this. This is too easily confused with the
|
|
||||||
// "hidden" state which is the expanded (or not) view of the list of rooms.
|
|
||||||
// What this prop *really* does is control whether the room name is displayed
|
|
||||||
// so it should be named as such.
|
|
||||||
collapsed: React.PropTypes.bool.isRequired,
|
|
||||||
onHeaderClick: React.PropTypes.func,
|
onHeaderClick: React.PropTypes.func,
|
||||||
alwaysShowHeader: React.PropTypes.bool,
|
alwaysShowHeader: React.PropTypes.bool,
|
||||||
incomingCall: React.PropTypes.object,
|
incomingCall: React.PropTypes.object,
|
||||||
onShowMoreRooms: React.PropTypes.func
|
onShowMoreRooms: React.PropTypes.func,
|
||||||
|
searchFilter: React.PropTypes.string,
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
@ -93,13 +89,20 @@ var RoomSubList = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
this.sortList(this.props.list, this.props.order);
|
this.sortList(this.applySearchFilter(this.props.list, this.props.searchFilter), this.props.order);
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillReceiveProps: function(newProps) {
|
componentWillReceiveProps: function(newProps) {
|
||||||
// order the room list appropriately before we re-render
|
// order the room list appropriately before we re-render
|
||||||
//if (debug) console.log("received new props, list = " + newProps.list);
|
//if (debug) console.log("received new props, list = " + newProps.list);
|
||||||
this.sortList(newProps.list, newProps.order);
|
this.sortList(this.applySearchFilter(newProps.list, newProps.searchFilter), newProps.order);
|
||||||
|
},
|
||||||
|
|
||||||
|
applySearchFilter: function(list, filter) {
|
||||||
|
if (filter === "") return list;
|
||||||
|
return list.filter((room) => {
|
||||||
|
return room.name && room.name.toLowerCase().indexOf(filter.toLowerCase()) >= 0
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onClick: function(ev) {
|
onClick: function(ev) {
|
||||||
|
|
|
@ -19,32 +19,78 @@ limitations under the License.
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
var sdk = require('matrix-react-sdk')
|
var sdk = require('matrix-react-sdk')
|
||||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||||
|
var rate_limited_func = require('matrix-react-sdk/lib/ratelimitedfunc');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'SearchBox',
|
displayName: 'SearchBox',
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
collapsed: React.PropTypes.bool,
|
||||||
|
onSearch: React.PropTypes.func,
|
||||||
|
},
|
||||||
|
|
||||||
|
onChange: new rate_limited_func(
|
||||||
|
function() {
|
||||||
|
if (this.refs.search) {
|
||||||
|
this.props.onSearch(this.refs.search.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
100
|
||||||
|
),
|
||||||
|
|
||||||
|
onToggleCollapse: function(show) {
|
||||||
|
if (show) {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'show_left_panel',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'hide_left_panel',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var TintableSvg = sdk.getComponent('elements.TintableSvg');
|
var TintableSvg = sdk.getComponent('elements.TintableSvg');
|
||||||
|
|
||||||
var toggleCollapse;
|
var toggleCollapse;
|
||||||
if (this.props.collapsed) {
|
if (this.props.collapsed) {
|
||||||
toggleCollapse = <img className="mx_SearchBox_maximise" src="img/maximise.svg" width="10" height="16" alt="<"/>;
|
toggleCollapse =
|
||||||
|
<div className="mx_SearchBox_maximise" onClick={ this.onToggleCollapse.bind(this, true) }>
|
||||||
|
<TintableSvg src="img/maximise.svg" width="10" height="16" alt="<"/>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
toggleCollapse = <img className="mx_SearchBox_minimise" src="img/minimise.svg" width="10" height="16" alt="<"/>;
|
toggleCollapse =
|
||||||
|
<div className="mx_SearchBox_minimise" onClick={ this.onToggleCollapse.bind(this, false) }>
|
||||||
|
<TintableSvg src="img/minimise.svg" width="10" height="16" alt="<"/>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
var searchControls;
|
||||||
<div className="mx_SearchBox">
|
if (!this.props.collapsed) {
|
||||||
|
searchControls = [
|
||||||
<TintableSvg
|
<TintableSvg
|
||||||
|
key="button"
|
||||||
className="mx_SearchBox_searchButton"
|
className="mx_SearchBox_searchButton"
|
||||||
src="img/search.svg" width="21" height="19"
|
src="img/search.svg" width="21" height="19"
|
||||||
/>
|
/>,
|
||||||
<input
|
<input
|
||||||
|
key="searchfield"
|
||||||
type="text"
|
type="text"
|
||||||
|
ref="search"
|
||||||
className="mx_SearchBox_search"
|
className="mx_SearchBox_search"
|
||||||
placeholder="Search Vector"
|
onChange={ this.onChange }
|
||||||
|
placeholder="Search room names"
|
||||||
/>
|
/>
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
return (
|
||||||
|
<div className="mx_SearchBox">
|
||||||
|
{ searchControls }
|
||||||
{ toggleCollapse }
|
{ toggleCollapse }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -15,9 +15,9 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.mx_RoomStatusBar {
|
.mx_RoomStatusBar {
|
||||||
margin-top: 12px;
|
margin-top: 15px;
|
||||||
margin-left: 65px;
|
margin-left: 65px;
|
||||||
min-height: 37px;
|
min-height: 34px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* position the indicator in the same place horizontally as .mx_EventTile_avatar. */
|
/* position the indicator in the same place horizontally as .mx_EventTile_avatar. */
|
||||||
|
@ -33,8 +33,9 @@ limitations under the License.
|
||||||
.mx_RoomStatusBar_placeholderIndicator span {
|
.mx_RoomStatusBar_placeholderIndicator span {
|
||||||
color: #4a4a4a;
|
color: #4a4a4a;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
/*
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
top: -4px;
|
||||||
|
/*
|
||||||
animation-duration: 1s;
|
animation-duration: 1s;
|
||||||
animation-name: bounce;
|
animation-name: bounce;
|
||||||
animation-direction: alternate;
|
animation-direction: alternate;
|
||||||
|
|
|
@ -45,5 +45,17 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_SearchBox_minimise,
|
.mx_SearchBox_minimise,
|
||||||
.mx_SearchBox_maximise {
|
.mx_SearchBox_maximise {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_SearchBox_minimise {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_SearchBox_maximise {
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_SearchBox object {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue