UNPKG

instantjob-recruiter-client

Version:

a set of tools for creating an instantjob recruiter react client

254 lines (234 loc) 7.75 kB
import React, {Component} from 'react' import classNames from 'classnames/bind' import {MdCheck} from 'react-icons/lib/md' import {color} from '../common/constants' import {array_contains, hash_with_key} from '../common/utilities' import auto_bind from '../common/auto_bind' import Button from 'components/utils/button' import SearchBar from './search_bar' import Hover from 'components/utils/hover' import Field from './field' import {new_values_fuse, action_create_value} from '../common/fields' import store from '../common/store' import {alert_failure} from '../actions/display' let cx = classNames.bind(require('../styles/field.scss')) class NonExclusiveField extends Component { constructor(props) { super(props) this.state = { comment: props.comment, active: false, query: "", results: [], } auto_bind(this) } componentDidMount() { this.mounted = true if (this.should_set_state) { this.setState(this.should_set_state) this.should_set_state = false } } componentWillUnmount() { this.mounted = false } on_query_change(query, results) { if (this.mounted) { this.setState({query, results}) } else { this.should_set_state = {query, results} } } create_value() { this.search_bar.set_query("") this.props.create_value(this.state.query) .then((id) => { this.props.on_select_value(id) }, () => {}) } get_default_results() { return this.props.values.sort((a, b) => a.name.localeCompare(b.name)).map((value) => value.id) } deactivate() { this.setState({active: false}) } activate() { this.setState({active: true}) this.focus_search_bar() } focus_search_bar() { setTimeout(() => { if (this.mounted && this.search_bar) { this.search_bar.focus() } }) } toggle_selected(selected, value_id) { return () => { this.should_blur = false this.focus_search_bar() if (selected) { this.props.on_deselect_value(value_id) } else { this.props.on_select_value(value_id) } } } render_hoverable(hover) { let editing = this.state.active && this.props.editable let use_ellipsis = !hover && !editing let {selected_values} = this.props if (this.props.ellipsis && use_ellipsis) { selected_values = selected_values.slice(0, this.props.ellipsis) } let values_hash = hash_with_key(this.props.values) let displayed_value_ids = this.props.searchable ? this.state.results : this.get_default_results() return ( <div> <div tabIndex={0} onFocus={this.activate} className={cx('field__display', {'field__display_empty': this.props.selected_values.length == 0, 'field__display_magnify': hover || editing})} > {this.props.selected_values.length == 0 ? ( <div className={cx('field__label', {'field__label_ellipsis': this.props.field_ellipsis})} style={this.props.field_ellipsis ? {maxWidth: this.props.field_ellipsis} : {}}> {this.props.placeholder || <span>&hellip;</span>} </div> ) : ( selected_values.sort((a, b) => a.name.localeCompare(b.name)).map((value) => ( <SelectedValue key={value.id} name={value.name} ellipsis={use_ellipsis && this.props.value_ellipsis} /> )) )} {this.props.ellipsis && selected_values.length < this.props.selected_values.length ? ( <div style={{...styles.pill, color: color('primary', 'light')}}>&hellip;</div> ) : null} </div> {this.props.editable ? ( <div className={cx('field__selection-values')} onMouseLeave={this.deactivate}> {this.props.searchable ? ( <SearchBar ref={(search_bar) => this.search_bar = search_bar} key={'search_bar'} className={cx('field__search-bar')} make_fuse={new_values_fuse} items={this.props.values} default_results={this.get_default_results()} on_query_change={this.on_query_change} placeholder="" /> ) : null} <div className={cx('field__selection-values-container')}> {displayed_value_ids.length == 0 ? ( this.props.allow_creating_values && this.state.query.length > 0 ? ( <div style={{padding: 5, display: 'flex', justifyContent: 'center', alignItems: 'center'}}> <Button onClick={this.create_value}> Ajouter </Button> </div> ) : ( <div style={{padding: 10, color: color('black', 'bright'), textAlign: 'center', fontStyle: 'italic', backgroundColor: color('black', 'pale')}}> Aucune valeur </div> ) ) : ( displayed_value_ids.map((id) => values_hash[id]) .filter(Boolean) .map((value) => { let selected = array_contains(this.props.selected_values, value) return ( <SelectionValue key={value.id} name={value.name} selected={selected} on_click={this.toggle_selected(selected, value.id)} /> ) }) )} </div> </div> ) : null} </div> ) } render() { return ( <Field {...this.props} category="non-exclusive" className={cx({ 'field_selected-values_empty': this.props.selected_values.length == 0, 'field_active': this.state.active && this.props.editable })} > <Hover> {this.render_hoverable} </Hover> </Field> ) } } class SelectedValue extends Component { render() { return ( <div className={cx('field__selected-value', {'field__selected-value_ellipsis': this.props.ellipsis})} style={this.props.ellipsis ? {maxWidth: this.props.ellipsis} : {}}> {this.props.name == "" ? ( <span style={{opacity: 0.54, fontStyle: 'italic'}}>Valeur sans nom</span> ) : ( <span>{this.props.name}</span> )} </div> ) } } class SelectionValue extends Component { render() { return ( <div onClick={this.props.on_click} className={cx('field__selection-value', {'field__selection-value_selected': this.props.selected})}> {this.props.name == "" ? ( <span style={{opacity: 0.54, fontStyle: 'italic'}}>Valeur sans nom</span> ) : ( <span>{this.props.name}</span> )} <span style={{width: 30, textAlign: 'center'}}> {this.props.selected ? ( <MdCheck /> ) : null} </span> </div> ) } } const styles = { pill: { borderRadius: 5, paddingLeft: 14, paddingTop: 1, paddingRight: 14, paddingBottom: 1, }, truncate: { whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", }, } NonExclusiveField.defaultProps = { name: "", show_label: true, selected_values: [], values: [], on_select_value: (id) => {}, on_deselect_value: (id) => {}, ellipsis: false, placeholder: "", value_ellipsis: false, field_ellipsis: false, edit_mode: 'hover', editable: true, searchable: true, allow_creating_values: true, create_value: (value) => new Promise((resolve, reject) => reject()), } export default NonExclusiveField