From e7927bdc642c252d1f6e94c4c3cf274e5e64f8ae Mon Sep 17 00:00:00 2001 From: Tom Robinson <tlrobinson@gmail.com> Date: Fri, 9 Sep 2016 17:19:56 -0700 Subject: [PATCH] Improve styling and error handling of custom maps settings --- .../components/SettingsCustomMaps.jsx | 119 ++++++++++-------- 1 file changed, 69 insertions(+), 50 deletions(-) diff --git a/frontend/src/metabase/admin/settings/components/SettingsCustomMaps.jsx b/frontend/src/metabase/admin/settings/components/SettingsCustomMaps.jsx index 9d0177f340e..3f11edc282a 100644 --- a/frontend/src/metabase/admin/settings/components/SettingsCustomMaps.jsx +++ b/frontend/src/metabase/admin/settings/components/SettingsCustomMaps.jsx @@ -4,6 +4,8 @@ import Utils from "metabase/lib/utils"; import Select, { Option } from "metabase/components/Select.jsx"; import Confirm from "metabase/components/Confirm.jsx"; +import Ellipsified from "metabase/components/Ellipsified.jsx"; +import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper.jsx"; import cx from "classnames"; import fetch from 'isomorphic-fetch'; @@ -74,6 +76,7 @@ export default class SettingsCustomMaps extends Component { }); this.setState({ geoJson: await geoJsonResponse.json() }); } catch (e) { + this.setState({ geoJsonError: e }); console.warn("map fetch failed", e) } } @@ -124,28 +127,40 @@ export default class SettingsCustomMaps extends Component { const ListMaps = ({ maps, onEditMap, onAddMap, onDeleteMap }) => <div> - <h2>Custom Maps</h2> - <p className="text-grey-4 flex align-center"> - <span>Add your own GeoJSON files</span> - <button className="Button Button--primary ml1" onClick={onAddMap}>Add a map</button> - </p> - <table> - {maps.filter(map => !map.builtin).map(map => - <tr key={map.id}> - <td> - <a className="cursor-pointer" onClick={() => onEditMap(map)}>{map.name}</a> - </td> - <td> - {map.url} - </td> - <td> - <Confirm action={() => onDeleteMap(map)} title="Delete custom map"> - <button className="Button Button--small Button--danger">Remove</button> - </Confirm> - </td> - </tr> - )} - </table> + <section className="PageHeader px2 clearfix"> + <div className="inline-block"> + <h2 className="PageTitle mb1">Custom Maps</h2> + <span>Add your own GeoJSON files</span> + </div> + <button className="Button Button--primary float-right" onClick={onAddMap}>Add a map</button> + </section> + <section> + <table className="ContentTable"> + <thead> + <tr> + <th>Name</th> + <th>URL</th> + </tr> + </thead> + <tbody> + {maps.filter(map => !map.builtin).map(map => + <tr key={map.id}> + <td className="cursor-pointer" onClick={() => onEditMap(map)}> + {map.name} + </td> + <td className="cursor-pointer" onClick={() => onEditMap(map)}> + <Ellipsified style={{ maxWidth: 600 }}>{map.url}</Ellipsified> + </td> + <td className="Table-actions"> + <Confirm action={() => onDeleteMap(map)} title="Delete custom map"> + <button className="Button Button--danger">Remove</button> + </Confirm> + </td> + </tr> + )} + </tbody> + </table> + </section> </div> const GeoJsonPropertySelect = ({ value, onChange, geoJson }) => { @@ -178,10 +193,10 @@ const GeoJsonPropertySelect = ({ value, onChange, geoJson }) => { ) } -const EditMap = ({ map, onMapChange, originalMap, geoJson, onLoadGeoJson, onCancel, onSave }) => - <ul> +const EditMap = ({ map, onMapChange, originalMap, geoJson, geoJsonError, onLoadGeoJson, onCancel, onSave }) => + <div> <h2>{ !originalMap ? "Add a new map" : "Edit map" }</h2> - <li className="m2 mb4"> + <div className="m2 mb4"> <div className="text-grey-4 text-bold text-uppercase pb1">Map Name</div> <div className="flex"> <input @@ -192,8 +207,8 @@ const EditMap = ({ map, onMapChange, originalMap, geoJson, onLoadGeoJson, onCanc onChange={(e) => onMapChange({ ...map, "name": e.target.value })} /> </div> - </li> - <li className="m2 mb4"> + </div> + <div className="m2 mb4"> <div className="text-grey-4 text-bold text-uppercase pb1">GeoJSON URL</div> <div className="flex"> <input @@ -205,31 +220,35 @@ const EditMap = ({ map, onMapChange, originalMap, geoJson, onLoadGeoJson, onCanc /> <button className={cx("Button ml1", { "Button--primary" : !geoJson })} onClick={onLoadGeoJson}>{geoJson ? "Refresh" : "Load"}</button> </div> - </li> - { geoJson && - <li className="m2 mb4"> - <div className="text-grey-4 text-bold text-uppercase pb1">Name Property</div> - <GeoJsonPropertySelect - value={map.region_name} - onChange={(value) => onMapChange({ ...map, "region_name": value })} - geoJson={geoJson} - /> - </li> - } - { geoJson && - <li className="m2 mb4"> - <div className="text-grey-4 text-bold text-uppercase pb1">Region Property</div> - <GeoJsonPropertySelect - value={map.region_key} - onChange={(value) => onMapChange({ ...map, "region_key": value })} - geoJson={geoJson} - /> - </li> + </div> + { geoJson !== undefined && + <LoadingAndErrorWrapper loading={geoJson === null} error={geoJsonError}> + { () => + <div> + <div className="m2 mb4"> + <div className="text-grey-4 text-bold text-uppercase pb1">Name Property</div> + <GeoJsonPropertySelect + value={map.region_name} + onChange={(value) => onMapChange({ ...map, "region_name": value })} + geoJson={geoJson} + /> + </div> + <div className="m2 mb4"> + <div className="text-grey-4 text-bold text-uppercase pb1">Region Property</div> + <GeoJsonPropertySelect + value={map.region_key} + onChange={(value) => onMapChange({ ...map, "region_key": value })} + geoJson={geoJson} + /> + </div> + </div> + } + </LoadingAndErrorWrapper> } - <li className="m2 mb4"> + <div className="m2 mb4"> <button className={cx("Button Button--borderless")} onClick={onCancel}>Cancel</button> <button className={cx("Button Button--primary ml1", { "disabled" : !map.name || !map.url || !map.region_name || !map.region_key })} onClick={onSave}> {originalMap ? "Save map" : "Add map"} </button> - </li> - </ul> + </div> + </div> -- GitLab