Files
redash/client/app/visualizations/map/Editor/StyleSettings.jsx
Levko Kravets 713fd2d0fb Change visualizations import to be static (#4592)
* getredash/redash#4565 Change visualizations import to be static

* Move visualizations-related components to own folder
2020-01-28 12:48:38 +02:00

245 lines
8.3 KiB
JavaScript

import { isNil, map } from "lodash";
import React, { useMemo } from "react";
import { useDebouncedCallback } from "use-debounce";
import { Section, Select, Checkbox, Input, ColorPicker, ContextHelp } from "@/components/visualizations/editor";
import { EditorPropTypes } from "@/visualizations/prop-types";
import ColorPalette from "@/visualizations/ColorPalette";
const mapTiles = [
{
name: "OpenStreetMap",
url: "//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
},
{
name: "OpenStreetMap BW",
url: "//{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png",
},
{
name: "OpenStreetMap DE",
url: "//{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png",
},
{
name: "OpenStreetMap FR",
url: "//{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png",
},
{
name: "OpenStreetMap Hot",
url: "//{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png",
},
{
name: "Thunderforest",
url: "//{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png",
},
{
name: "Thunderforest Spinal",
url: "//{s}.tile.thunderforest.com/spinal-map/{z}/{x}/{y}.png",
},
{
name: "OpenMapSurfer",
url: "//korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}",
},
{
name: "Stamen Toner",
url: "//stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}.png",
},
{
name: "Stamen Toner Background",
url: "//stamen-tiles-{s}.a.ssl.fastly.net/toner-background/{z}/{x}/{y}.png",
},
{
name: "Stamen Toner Lite",
url: "//stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.png",
},
{
name: "OpenTopoMap",
url: "//{s}.tile.opentopomap.org/{z}/{x}/{y}.png",
},
];
const CustomColorPalette = {
White: "#ffffff",
...ColorPalette,
};
function getCustomIconOptionFields(iconShape) {
switch (iconShape) {
case "doughnut":
return { showIcon: false, showBackgroundColor: true, showBorderColor: true };
case "circle-dot":
case "rectangle-dot":
return { showIcon: false, showBackgroundColor: false, showBorderColor: true };
default:
return { showIcon: true, showBackgroundColor: true, showBorderColor: true };
}
}
export default function StyleSettings({ options, onOptionsChange }) {
const [debouncedOnOptionsChange] = useDebouncedCallback(onOptionsChange, 200);
const { showIcon, showBackgroundColor, showBorderColor } = useMemo(
() => getCustomIconOptionFields(options.iconShape),
[options.iconShape]
);
const isCustomMarkersStyleAllowed = isNil(options.classify);
return (
<React.Fragment>
<Section>
<Select
label="Map Tiles"
data-test="Map.Editor.Tiles"
className="w-100"
value={options.mapTileUrl}
onChange={mapTileUrl => onOptionsChange({ mapTileUrl })}>
{map(mapTiles, ({ name, url }) => (
<Select.Option key={url} data-test={"Map.Editor.Tiles." + name}>
{name}
</Select.Option>
))}
</Select>
</Section>
<Section.Title>Markers</Section.Title>
<Section>
<Checkbox
data-test="Map.Editor.ClusterMarkers"
defaultChecked={options.clusterMarkers}
onChange={event => onOptionsChange({ clusterMarkers: event.target.checked })}>
Cluster Markers
</Checkbox>
</Section>
<Section>
<Checkbox
data-test="Map.Editor.CustomizeMarkers"
disabled={!isCustomMarkersStyleAllowed}
defaultChecked={options.customizeMarkers}
onChange={event => onOptionsChange({ customizeMarkers: event.target.checked })}>
Override default style
</Checkbox>
{!isCustomMarkersStyleAllowed && (
<ContextHelp placement="topLeft" arrowPointAtCenter>
Custom marker styles are not available
<br />
when <b>Group By</b> column selected.
</ContextHelp>
)}
</Section>
{isCustomMarkersStyleAllowed && options.customizeMarkers && (
<React.Fragment>
<Section>
<Select
layout="horizontal"
label="Shape"
className="w-100"
data-test="Map.Editor.MarkerShape"
value={options.iconShape}
onChange={iconShape => onOptionsChange({ iconShape })}>
<Select.Option key="marker" data-test="Map.Editor.MarkerShape.marker">
Marker + Icon
</Select.Option>
<Select.Option key="doughnut" data-test="Map.Editor.MarkerShape.doughnut">
Circle
</Select.Option>
<Select.Option key="circle-dot" data-test="Map.Editor.MarkerShape.circle-dot">
Circle Dot
</Select.Option>
<Select.Option key="circle" data-test="Map.Editor.MarkerShape.circle">
Circle + Icon
</Select.Option>
<Select.Option key="rectangle-dot" data-test="Map.Editor.MarkerShape.rectangle-dot">
Square Dot
</Select.Option>
<Select.Option key="rectangle" data-test="Map.Editor.MarkerShape.rectangle">
Square + Icon
</Select.Option>
</Select>
</Section>
{showIcon && (
<Section>
<Input
layout="horizontal"
label={
<React.Fragment>
Icon
<ContextHelp placement="topLeft" arrowPointAtCenter>
<div className="m-b-5">
Enter an icon name from{" "}
<a href="https://fontawesome.com/v4.7.0/icons/" target="_blank" rel="noopener noreferrer">
Font-Awesome 4.7
</a>
</div>
<div className="m-b-5">
Examples: <code>check</code>, <code>times-circle</code>, <code>flag</code>
</div>
<div>Leave blank to remove.</div>
</ContextHelp>
</React.Fragment>
}
className="w-100"
data-test="Map.Editor.MarkerIcon"
defaultValue={options.iconFont}
onChange={event => debouncedOnOptionsChange({ iconFont: event.target.value })}
/>
</Section>
)}
{showIcon && (
<Section>
<ColorPicker
layout="horizontal"
label="Icon Color"
interactive
presetColors={CustomColorPalette}
placement="topRight"
color={options.foregroundColor}
triggerProps={{ "data-test": "Map.Editor.MarkerIconColor" }}
onChange={foregroundColor => onOptionsChange({ foregroundColor })}
addonAfter={<ColorPicker.Label color={options.foregroundColor} presetColors={CustomColorPalette} />}
/>
</Section>
)}
{showBackgroundColor && (
<Section>
<ColorPicker
layout="horizontal"
label="Background Color"
interactive
presetColors={CustomColorPalette}
placement="topRight"
color={options.backgroundColor}
triggerProps={{ "data-test": "Map.Editor.MarkerBackgroundColor" }}
onChange={backgroundColor => onOptionsChange({ backgroundColor })}
addonAfter={<ColorPicker.Label color={options.backgroundColor} presetColors={CustomColorPalette} />}
/>
</Section>
)}
{showBorderColor && (
<Section>
<ColorPicker
layout="horizontal"
label="Border Color"
interactive
presetColors={CustomColorPalette}
placement="topRight"
color={options.borderColor}
triggerProps={{ "data-test": "Map.Editor.MarkerBorderColor" }}
onChange={borderColor => onOptionsChange({ borderColor })}
addonAfter={<ColorPicker.Label color={options.borderColor} presetColors={CustomColorPalette} />}
/>
</Section>
)}
</React.Fragment>
)}
</React.Fragment>
);
}
StyleSettings.propTypes = EditorPropTypes;