diff --git a/client/src/components/Coloring/ColorSelector.vue b/client/src/components/Coloring/ColorSelector.vue index 3f1a52e..2139dbe 100644 --- a/client/src/components/Coloring/ColorSelector.vue +++ b/client/src/components/Coloring/ColorSelector.vue @@ -126,6 +126,17 @@ export default defineComponent({ && layer.default_style.layers[props.layerType] !== true ) { (layer.default_style.layers[props.layerType] as VectorLayerDisplayConfig).color = '#888888'; + (layer.default_style.layers[props.layerType] as VectorLayerDisplayConfig).legend = false; + } + } + } else { + const { layer } = getVectorLayerDisplayConfig(props.layerId, props.layerType); + if (layer?.default_style?.layers && layer.default_style.layers[props.layerType]) { + if ( + layer.default_style.layers[props.layerType] !== false + && layer.default_style.layers[props.layerType] !== true + ) { + (layer.default_style.layers[props.layerType] as VectorLayerDisplayConfig).legend = true; } } } diff --git a/client/src/components/DataSelection/Datasets.vue b/client/src/components/DataSelection/Datasets.vue index 30523ba..f6c2224 100644 --- a/client/src/components/DataSelection/Datasets.vue +++ b/client/src/components/DataSelection/Datasets.vue @@ -107,7 +107,6 @@ export default defineComponent({ return { datasets: filteredDatasets, layersByDataset: MapStore.mapLayersByDataset, - selectedLayers: MapStore.selectedMapLayers, toggleLayerSelection, loadDataset, updateNetCDFLayer, diff --git a/client/src/components/DataSelection/NetCDFDataConfigurator.vue b/client/src/components/DataSelection/NetCDFDataConfigurator.vue index 00cf1bd..ce8ebb8 100644 --- a/client/src/components/DataSelection/NetCDFDataConfigurator.vue +++ b/client/src/components/DataSelection/NetCDFDataConfigurator.vue @@ -91,6 +91,9 @@ export default defineComponent({ const data = getVariableInformation(variable); if (data) { if (data.geospatial === 'longitude360') { + if (data.attributes.units === 'degrees_east') { + return [-1 * convert360Longitude(data.max), -1 * convert360Longitude(data.min)]; + } return [convert360Longitude(data.min), convert360Longitude(data.max)]; } return [data.min, data.max]; @@ -106,7 +109,11 @@ export default defineComponent({ const dataX = getVariableInformation(newLayerX.value); let xRange = [dataX.min, dataX.max]; if (dataX.geospatial === 'longitude360') { - xRange = [convert360Longitude(dataX.min), convert360Longitude(dataX.max)]; + if (dataX.attributes.units === 'degrees_east') { + xRange = [-1 * convert360Longitude(dataX.max), -1 * convert360Longitude(dataX.min)]; + } else { + xRange = [convert360Longitude(dataX.min), convert360Longitude(dataX.max)]; + } } const dataY = getVariableInformation(newLayerY.value); const yRange = [dataY.min, dataY.max]; @@ -142,7 +149,11 @@ export default defineComponent({ const dataX = getVariableInformation(newLayerX.value); let xRange = [dataX.min, dataX.max]; if (dataX.geospatial === 'longitude360') { - xRange = [convert360Longitude(dataX.min), convert360Longitude(dataX.max)]; + if (dataX.attributes.units === 'degrees_east') { + xRange = [-1 * convert360Longitude(dataX.max), -1 * convert360Longitude(dataX.min)]; + } else { + xRange = [convert360Longitude(dataX.min), convert360Longitude(dataX.max)]; + } } const dataY = getVariableInformation(newLayerY.value); @@ -168,7 +179,11 @@ export default defineComponent({ xLayerRange.value = [data.min, data.max]; xLayerRangeStep.value = (data.max - data.min) / (data.steps || 1); if (data.geospatial === 'longitude360') { - xLayerRange.value = [convert360Longitude(data.min), convert360Longitude(data.max)]; + if (data.attributes.units === 'degrees_east') { + xLayerRange.value = [-1 * convert360Longitude(data.max), -1 * convert360Longitude(data.min)]; + } else { + xLayerRange.value = [convert360Longitude(data.min), convert360Longitude(data.max)]; + } xLayerRangeStep.value = (xLayerRange.value[1] - xLayerRange.value[0]) / (data.steps || 1); } }); diff --git a/client/src/components/LayerTypeConfig.vue b/client/src/components/LayerTypeConfig.vue index a447124..4db6e1e 100644 --- a/client/src/components/LayerTypeConfig.vue +++ b/client/src/components/LayerTypeConfig.vue @@ -54,11 +54,12 @@ export default defineComponent({ return enabled; }); - type LayerActionItems = 'enabled' | 'selectable' | 'hoverable' | 'opacity' | 'zoomMinMax' | 'selectColor' | 'defaultSize' | 'color' | 'text' | 'heatmapControls'; + type LayerActionItems = 'enabled' | 'selectable' | 'hoverable' | 'opacity' | 'zoomMinMax' | 'selectColor' | 'defaultSize' | 'legend' | 'color' | 'text' | 'heatmapControls'; const layerActionItemsMap: Record = { enabled: ['line', 'fill', 'circle', 'fill-extrusion', 'text', 'heatmap'], selectable: ['line', 'fill', 'circle', 'fill-extrusion'], hoverable: ['line', 'fill', 'circle', 'fill-extrusion'], + legend: ['line', 'fill', 'circle', 'fill-extrusion', 'heatmap'], opacity: ['line', 'fill', 'circle', 'fill-extrusion', 'text', 'heatmap'], zoomMinMax: ['line', 'fill', 'circle', 'fill-extrusion', 'text', 'heatmap'], selectColor: ['line', 'fill', 'circle', 'fill-extrusion'], @@ -70,7 +71,7 @@ export default defineComponent({ const actionItemVisible = computed(() => { const enabledItems = new Set(); - const itemList: LayerActionItems[] = ['enabled', 'selectable', 'hoverable', 'opacity', 'zoomMinMax', 'selectColor', 'defaultSize', 'color', 'text', 'heatmapControls']; + const itemList: LayerActionItems[] = ['enabled', 'selectable', 'hoverable', 'legend', 'opacity', 'zoomMinMax', 'selectColor', 'defaultSize', 'color', 'text', 'heatmapControls']; itemList.forEach((key) => { if (layerActionItemsMap[key].includes(props.layerType)) { enabledItems.add(key); @@ -98,6 +99,9 @@ export default defineComponent({ if (field === 'hoverable') { displayConfig.hoverable = val; } + if (field === 'legend') { + displayConfig.legend = val; + } if (field === 'opacity') { if (val) { displayConfig.opacity = 0.75; @@ -232,6 +236,11 @@ export default defineComponent({ const foundColorIndex = found.default_style.savedColors.findIndex((item) => item.name === name); if (foundColorIndex !== -1) { currentLayerType.value.color = found.default_style.savedColors[foundColorIndex].color; + if (typeof (currentLayerType.value.color) !== 'string' && currentLayerType.value.color?.type) { + updateLayerTypeField('legend', true); + } else { + updateLayerTypeField('legend', true); + } updateLayer(found); } colorSaveChooser.value = false; @@ -239,6 +248,36 @@ export default defineComponent({ } } }; + + // Static color setting: + const getLayerConfigColor = () => { + const found = MapStore.selectedVectorMapLayers.value.find((item: VectorMapLayer) => item.id === props.layerId); + if (found?.default_style?.layers) { + const layerTypeVal = found?.default_style?.layers[props.layerType]; + if (layerTypeVal !== false && layerTypeVal !== true) { + if (layerTypeVal.color === undefined) { + layerTypeVal.color = '#00FF00'; + } + return layerTypeVal.color; + } + } + return '#00FF00'; + }; + const baseColorConfig = computed(() => getLayerConfigColor()); + + const updateStaticColor = (color: string) => { + const { layer } = getVectorLayerDisplayConfig(props.layerId, props.layerType); + if (layer?.default_style?.layers && layer.default_style.layers[props.layerType]) { + if ( + layer.default_style.layers[props.layerType] !== false + && layer.default_style.layers[props.layerType] !== true + ) { + (layer.default_style.layers[props.layerType] as VectorLayerDisplayConfig).color = color; + updateLayer(layer); + } + } + }; + return { currentLayerType, colorPickerVisible, @@ -259,6 +298,8 @@ export default defineComponent({ updateOpacity, updateZoom, actionItemVisible, + baseColorConfig, + updateStaticColor, }; }, }); @@ -294,6 +335,43 @@ export default defineComponent({ Enabled + + + + + + + + + {{ + valueDisplayCheckbox('opacity') ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline' }} + + Opacity + {{ currentLayerType.opacity.toFixed(2) }} + + + + + - + {{ valueDisplayCheckbox('selectColor') ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline' }} @@ -401,79 +479,68 @@ export default defineComponent({ - + - - + + {{ - valueDisplayCheckbox('opacity') ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline' }} + valueDisplayCheckbox('zoom') ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline' }} - Opacity - {{ currentLayerType.opacity.toFixed(2) }} + Zoom Min/Max - - + - + - + {{ - valueDisplayCheckbox('zoom') ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline' }} + valueDisplayCheckbox('legend') ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline' }} - Zoom Min/Max - - - + Legend - {{ getColorType() }} + + {{ getColorType() }} + + + + + + + diff --git a/client/src/components/MapLegend.vue b/client/src/components/MapLegend.vue index ed49c9b..0c899e1 100644 --- a/client/src/components/MapLegend.vue +++ b/client/src/components/MapLegend.vue @@ -3,18 +3,31 @@ import { Ref, computed, defineComponent, ref, } from 'vue'; import MapStore from '../MapStore'; -import ColorKey from './ColorKey.vue'; -import FilterKey from './FilterKey.vue'; +import ColorKey from './MapLegends/ColorKey.vue'; +import FilterKey from './MapLegends/FilterKey.vue'; +import OpacityFilter from './MapLegends/ControlsKey.vue'; export default defineComponent({ components: { ColorKey, FilterKey, + OpacityFilter, }, props: { }, setup() { - const selectedNetCDFMapLayers = computed(() => MapStore.selectedNetCDFMapLayers.value); + const selectedNetCDFMapLayers = computed( + () => MapStore.selectedNetCDFMapLayers.value.filter( + (layer) => MapStore.visibleMapLayers.value.has(`${layer.type}_${layer.id}`), + ), + ); + + const selectedRasterMapLayers = computed( + () => MapStore.selectedRasterMapLayers.value.filter( + (layer) => MapStore.visibleMapLayers.value.has(`${layer.type}_${layer.id}`), + ), + ); + const selectedVectorMapLayers = computed( () => MapStore.selectedVectorMapLayers.value.filter( (layer) => MapStore.visibleMapLayers.value.has(`${layer.type}_${layer.id}`), @@ -29,10 +42,11 @@ export default defineComponent({ }); return exists; }); - const tab: Ref<'colors' | 'filters'> = ref('colors'); + const tab: Ref<'colors' | 'opacity' | 'filters'> = ref('opacity'); return { selectedVectorMapLayers, selectedNetCDFMapLayers, + selectedRasterMapLayers, tab, hasFilters, }; @@ -42,8 +56,8 @@ export default defineComponent({