UNPKG

@hackoregon/component-library

Version:

Official repo for Hack Oregon React component library

414 lines (391 loc) 12.9 kB
/* eslint-disable react/no-access-state-in-setstate */ /* eslint-disable react/destructuring-assignment */ /* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable no-console */ import React from "react"; import { css } from "emotion"; import { storiesOf } from "@storybook/react"; import { withA11y } from "@storybook/addon-a11y"; import "react-select/dist/react-select.css"; import { isArray } from "lodash"; import { Sandbox } from "../src"; import { foundations, slides } from "../src/Sandbox/constants"; /* global fetch */ class SandboxStory extends React.Component { constructor() { super(); this.state = { data: { packages: {}, foundations: {}, slides: {} }, hasFetched: false, selectedPackage: "Sweeps", selectedFoundation: "", selectedSlide: [], defaultFoundation: {}, defaultSlides: [], drawerVisible: true, slideData: [], foundationData: {}, allSlides: [], foundationMapProps: {} }; this.updateFoundation = this.updateFoundation.bind(this); this.updateSlide = this.updateSlide.bind(this); this.updateSlide2 = this.updateSlide2.bind(this); this.updatePackage = this.updatePackage.bind(this); this.toggleDrawer = this.toggleDrawer.bind(this); this.fetchSlideData = this.fetchSlideData.bind(this); this.fetchFoundationData = this.fetchFoundationData.bind(this); this.fetchSlideDataByDate = this.fetchSlideDataByDate.bind(this); this.initialDataSetup = this.initialDataSetup.bind(this); } componentDidMount() { fetch("https://sandbox.civicpdx.org/civic-sandbox") .then(res => res) .then(res => res.json()) .then(data => this.setState({ data: data.body, hasFetched: true })); } componentDidUpdate(prevProps, prevState) { if ( this.state.hasFetched !== prevState.hasFetched && this.state.hasFetched ) { this.initialDataSetup(this.state); } if (this.state.selectedFoundation !== prevState.selectedFoundation) { this.updateFoundation(this.state.selectedFoundation); } if (this.state.selectedSlide !== prevState.selectedSlide) { this.updateSlide2(this.state.selectedSlide); } } initialDataSetup = state => { const selectedPackageData = state.data.packages[this.state.selectedPackage]; const selectedFoundation = selectedPackageData ? selectedPackageData.default_foundation : ""; const selectedSlide = selectedPackageData ? selectedPackageData.default_slide : []; const defaultFoundation = selectedFoundation && state.data.foundations[selectedFoundation]; const dataObj = { slide_meta: {}, slide_data: {} }; const foundationMapObj = foundations(dataObj)[defaultFoundation.name]; const foundationMapProps = { color: foundationMapObj.color, getPropValue: foundationMapObj.getPropValue, propName: foundationMapObj.propName, scaleType: foundationMapObj.scaleType }; if ( foundationMapObj.scaleType === "ordinal" || foundationMapObj.scaleType === "threshold" ) { foundationMapProps.categories = foundationMapObj.categories; } const allSlides = state.data.packages[ this.state.selectedPackage ].slides.map(slide => { const mapObj = slides(dataObj)[state.data.slides[slide].name]; const gray = [238, 238, 238, 255]; const color = mapObj.boundary.getLineColor ? mapObj.boundary.getLineColor() : gray; const { mapType } = mapObj.map; return { slideId: slide, slideObj: state.data.slides[slide], label: state.data.slides[slide].name, checked: !!selectedSlide.includes(slide), color, mapType }; }); const defaultSlides = allSlides .filter(slide => slide.checked === true) .map(slide => state.data.slides[slide.slideId]); this.setState({ selectedFoundation, selectedSlide, defaultFoundation, defaultSlides, allSlides, foundationMapProps }); }; updateFoundation = selectedFoundation => { const defaultFoundation = this.state.data.foundations[selectedFoundation]; const dataObj = { slide_meta: {}, slide_data: {} }; const foundationMapObj = foundations(dataObj)[defaultFoundation.name]; const foundationMapProps = { color: foundationMapObj.color, getPropValue: foundationMapObj.getPropValue, propName: foundationMapObj.propName, scaleType: foundationMapObj.scaleType }; if ( foundationMapObj.scaleType === "ordinal" || foundationMapObj.scaleType === "threshold" ) { foundationMapProps.categories = foundationMapObj.categories; } this.fetchFoundationData(defaultFoundation); this.setState({ selectedFoundation, defaultFoundation, foundationMapProps }); }; updateSlide2 = selectedSlide => { const selectedSlides = isArray(selectedSlide) ? selectedSlide : selectedSlide.split(","); const defaultSlides = selectedSlides.map( slide => this.state.data.slides[slide] ); this.fetchSlideData(defaultSlides); this.setState({ selectedSlide: selectedSlides, defaultSlides }); }; updateSlide = event => { const slideId = event.target.name; const allSlides = this.state.allSlides.map(slide => { if (slide.slideId === slideId) { return { ...slide, checked: !slide.checked }; } return slide; }); const defaultSlides = allSlides .filter(slide => slide.checked === true) .map(slide => this.state.data.slides[slide.slideId]); const selectedSlides = allSlides .filter(slide => slide.checked === true) .map(slide => slide.slideId); this.fetchSlideData(defaultSlides); this.setState({ selectedSlide: selectedSlides, defaultSlides, allSlides }); }; fetchFoundationData = foundation => { const url = foundation.endpoint.includes("https") ? foundation.endpoint : `${foundation.endpoint.slice(0, 4)}s${foundation.endpoint.slice(4)}`; fetch(url) .then(res => { if (!res.ok) { throw Error(res.statusText); } return res; }) .then(res => res.json()) .then(data => this.setState({ foundationData: data })) .catch(err => console.error(err)); }; fetchSlideData = slideData => { const defaultSlides = [...slideData]; const slideDataNames = this.state.slideData.map( slide => Object.keys(slide)[0] ); const onlyFetchNewSlides = defaultSlides.filter( slide => !slideDataNames.includes(slide.name) ); Promise.all( onlyFetchNewSlides.map(s => { const url = s.endpoint.includes("https") ? s.endpoint : `${s.endpoint.slice(0, 4)}s${s.endpoint.slice(4)}`; return fetch(url) .then(res => { if (!res.ok) { throw Error(res.statusText); } return res; }) .then(res => res.json()) .then(data => ({ [s.name]: data })) .catch(err => console.error(err)); }) ).then(data => { this.setState({ slideData: [...this.state.slideData, ...data] }); }); }; findAndReplaceSlideData = (slideData, data, slideLabel) => { const slideDataValues = Object.values(slideData); const newSlideData = slideData.map((slide, index) => { const [slideDataName] = Object.keys(slideDataValues[index]); if (slideDataName === slideLabel) { return { [slideLabel]: data }; } return slide; }); return newSlideData; }; fetchSlideDataByDate = (slide, date, type) => { let url; if (type === "slide") { url = slide.slideObj.endpoint.includes("https") ? `${slide.slideObj.endpoint}${date}` : `${slide.slideObj.endpoint.slice( 0, 4 )}s${slide.slideObj.endpoint.slice(4)}${date}`; } else { url = slide.endpoint.includes("https") ? `${slide.endpoint}${date}` : `${slide.endpoint.slice(0, 4)}s${slide.endpoint.slice(4)}${date}`; } fetch(url) .then(res => { if (!res.ok) { throw Error(res.statusText); } return res; }) .then(res => res.json()) .then(data => { if (type === "slide") { this.setState({ slideData: this.findAndReplaceSlideData( this.state.slideData, data, slide.label ) }); } else { this.setState({ foundationData: data }); } }) .catch(err => console.error(err)); }; updatePackage = selectedPackage => { const { data } = this.state; const packageData = data.packages[selectedPackage]; const selectedFoundation = packageData.default_foundation; this.updateFoundation(selectedFoundation); const selectedSlide = isArray(packageData.default_slide) ? packageData.default_slide : packageData.default_slide.split(","); this.updateSlide2(selectedSlide); const dataObj = { slide_meta: {}, slide_data: {} }; const defaultFoundation = data.foundations[selectedFoundation]; const foundationMapObj = foundations(dataObj)[defaultFoundation.name]; const foundationMapProps = { color: foundationMapObj.color, getPropValue: foundationMapObj.getPropValue, propName: foundationMapObj.propName, scaleType: foundationMapObj.scaleType }; if ( foundationMapObj.scaleType === "ordinal" || foundationMapObj.scaleType === "threshold" ) { foundationMapProps.categories = foundationMapObj.categories; } const defaultSlides = selectedSlide.map(slide => data.slides[slide]); const allSlides = data.packages[selectedPackage].slides.map(slide => { const mapObj = slides(dataObj)[data.slides[slide].name]; const gray = [238, 238, 238, 255]; const color = mapObj.boundary.getLineColor ? mapObj.boundary.getLineColor() : gray; const { mapType } = mapObj.map; return { slideId: slide, slideObj: data.slides[slide], label: data.slides[slide].name, checked: !!selectedSlide.includes(slide), color, mapType }; }); this.setState({ selectedPackage, selectedFoundation, selectedSlide, defaultFoundation, defaultSlides, allSlides, foundationMapProps }); }; toggleDrawer = () => { this.setState({ drawerVisible: !this.state.drawerVisible }); }; formatData = (defaultFoundation, defaultSlides) => { const formatSlideData = defaultSlides .map(slide => { let data = { slide_meta: {}, slide_data: {} }; if (this.state.slideData.length) { const findSlide = this.state.slideData.find(slideData => { return slideData[slide.name]; }); data = findSlide ? findSlide[slide.name] : data; } const slideObj = slides(data)[slide.name]; return [ { data: slideObj ? slideObj.boundary : {} }, { data: slideObj ? slideObj.map : {} } ]; }) .reduce((a, b) => a.concat(b), []); return [ { data: this.state.foundationData.slide_data ? foundations(this.state.foundationData)[defaultFoundation.name] : {} }, ...formatSlideData ]; }; render() { const styles = css(` margin: 0; padding: 0; width: 100%; font-family: 'Roboto Condensed', 'Helvetica Neue', Helvetica, sans-serif; `); return this.state.hasFetched ? ( <Sandbox layerData={this.formatData( this.state.defaultFoundation, this.state.defaultSlides )} updateFoundation={this.updateFoundation} updateSlide={this.updateSlide} toggleDrawer={this.toggleDrawer} fetchSlideDataByDate={this.fetchSlideDataByDate} updatePackage={this.updatePackage} styles={styles} data={this.state.data} selectedPackage={this.state.selectedPackage} selectedFoundation={this.state.selectedFoundation} selectedSlide={this.state.selectedSlide} drawerVisible={this.state.drawerVisible} slideData={this.state.slideData} defaultSlides={this.state.defaultSlides} defaultFoundation={this.state.defaultFoundation} foundationData={this.state.foundationData} allSlides={this.state.allSlides} foundationMapProps={this.state.foundationMapProps} /> ) : null; } } export default () => storiesOf("Component Lib|CIVIC Platform/Sandbox", module).add( "Sandbox", () => <SandboxStory /> );