public/components/BatchTagControls/BatchTagControls.js (160 lines of code) (raw):

import React from 'react'; import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup'; import TagSelect from '../utils/TagSelect'; import tagManagerApi from '../../util/tagManagerApi'; import { browserHistory } from 'react-router' export default class BatchTagControls extends React.Component { constructor(props) { super(props); this.modeMap = { 'add_to_top': { text: 'Add tag to top', func: this.addTagToContentTop }, 'add_to_bottom': { text: 'Add tag to bottom', func: this.addTagToContentBottom }, 'remove': { text: 'Remove tag', func: this.removeTagFromContent } } this.state = { mode: '', toAddToTop: [], toAddToBottom: [], toRemove: [], }; } switchMode(mode) { this.setState({ mode }); } addTagToContentTop(tag) { if (!this.state.toAddToTop.some(t => t.id === tag.id)) { this.setState({ toAddToTop: [tag, ...this.state.toAddToTop], mode: '' }); } } addTagToContentBottom(tag) { if (!this.state.toAddToBottom.some(t => t.id === tag.id)) { this.setState({ toAddToBottom: [tag, ...this.state.toAddToBottom], mode: '' }); } } removeTagFromContent(tag) { if (!this.state.toRemove.some(t => t.id === tag.id)) { this.setState({ toRemove: [tag, ...this.state.toRemove], mode: '' }); } } resetMode() { this.setState({ mode: '' }); } performBatchTag(tag, operation) { const {toAddToTop, toAddToBottom, toRemove} = this.state; const toId = (tag) => tag.id; // Currently we only support setting 1 tag to "add to top" because otherwise it will depends on the order the events are processed tagManagerApi.batchTag(this.props.selectedContent, toAddToTop.map(toId)[0], toAddToBottom.map(toId), toRemove.map(toId)) .then(_ => browserHistory.push('/status')); } renderButtons() { const pluralContent = this.props.selectedContent.length > 1 ? 'pieces' : 'piece'; const topButtonClass = this.state.toAddToTop.length > 0 ? "batch-status__button--disabled" : "batch-status__button"; const topButtonFunc = this.state.toAddToTop.length > 0 ? () => {} : this.switchMode.bind(this, 'add_to_top'); return ( <div className="batch-status__mode"> <div className={topButtonClass} onClick={topButtonFunc}> Add tag to top of tag list </div> <div className="batch-status__button" onClick={this.switchMode.bind(this, 'add_to_bottom')}> Add tag to bottom of tag list </div> <div className="batch-status__button--remove" onClick={this.switchMode.bind(this, 'remove')}> Remove tag </div> <div className="batch-status__info"> {this.props.selectedContent.length} {pluralContent} selected </div> </div> ); } renderTagPicker() { const {text, func} = this.modeMap[this.state.mode]; return ( <div className="batch-status__mode"> <div className="batch-status__info"> {text} </div> <TagSelect onTagClick={func.bind(this)} showResultsAbove={true} /> <i className="i-cross batch-status__cancel clickable-icon" onClick={this.resetMode.bind(this)}></i> </div> ); } renderMode() { if (!this.state.mode) { return this.renderButtons(); } else { return this.renderTagPicker(); } } removeFromList(tagIndex, list, listName) { const before = [...list].splice(0, tagIndex); const after = [...list].splice(tagIndex + 1); this.setState({ [listName]: [...before, ...after] }); } renderBasket() { const renderCategory = (title, tags, name) => { if (tags.length) { return ( <ul className='batch-status__basket-category'> <h3 className='batch-status__basket-category-title'>{title}</h3> {tags.map((tag, i) => { return ( <li key={tag.id}> <i className="i-cross clickable-icon" onClick={() => this.removeFromList(i, tags, name)}></i> <strong>{tag.internalName}</strong> <span className='batch-status__small-path'>({tag.path})</span> </li> ); })} </ul> ); } else { return false; } }; return ( <div className='batch-status__basket'> <h2 className='batch-status__basket-title'>Changes</h2> {renderCategory('To Add to Top', this.state.toAddToTop, 'toAddToTop')} {renderCategory('To Add to Bottom', this.state.toAddToBottom, 'toAddToBottom')} {renderCategory('To Remove', this.state.toRemove, 'toRemove')} <button className='batch-status__submit' onClick={this.performBatchTag.bind(this)}>Submit</button> </div> ); } render () { if (this.props.selectedContent.length === 0) { return false; } const {toAddToTop, toAddToBottom, toRemove} = this.state; return ( <CSSTransitionGroup transitionName="batch-status-transition" transitionEnterTimeout={500} transitionLeaveTimeout={500}> <div className="batch-status__container"> <div className="batch-status"> {this.renderMode()} </div> {toAddToTop.length + toAddToBottom.length + toRemove.length > 0 ? this.renderBasket() : false} </div> </CSSTransitionGroup> ); } }