UNPKG

react-floorplanner

Version:

react-floorplanner is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.

228 lines (190 loc) 6.7 kB
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import CatalogItem from './catalog-item'; import CatalogBreadcrumb from './catalog-breadcrumb'; import CatalogPageItem from './catalog-page-item'; import CatalogTurnBackPageItem from './catalog-turn-back-page-item'; import ContentContainer from '../style/content-container'; import ContentTitle from '../style/content-title'; import * as SharedStyle from '../../shared-style'; const containerStyle = { position: 'fixed', width:'calc( 100% - 51px)', height:'calc( 100% - 20px)', backgroundColor:'#FFF', padding:'1em', left:50, overflowY:'auto', overflowX:'hidden', zIndex:10 }; const itemsStyle = { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(14em, 1fr))', gridGap: '10px', marginTop: '1em' }; const searchContainer = { width: '100%', height: '3em', padding: '0.625em', background: '#f7f7f9', border: '1px solid #e1e1e8', cursor: 'pointer', position: 'relative', boxShadow: '0 1px 6px 0 rgba(0, 0, 0, 0.11), 0 1px 4px 0 rgba(0, 0, 0, 0.11)', borderRadius: '2px', transition: 'all .2s ease-in-out', WebkitTransition: 'all .2s ease-in-out', marginBottom: '1em' }; const searchText = { width: '8em', display: 'inline-block' }; const searchInput = { width: 'calc( 100% - 10em )', height: '2em', margin: '0', padding: '0 1em', border: '1px solid #EEE' }; const historyContainer = { ...searchContainer, padding: '0.2em 0.625em' }; const historyElementStyle = { width: 'auto', height: '2em', lineHeight: '2em', textAlign:'center', borderRadius: '1em', display: 'inline-block', cursor: 'pointer', backgroundColor: SharedStyle.PRIMARY_COLOR.alt, color: SharedStyle.PRIMARY_COLOR.text_main, textTransform: 'capitalize', margin: '0.25em', padding: '0 1em' }; export default class CatalogList extends Component { constructor(props, context) { super(props); let page = props.state.catalog.page; let currentCategory = context.catalog.getCategory(page); let categoriesToDisplay = currentCategory.categories; let elementsToDisplay = currentCategory.elements.filter(element => element.info.visibility ? element.info.visibility.catalog : true ); this.state = { categories: currentCategory.categories, elements: elementsToDisplay, matchString: '', matchedElements: [] }; } flattenCategories( categories ) { let toRet = []; for( let x = 0; x < categories.length; x++ ) { let curr = categories[x]; toRet = toRet.concat( curr.elements ); if( curr.categories.length ) toRet = toRet.concat( this.flattenCategories ( curr.categories ) ); } return toRet; } matcharray( text ) { let array = this.state.elements.concat( this.flattenCategories( this.state.categories ) ); let filtered = []; if( text != '' ) { let regexp = new RegExp( text, 'i'); for (let i = 0; i < array.length; i++) { if (regexp.test(array[i].info.title)) { filtered.push(array[i]); } } } this.setState({ matchString: text, matchedElements: filtered }); }; select( element ) { switch (element.prototype) { case 'lines': this.context.linesActions.selectToolDrawingLine(element.name); break; case 'items': this.context.itemsActions.selectToolDrawingItem(element.name); break; case 'holes': this.context.holesActions.selectToolDrawingHole(element.name); break; } this.context.projectActions.pushLastSelectedCatalogElementToHistory(element); } render() { let page = this.props.state.catalog.page; let currentCategory = this.context.catalog.getCategory(page); let categoriesToDisplay = currentCategory.categories; let elementsToDisplay = currentCategory.elements.filter(element => element.info.visibility ? element.info.visibility.catalog : true ); let breadcrumbComponent = null; if (page !== 'root') { let breadcrumbsNames = []; this.props.state.catalog.path.forEach(pathName => { breadcrumbsNames.push({ name: this.context.catalog.getCategory(pathName).label, action: () => projectActions.goBackToCatalogPage(pathName) }); }); breadcrumbsNames.push({name: currentCategory.label, action: ''}); breadcrumbComponent = (<CatalogBreadcrumb names={breadcrumbsNames}/>); } let pathSize = this.props.state.catalog.path.size; let turnBackButton = pathSize > 0 ? ( <CatalogTurnBackPageItem key={pathSize} page={this.context.catalog.categories[this.props.state.catalog.path.get(pathSize - 1)]}/>) : null; let selectedHistory = this.props.state.get('selectedElementsHistory'); let selectedHistoryElements = selectedHistory.map( ( el, ind ) => <div key={ind} style={historyElementStyle} title={el.name} onClick={() => this.select(el) }>{el.name}</div> ); return ( <ContentContainer width={this.props.width} height={this.props.height} style={{...containerStyle, ...this.props.style}}> <ContentTitle>{this.context.translator.t('Catalog')}</ContentTitle> {breadcrumbComponent} <div style={searchContainer}> <span style={searchText}>{this.context.translator.t('Search Element')}</span> <input type="text" style={searchInput} onChange={( e ) => { this.matcharray( e.target.value ); } }/> </div> { selectedHistory.size ? <div style={historyContainer}> <span>{this.context.translator.t('Last Selected')}</span> {selectedHistoryElements} </div> : null } <div style={itemsStyle}> { this.state.matchString === '' ? [ turnBackButton, categoriesToDisplay.map(cat => <CatalogPageItem key={cat.name} page={cat} oldPage={currentCategory}/>), elementsToDisplay.map(elem => <CatalogItem key={elem.name} element={elem}/>) ] : this.state.matchedElements.map(elem => <CatalogItem key={elem.name} element={elem}/>) } </div> </ContentContainer> ) } } CatalogList.propTypes = { state: PropTypes.object.isRequired, width: PropTypes.number.isRequired, height: PropTypes.number.isRequired, style: PropTypes.object }; CatalogList.contextTypes = { catalog: PropTypes.object.isRequired, translator: PropTypes.object.isRequired, itemsActions: PropTypes.object.isRequired, linesActions: PropTypes.object.isRequired, holesActions: PropTypes.object.isRequired, projectActions: PropTypes.object.isRequired };