d2-ui
Version:
189 lines (163 loc) • 7.36 kB
JavaScript
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
import { createClass, PropTypes, default as React } from 'react';
import TextField from 'material-ui/TextField';
import Action from '../action/Action';
import { Observable, helpers, Scheduler, default as Rx } from 'rx';
import { config } from 'd2/lib/d2';
import d2Lib from 'd2/lib/d2';
import List from 'material-ui/List/List';
import ListItem from 'material-ui/List/ListItem';
import Paper from 'material-ui/Paper';
import Translate from '../i18n/Translate.mixin';
import log from 'loglevel';
config.i18n.strings.add('members');
config.i18n.strings.add('search_for_user_groups');
function searchByForModel(searchBy, modelTypeToSearch, valueToSearchFor) {
var options = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];
if (!Boolean(modelTypeToSearch) || !Boolean(valueToSearchFor)) {
log.warn('forType property and value should be provided to be able to show results');
return Observable.just([]);
}
var searchQueryRequest = d2Lib.getInstance().then(function (d2) {
return d2.models[modelTypeToSearch];
}).then(function (modelType) {
return modelType.filter().on(searchBy).ilike(valueToSearchFor);
}).then(function (modelTypeWithFilter) {
return modelTypeWithFilter.list(options);
}).then(function (collection) {
return collection.toArray();
}).catch(function (error) {
return log.error(error);
});
return Observable.fromPromise(searchQueryRequest);
}
export default createClass({
propTypes: {
actions: PropTypes.object,
forType: PropTypes.string.isRequired,
onSuggestionClicked: PropTypes.func.isRequired,
closeOnItemClicked: PropTypes.bool,
clearValueOnItemClicked: PropTypes.bool,
filterForSuggestions: PropTypes.func
},
mixins: [Translate],
getDefaultProps: function getDefaultProps() {
return {
actions: Action.createActionsFromNames(['loadAutoCompleteSuggestions']),
debounceTime: 500,
propertyToSearchBy: 'displayName',
scheduler: Scheduler.default,
closeOnItemClicked: true,
clearValueOnItemClicked: true
};
},
//
getInitialState: function getInitialState() {
return {
showAutoComplete: false,
autoCompleteValues: [],
loadingSuggestions: false
};
},
componentWillMount: function componentWillMount() {
var _this = this;
var _props = this.props;
var actions = _props.actions;
var forType = _props.forType;
this.disposable = actions.loadAutoCompleteSuggestions.map(function (_ref) {
var event = _ref.data;
return event.target.value;
}).tap(function (value) {
return _this.setState({
loadingSuggestions: true,
showAutoComplete: Boolean(value)
});
}).debounce(this.props.debounceTime, this.props.scheduler).distinctUntilChanged()
// TODO: Do not hardcore these fields to search for
.map(function (valueToSearchFor) {
return searchByForModel(_this.props.propertyToSearchBy, forType, valueToSearchFor, { fields: 'id,displayName|rename(name),users::size', pageSize: 10 });
}).concatAll().map(function (suggestions) {
return Array.isArray(suggestions) ? suggestions.filter(_this.props.filterForSuggestions || helpers.identity) : [];
}).map(function (suggestions) {
return suggestions.slice(0, 5);
}).subscribe(function (autoCompleteValues) {
return _this.setState({
autoCompleteValues: autoCompleteValues,
loadingSuggestions: false
});
}, function (errorMessage) {
return log.error(errorMessage);
});
},
componentWillUnmount: function componentWillUnmount() {
this.disposable && this.disposable.dispose();
},
onSuggestionClick: function onSuggestionClick(item) {
var _this2 = this;
return function (event) {
var _props2 = _this2.props;
var closeOnItemClicked = _props2.closeOnItemClicked;
var clearValueOnItemClicked = _props2.clearValueOnItemClicked;
var onSuggestionClicked = _props2.onSuggestionClicked;
if (closeOnItemClicked) {
_this2.refs.autoCompleteField.focus();
}
if (clearValueOnItemClicked) {
_this2.refs.autoCompleteField.setValue('');
_this2.props.actions.loadAutoCompleteSuggestions({
target: { value: '' }
});
}
_this2.setState({
showAutoComplete: !closeOnItemClicked
});
if (onSuggestionClicked) {
onSuggestionClicked(item, event);
}
};
},
// TODO: Allow the component user to specify how to render the list items or at least the primary and secondary texts
renderAutoCompleteSuggestions: function renderAutoCompleteSuggestions() {
var _this3 = this;
return React.createElement(
'div',
{ style: { position: 'absolute', zIndex: 100 } },
React.createElement(
Paper,
null,
React.createElement(
List,
null,
this.state.autoCompleteValues.map(function (userGroup) {
return React.createElement(ListItem, {
primaryText: userGroup.name,
secondaryText: userGroup.users + ' ' + _this3.getTranslation('members'),
innerDivStyle: { paddingTop: '.5rem', paddingBottom: '.5rem' },
onClick: _this3.onSuggestionClick(userGroup)
});
})
)
)
);
},
render: function render() {
var _props3 = this.props;
var actions = _props3.actions;
var forType = _props3.forType;
var other = _objectWithoutProperties(_props3, ['actions', 'forType']);
return React.createElement(
'div',
{ style: { position: 'relative' }, onClick: function onClick(event) {
return event.stopPropagation();
} },
React.createElement(TextField, _extends({
ref: 'autoCompleteField' }, other, {
onChange: actions.loadAutoCompleteSuggestions,
hintText: this.getTranslation('search_for_user_groups'),
fullWidth: true
})),
this.state.showAutoComplete && !this.state.loadingSuggestions ? this.renderAutoCompleteSuggestions() : null
);
}
});