# HG changeset patch # User Sascha Wilde # Date 1563803059 -7200 # Node ID 1b6e1d79a0ca0919f525e668962e7dacb2580999 # Parent 9cfc6f4781575c0cdd8663d6540e3f82806b79d3# Parent b10f210af325094781a4a2247ca2b56b04bbf6f9 Merged diff -r 9cfc6f478157 -r 1b6e1d79a0ca .dockerignore --- a/.dockerignore Wed Jul 17 18:47:42 2019 +0200 +++ b/.dockerignore Mon Jul 22 15:44:19 2019 +0200 @@ -7,6 +7,7 @@ cmd/gemma/gemma # Dependency directories +.buildbase **/node_modules # local dotenv environment variables file diff -r 9cfc6f478157 -r 1b6e1d79a0ca .hgtags --- a/.hgtags Wed Jul 17 18:47:42 2019 +0200 +++ b/.hgtags Mon Jul 22 15:44:19 2019 +0200 @@ -11,3 +11,4 @@ b166cb97b98a40f33e977c96e65e79bf22e92fca v3.1 b166cb97b98a40f33e977c96e65e79bf22e92fca v3.1 d78af8354b95cea86744459f350edb16662dadd0 v3.1 +5396581cf20334cbc5e69280e5d9b192640d96b9 v4-preview20190717 diff -r 9cfc6f478157 -r 1b6e1d79a0ca client/src/components/fairway/AvailableFairwayDepth.vue --- a/client/src/components/fairway/AvailableFairwayDepth.vue Wed Jul 17 18:47:42 2019 +0200 +++ b/client/src/components/fairway/AvailableFairwayDepth.vue Mon Jul 22 15:44:19 2019 +0200 @@ -169,12 +169,18 @@ const w = [this.widthlimit1, this.widthlimit2].sort(); const lowerBound = [d[0], w[0]].filter(x => x).join(", "); const upperBound = [d[1], w[1]].filter(x => x).join(", "); - return [ - `> LDC`, - `>= ${upperBound}`, - `< ${upperBound}`, - `< ${lowerBound}` - ]; + let result; + if (this.depthlimit1 !== this.depthlimit2) { + result = [ + `> LDC`, + `>= ${upperBound}`, + `< ${upperBound}`, + `< ${lowerBound}` + ]; + } else { + result = [`> LDC`, `>= ${upperBound}`, `< ${upperBound}`]; + } + return result; }, dataLink() { return `data:text/csv;charset=utf-8, ${encodeURIComponent(this.csv)}`; @@ -265,28 +271,56 @@ y = this.pdf.height - offset.y - this.getTextHeight(6); } - this.pdf.doc.setTextColor(color); - this.pdf.doc.setDrawColor(this.$options.COLORS.LDC); - this.pdf.doc.setFillColor(this.$options.COLORS.LDC); - this.pdf.doc.roundedRect(x, y, 10, 4, 1.5, 1.5, "FD"); - this.pdf.doc.text(this.legend[0], x + 12, y + 3); + if (this.legend[3]) { + this.pdf.doc.setTextColor(color); + this.pdf.doc.setDrawColor(this.$options.COLORS.LDC); + this.pdf.doc.setFillColor(this.$options.COLORS.LDC); + this.pdf.doc.roundedRect(x, y, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legend[0], x + 12, y + 3); + + this.pdf.doc.setDrawColor(this.$options.COLORS.HIGHEST); + this.pdf.doc.setFillColor(this.$options.COLORS.HIGHEST); + this.pdf.doc.roundedRect(x, y + 5, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legend[1], x + 12, y + 8); + + this.pdf.doc.setDrawColor(this.$options.COLORS.REST[1]); + this.pdf.doc.setFillColor(this.$options.COLORS.REST[1]); + this.pdf.doc.roundedRect(x, y + 10, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legend[2], x + 12, y + 13); - this.pdf.doc.setDrawColor(this.$options.COLORS.REST[0]); - this.pdf.doc.setFillColor(this.$options.COLORS.REST[0]); - this.pdf.doc.roundedRect(x, y + 5, 10, 4, 1.5, 1.5, "FD"); - this.pdf.doc.text(this.legend[1], x + 12, y + 8); + this.pdf.doc.setDrawColor(this.$options.COLORS.REST[0]); + this.pdf.doc.setFillColor(this.$options.COLORS.REST[0]); + this.pdf.doc.roundedRect(x, y + 15, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legend[3], x + 12, y + 18); + } else { + this.pdf.doc.setTextColor(color); + this.pdf.doc.setDrawColor(this.$options.COLORS.LDC); + this.pdf.doc.setFillColor(this.$options.COLORS.LDC); + this.pdf.doc.roundedRect(x, y, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legend[0], x + 12, y + 3); - this.pdf.doc.setDrawColor(this.$options.COLORS.REST[1]); - this.pdf.doc.setFillColor(this.$options.COLORS.REST[1]); - this.pdf.doc.roundedRect(x, y + 10, 10, 4, 1.5, 1.5, "FD"); - this.pdf.doc.text(this.legend[2], x + 12, y + 13); + this.pdf.doc.setDrawColor(this.$options.COLORS.HIGHEST); + this.pdf.doc.setFillColor(this.$options.COLORS.HIGHEST); + this.pdf.doc.roundedRect(x, y + 5, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legend[1], x + 12, y + 8); - this.pdf.doc.setDrawColor(this.$options.COLORS.HIGHEST); - this.pdf.doc.setFillColor(this.$options.COLORS.HIGHEST); - this.pdf.doc.roundedRect(x, y + 15, 10, 4, 1.5, 1.5, "FD"); - this.pdf.doc.text(this.legend[3], x + 12, y + 18); + this.pdf.doc.setDrawColor(this.$options.COLORS.REST[0]); + this.pdf.doc.setFillColor(this.$options.COLORS.REST[0]); + this.pdf.doc.roundedRect(x, y + 10, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legend[2], x + 12, y + 13); + } }, legendStyle(index) { + if (this.depthlimit1 === this.depthlimit2) { + let result = [ + `background-color: ${this.$options.COLORS.LDC};`, + `background-color: ${this.$options.COLORS.HIGHEST};` + ]; + this.fwData[0].lowerLevels.forEach((e, i) => { + result.push(`background-color: ${this.$options.COLORS.REST[i]};`); + }); + return result[index]; + } return [ `background-color: ${this.$options.COLORS.LDC};`, `background-color: ${this.$options.COLORS.HIGHEST};`, diff -r 9cfc6f478157 -r 1b6e1d79a0ca client/src/components/fairway/AvailableFairwayDepthLNWL.vue --- a/client/src/components/fairway/AvailableFairwayDepthLNWL.vue Wed Jul 17 18:47:42 2019 +0200 +++ b/client/src/components/fairway/AvailableFairwayDepthLNWL.vue Mon Jul 22 15:44:19 2019 +0200 @@ -166,12 +166,18 @@ const w = [this.widthlimit1, this.widthlimit2].sort(); const lowerBound = [d[0], w[0]].filter(x => x).join(", "); const upperBound = [d[1], w[1]].filter(x => x).join(", "); - return [ - `> LDC`, - `< ${lowerBound}`, - `< ${upperBound}`, - `>= ${upperBound}` - ]; + let result; + if (this.depthlimit1 !== this.depthlimit2) { + result = [ + `> LDC`, + `< ${lowerBound}`, + `< ${upperBound}`, + `>= ${upperBound}` + ]; + } else { + result = [`> LDC`, `< ${upperBound}`, `>= ${upperBound}`]; + } + return result; }, dataLink() { return `data:text/csv;charset=utf-8, ${encodeURIComponent(this.csv)}`; @@ -206,12 +212,22 @@ }, methods: { legendStyle(index) { - const style = { - 0: `background-color: ${this.$options.LWNLCOLORS.LDC};`, - 1: `background-color: ${this.$options.AFDCOLORS[2]};`, - 2: `background-color: ${this.$options.AFDCOLORS[1]};`, - 3: `background-color: ${this.$options.AFDCOLORS[0]};` - }; + let style; + if (this.depthlimit1 !== this.depthlimit2) { + style = { + 0: `background-color: ${this.$options.LWNLCOLORS.LDC};`, + 1: `background-color: ${this.$options.AFDCOLORS[2]};`, + 2: `background-color: ${this.$options.AFDCOLORS[1]};`, + 3: `background-color: ${this.$options.AFDCOLORS[0]};` + }; + } else { + style = { + 0: `background-color: ${this.$options.LWNLCOLORS.LDC};`, + 1: `background-color: ${this.$options.AFDCOLORS[2]};`, + 2: `background-color: ${this.$options.AFDCOLORS[0]};` + }; + } + return style[index]; }, applyChange() { @@ -262,26 +278,44 @@ if (["bottomright", "bottomleft"].indexOf(position) !== -1) { y = this.pdf.height - offset.y - this.getTextHeight(6); } - this.pdf.doc.setTextColor(color); - this.pdf.doc.setDrawColor(this.$options.LWNLCOLORS.LDC); - this.pdf.doc.setFillColor(this.$options.LWNLCOLORS.LDC); - this.pdf.doc.roundedRect(x, y, 10, 4, 1.5, 1.5, "FD"); - this.pdf.doc.text(this.legendLNWL[0], x + 12, y + 3); + if (this.legendLNWL[3]) { + this.pdf.doc.setTextColor(color); + this.pdf.doc.setDrawColor(this.$options.LWNLCOLORS.LDC); + this.pdf.doc.setFillColor(this.$options.LWNLCOLORS.LDC); + this.pdf.doc.roundedRect(x, y, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legendLNWL[0], x + 12, y + 3); + + this.pdf.doc.setDrawColor(this.$options.AFDCOLORS[2]); + this.pdf.doc.setFillColor(this.$options.AFDCOLORS[2]); + this.pdf.doc.roundedRect(x, y + 5, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legendLNWL[1], x + 12, y + 8); + + this.pdf.doc.setDrawColor(this.$options.AFDCOLORS[1]); + this.pdf.doc.setFillColor(this.$options.AFDCOLORS[1]); + this.pdf.doc.roundedRect(x, y + 10, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legendLNWL[2], x + 12, y + 13); - this.pdf.doc.setDrawColor(this.$options.AFDCOLORS[2]); - this.pdf.doc.setFillColor(this.$options.AFDCOLORS[2]); - this.pdf.doc.roundedRect(x, y + 5, 10, 4, 1.5, 1.5, "FD"); - this.pdf.doc.text(this.legendLNWL[1], x + 12, y + 8); + this.pdf.doc.setDrawColor(this.$options.AFDCOLORS[0]); + this.pdf.doc.setFillColor(this.$options.AFDCOLORS[0]); + this.pdf.doc.roundedRect(x, y + 15, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legendLNWL[3], x + 12, y + 18); + } else { + this.pdf.doc.setTextColor(color); + this.pdf.doc.setDrawColor(this.$options.LWNLCOLORS.LDC); + this.pdf.doc.setFillColor(this.$options.LWNLCOLORS.LDC); + this.pdf.doc.roundedRect(x, y, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legendLNWL[0], x + 12, y + 3); - this.pdf.doc.setDrawColor(this.$options.AFDCOLORS[1]); - this.pdf.doc.setFillColor(this.$options.AFDCOLORS[1]); - this.pdf.doc.roundedRect(x, y + 10, 10, 4, 1.5, 1.5, "FD"); - this.pdf.doc.text(this.legendLNWL[2], x + 12, y + 13); + this.pdf.doc.setDrawColor(this.$options.AFDCOLORS[2]); + this.pdf.doc.setFillColor(this.$options.AFDCOLORS[2]); + this.pdf.doc.roundedRect(x, y + 5, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legendLNWL[1], x + 12, y + 8); - this.pdf.doc.setDrawColor(this.$options.AFDCOLORS[0]); - this.pdf.doc.setFillColor(this.$options.AFDCOLORS[0]); - this.pdf.doc.roundedRect(x, y + 15, 10, 4, 1.5, 1.5, "FD"); - this.pdf.doc.text(this.legendLNWL[3], x + 12, y + 18); + this.pdf.doc.setDrawColor(this.$options.AFDCOLORS[0]); + this.pdf.doc.setFillColor(this.$options.AFDCOLORS[0]); + this.pdf.doc.roundedRect(x, y + 10, 10, 4, 1.5, 1.5, "FD"); + this.pdf.doc.text(this.legendLNWL[2], x + 12, y + 13); + } }, close() { this.$store.commit("application/paneSetup", "DEFAULT"); diff -r 9cfc6f478157 -r 1b6e1d79a0ca client/src/components/fairway/Fairwayprofile.vue --- a/client/src/components/fairway/Fairwayprofile.vue Wed Jul 17 18:47:42 2019 +0200 +++ b/client/src/components/fairway/Fairwayprofile.vue Mon Jul 22 15:44:19 2019 +0200 @@ -411,15 +411,17 @@ svg.attr("height", "100%"); const width = dimensions.width; const height = dimensions.mainHeight; + const offsetY = 15; const currentData = this.currentData; const additionalData = this.additionalData; const { xScale, yScaleRight, graph } = this.generateScalesAndGraph({ svg, height, width, - dimensions + dimensions, + offsetY }); - this.drawWaterlevel({ graph, xScale, yScaleRight, height }); + this.drawWaterlevel({ graph, xScale, yScaleRight, height, offsetY }); this.drawLabels({ graph, dimensions }); if (currentData) { this.drawProfile({ @@ -430,7 +432,8 @@ height, color: GROUND_COLOR, strokeColor: "black", - opacity: 1 + opacity: 1, + offsetY }); } if (additionalData) { @@ -442,12 +445,13 @@ height, color: GROUND_COLOR, strokeColor: "#943007", - opacity: 0.6 + opacity: 0.6, + offsetY }); } - this.drawFairway({ graph, xScale, yScaleRight }); + this.drawFairway({ graph, xScale, yScaleRight, offsetY }); }, - drawFairway({ graph, xScale, yScaleRight }) { + drawFairway({ graph, xScale, yScaleRight, offsetY }) { if (this.fairwayData === undefined) { return; } @@ -487,7 +491,8 @@ ) .attr("stroke-opacity", this.getLayerStyle(data.los).strokeOpacity) .attr("stroke-dasharray", this.getLayerStyle(data.los).strokeDash) - .attr("d", fairwayArea); + .attr("d", fairwayArea) + .attr("transform", `translate(0 ${-offsetY})`); }); } }, @@ -510,22 +515,18 @@ .text("Waterlevel [m]"); graph .append("text") - .attr("y", 30) + .attr("y", 0) .attr("x", 0) .attr("dy", "1em") .attr("fill", "black") .style("text-anchor", "middle") .attr("transform", [ - "translate(" + - dimensions.width / 2 + - "," + - dimensions.mainHeight + - ")", + `translate(${dimensions.width / 2} ${dimensions.mainHeight})`, "rotate(0)" ]) .text("Width [m]"); }, - generateScalesAndGraph({ svg, height, width, dimensions }) { + generateScalesAndGraph({ svg, height, width, dimensions, offsetY }) { let xScale = d3 .scaleLinear() .domain([0, this.totalLength]) @@ -568,7 +569,7 @@ ); graph .append("g") - .attr("transform", "translate(0," + height + ")") + .attr("transform", `translate(0 ${height - offsetY})`) .call(xAxis) .selectAll(".tick text") .attr("fill", "black") @@ -579,7 +580,7 @@ .attr("stroke", "black"); graph .append("g") - .attr("transform", "translate(" + width + ",0)") + .attr("transform", `translate(${width} ${-offsetY})`) .call(yAxisRight) .selectAll(".tick text") .attr("fill", "black") @@ -590,7 +591,7 @@ .attr("stroke", "black"); graph .append("g") - .attr("transform", "translate(0 0)") + .attr("transform", `translate(0 ${-offsetY})`) .call(yAxisLeft) .selectAll(".tick text") .attr("fill", "black") @@ -603,7 +604,7 @@ graph.selectAll(".domain").attr("stroke", "black"); return { xScale, yScaleRight, graph }; }, - drawWaterlevel({ graph, xScale, yScaleRight, height }) { + drawWaterlevel({ graph, xScale, yScaleRight, height, offsetY }) { let waterArea = d3 .area() .x(function(d) { @@ -619,7 +620,8 @@ .attr("fill-opacity", 0.65) .attr("fill", WATER_COLOR) .attr("stroke", "transparent") - .attr("d", waterArea); + .attr("d", waterArea) + .attr("transform", `translate(0 ${-offsetY})`); }, drawProfile({ graph, @@ -629,7 +631,8 @@ height, color, strokeColor, - opacity + opacity, + offsetY }) { for (let part of currentData) { let profileLine = d3 @@ -659,7 +662,8 @@ .attr("fill", color) .attr("stroke", "transparent") .attr("fill-opacity", opacity) - .attr("d", profileArea); + .attr("d", profileArea) + .attr("transform", `translate(0 ${-offsetY})`); graph .append("path") .datum(part) @@ -670,7 +674,8 @@ .attr("stroke-width", 3) .attr("stroke-opacity", opacity) .attr("fill-opacity", 0) - .attr("d", profileLine); + .attr("d", profileLine) + .attr("transform", `translate(0 ${-offsetY})`); } }, scaleFairwayProfile() { diff -r 9cfc6f478157 -r 1b6e1d79a0ca client/src/components/layers/Layerselect.vue --- a/client/src/components/layers/Layerselect.vue Wed Jul 17 18:47:42 2019 +0200 +++ b/client/src/components/layers/Layerselect.vue Mon Jul 22 15:44:19 2019 +0200 @@ -59,6 +59,7 @@ "differencesLegendImgDataURL" ]), ...mapGetters("map", ["openLayersMap"]), + ...mapState("bottlenecks", ["selectedSurvey"]), layer() { return this.openLayersMap().getLayer(this.layerId); }, @@ -69,6 +70,18 @@ methods: { toggle(map) { if (map) { + if ( + (this.layerId === "BOTTLENECKISOLINE" || + this.layerId === "DIFFERENCES") && + !this.selectedSurvey + ) { + map + .getLayer(this.layerId) + .getSource() + .updateParams({ + cql_filter: `bottleneck_id='NO_BOTTLENECK_SELECTED'` + }); + } map .getLayer(this.layerId) .setVisible(!map.getLayer(this.layerId).getVisible()); diff -r 9cfc6f478157 -r 1b6e1d79a0ca client/src/components/map/Map.vue --- a/client/src/components/map/Map.vue Wed Jul 17 18:47:42 2019 +0200 +++ b/client/src/components/map/Map.vue Mon Jul 22 15:44:19 2019 +0200 @@ -145,8 +145,8 @@ }, methods: { updateBottleneckFilter(bottleneck_id, datestr) { + if (!bottleneck_id) return; const exists = bottleneck_id != "does_not_exist"; - if (exists) { this.layers .get("BOTTLENECKISOLINE") diff -r 9cfc6f478157 -r 1b6e1d79a0ca client/src/lib/mixins.js --- a/client/src/lib/mixins.js Wed Jul 17 18:47:42 2019 +0200 +++ b/client/src/lib/mixins.js Mon Jul 22 15:44:19 2019 +0200 @@ -18,6 +18,18 @@ import locale2 from "locale2"; import { mapState } from "vuex"; import { HTTP } from "@/lib/http"; +import * as d3 from "d3"; + +/*eslint no-unused-vars: ["error", { "varsIgnorePattern": "debugSVG" }]*/ + +const debugSVG = ({ svg, svgWidth, svgHeight }) => { + d3.select(svg) + .append("rect") + .attr("width", svgWidth) + .attr("height", svgHeight) + .attr("fill-opacity", 0) + .attr("stroke", "#ff0000"); +}; export const sortTable = { data() { @@ -337,10 +349,7 @@ x = this.pdf.width - offset.x - width; } if (["bottomright", "bottomleft"].indexOf(position) !== -1) { - y = - this.pdf.height - - offset.y * 0.3 - - this.getTextHeight(textLines.length); + y = this.pdf.height - offset.y - this.getTextHeight(textLines.length); } this.pdf.doc.text(textLines, x, y, { baseline: "hanging" }); }, @@ -468,14 +477,25 @@ background, brcolor ); - this.addText( - position, - { x: offset.x + padding, y: offset.y + padding * 2 }, - textWidth, - fontSize, - color, - text - ); + if (["bottomright", "bottomleft"].indexOf(position) !== -1) { + this.addText( + position, + { x: offset.x + padding, y: offset.y - padding / 2 }, + textWidth, + fontSize, + color, + text + ); + } else { + this.addText( + position, + { x: offset.x + padding, y: offset.y + padding * 2 }, + textWidth, + fontSize, + color, + text + ); + } } } }; diff -r 9cfc6f478157 -r 1b6e1d79a0ca client/src/store/fairwayavailability.js --- a/client/src/store/fairwayavailability.js Wed Jul 17 18:47:42 2019 +0200 +++ b/client/src/store/fairwayavailability.js Mon Jul 22 15:44:19 2019 +0200 @@ -102,17 +102,31 @@ const transformAFD = csv => { return csv.map(e => { const result = e.split(","); - let [label, _, ldc, lower, middle, highestLevel] = result; - let levelsWithSum = [ + let label, _, ldc, lower, middle, highestLevel; + let levelsWithSum; + if (result.length == 6) { + [label, _, ldc, lower, middle, highestLevel] = result; + levelsWithSum = [ + { + height: Number(lower), + translateY: Number(middle) + }, + { + height: Number(middle), + translateY: 0 + } + ]; + } else { { - height: Number(lower), - translateY: Number(middle) - }, - { - height: Number(middle), - translateY: 0 + [label, _, ldc, middle, highestLevel] = result; + levelsWithSum = [ + { + height: Number(middle), + translateY: 0 + } + ]; } - ]; + } return { label: label, ldc: ldc, @@ -298,13 +312,25 @@ data.shift(); // remove header line data = data.map(d => { let columns = d.split(","); - return { - date: columns[0], - ldc: Number(columns[2]), - below: Number(columns[3]), - between: Number(columns[4]), - above: Number(columns[5]) - }; + let result; + if (columns.length === 6) { + result = { + date: columns[0], + ldc: Number(columns[2]), + below: Number(columns[3]), + between: Number(columns[4]), + above: Number(columns[5]) + }; + } else { + result = { + date: columns[0], + ldc: Number(columns[2]), + below: Number(columns[3]), + between: null, + above: Number(columns[4]) + }; + } + return result; }); commit("setFwLNWLData", data); return data; diff -r 9cfc6f478157 -r 1b6e1d79a0ca client/src/store/gauges.js --- a/client/src/store/gauges.js Wed Jul 17 18:47:42 2019 +0200 +++ b/client/src/store/gauges.js Mon Jul 22 15:44:19 2019 +0200 @@ -13,7 +13,7 @@ */ import { HTTP } from "@/lib/http"; import { WFS } from "ol/format"; -import { isPast } from "date-fns"; +import { isPast, startOfDay, endOfDay, format } from "date-fns"; let dateFrom = new Date(); dateFrom.setDate(dateFrom.getDate() - 30); @@ -136,16 +136,12 @@ }); }, loadWaterlevels({ state, commit }) { - // include the last day - let dateTo = new Date(state.dateTo.getTime() + 86400); - return new Promise((resolve, reject) => { HTTP.get( - `/data/waterlevels/${ - state.selectedGaugeISRS - }?from=${state.dateFrom - .toISOString() - .substr(0, 23)}&to=${dateTo.toISOString().substr(0, 23)}`, + `/data/waterlevels/${state.selectedGaugeISRS}?from=${format( + startOfDay(state.dateFrom), + "YYYY-MM-DDTHH:mm:ss.SSS" + )}&to=${format(endOfDay(state.dateTo), "YYYY-MM-DDTHH:mm:ss.SSS")}`, { headers: { "X-Gemma-Auth": localStorage.getItem("token") } } diff -r 9cfc6f478157 -r 1b6e1d79a0ca docker/Dockerfile.spa --- a/docker/Dockerfile.spa Wed Jul 17 18:47:42 2019 +0200 +++ b/docker/Dockerfile.spa Mon Jul 22 15:44:19 2019 +0200 @@ -7,7 +7,7 @@ RUN apt-get update &&\ apt-get -y install --no-install-recommends \ - curl ca-certificates gnupg nodejs make mercurial + curl ca-certificates gnupg nodejs make mercurial git # Install yarn RUN curl https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - &&\ diff -r 9cfc6f478157 -r 1b6e1d79a0ca schema/gemma.sql --- a/schema/gemma.sql Wed Jul 17 18:47:42 2019 +0200 +++ b/schema/gemma.sql Mon Jul 22 15:44:19 2019 +0200 @@ -477,8 +477,11 @@ date_info timestamp with time zone NOT NULL, source_organization varchar NOT NULL, -- "originator" from NtS response staging_done boolean NOT NULL DEFAULT false, - UNIQUE (location, measure_date, staging_done) + UNIQUE (measure_date, location, staging_done) ) + -- For fast retrieval of newest measurement per location: + CREATE INDEX gauge_measurements_location_measure_date_desc + ON waterway.gauge_measurements (location, measure_date DESC) CREATE TABLE gauge_predictions ( location isrs NOT NULL, @@ -498,7 +501,7 @@ CHECK (conf_interval @> CAST(water_level AS numeric)), date_info timestamp with time zone NOT NULL, source_organization varchar NOT NULL, -- "originator" from NtS response - PRIMARY KEY (location, measure_date, date_issue) + PRIMARY KEY (measure_date, location, date_issue) ) CREATE TABLE waterway_axis ( diff -r 9cfc6f478157 -r 1b6e1d79a0ca schema/geoserver_views.sql --- a/schema/geoserver_views.sql Wed Jul 17 18:47:42 2019 +0200 +++ b/schema/geoserver_views.sql Mon Jul 22 15:44:19 2019 +0200 @@ -94,16 +94,6 @@ FROM waterway.distance_marks; CREATE OR REPLACE VIEW waterway.bottlenecks_geoserver AS - WITH - fairway_availability_latest AS ( - SELECT DISTINCT ON (bottleneck_id) bottleneck_id, date_info, critical - FROM waterway.fairway_availability - ORDER BY bottleneck_id, date_info DESC), - sounding_result_latest AS ( - SELECT DISTINCT ON (bottleneck_id) bottleneck_id, max(date_info) AS date_max - FROM waterway.sounding_results - GROUP BY bottleneck_id - ORDER BY bottleneck_id DESC) SELECT b.id, b.bottleneck_id, @@ -132,9 +122,16 @@ FROM waterway.bottlenecks b LEFT JOIN waterway.gauges_base_view g ON b.gauge_location = g.location AND b.gauge_validity = g.validity - LEFT JOIN fairway_availability_latest fal + LEFT JOIN (SELECT DISTINCT ON (bottleneck_id) + bottleneck_id, date_info, critical + FROM waterway.fairway_availability + ORDER BY bottleneck_id, date_info DESC) AS fal ON b.id = fal.bottleneck_id - LEFT JOIN sounding_result_latest srl + LEFT JOIN (SELECT DISTINCT ON (bottleneck_id) + bottleneck_id, max(date_info) AS date_max + FROM waterway.sounding_results + GROUP BY bottleneck_id + ORDER BY bottleneck_id DESC) AS srl ON b.bottleneck_id = srl.bottleneck_id WHERE b.validity @> current_timestamp; diff -r 9cfc6f478157 -r 1b6e1d79a0ca schema/search_functions.sql --- a/schema/search_functions.sql Wed Jul 17 18:47:42 2019 +0200 +++ b/schema/search_functions.sql Mon Jul 22 15:44:19 2019 +0200 @@ -55,6 +55,7 @@ 'bottleneck' AS type FROM waterway.bottlenecks WHERE objnam ILIKE '%' || search_string || '%' + AND validity @> now() ORDER BY name) r; RETURN _result; END; diff -r 9cfc6f478157 -r 1b6e1d79a0ca schema/update-db.sh --- a/schema/update-db.sh Wed Jul 17 18:47:42 2019 +0200 +++ b/schema/update-db.sh Mon Jul 22 15:44:19 2019 +0200 @@ -103,9 +103,9 @@ if [ -d "$d" ] && [ "$new_ver" -gt $current_ver ] ; then echo "Running updates for $new_ver ..." - sql=$( cat `echo "$d/"* | sort -n` ) - sql+="INSERT INTO gemma_schema_version(version) VALUES ($new_ver);" + psql -1qv ON_ERROR_STOP= -p "$port" -d "$db" \ + $(find "$d" -type f -printf ' -f %p') \ + -c "INSERT INTO gemma_schema_version(version) VALUES ($new_ver)" - psql -1 -q -p "$port" -d "$db" -c "$sql" fi done diff -r 9cfc6f478157 -r 1b6e1d79a0ca schema/updates/1002/01.replace-ctes.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/updates/1002/01.replace-ctes.sql Mon Jul 22 15:44:19 2019 +0200 @@ -0,0 +1,1 @@ +\ir ../../geoserver_views.sql diff -r 9cfc6f478157 -r 1b6e1d79a0ca schema/updates/1003/01.add-indexes.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/updates/1003/01.add-indexes.sql Mon Jul 22 15:44:19 2019 +0200 @@ -0,0 +1,5 @@ +CREATE INDEX gauge_measurements_measure_date + ON waterway.gauge_measurements (measure_date); + +CREATE INDEX gauge_predictions_measure_date + ON waterway.gauge_predictions (measure_date) diff -r 9cfc6f478157 -r 1b6e1d79a0ca schema/updates/1004/01.optimize_index-setup.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/updates/1004/01.optimize_index-setup.sql Mon Jul 22 15:44:19 2019 +0200 @@ -0,0 +1,16 @@ +ALTER TABLE waterway.gauge_measurements + DROP CONSTRAINT gauge_measurements_location_measure_date_staging_done_key; +ALTER TABLE waterway.gauge_measurements + ADD CONSTRAINT gauge_measurements_measure_date_location_staging_done_key + UNIQUE (measure_date, location, staging_done); +DROP INDEX waterway.gauge_measurements_measure_date; + +ALTER TABLE waterway.gauge_predictions + DROP CONSTRAINT gauge_predictions_pkey; +ALTER TABLE waterway.gauge_predictions + ADD CONSTRAINT gauge_predictions_pkey + PRIMARY KEY (measure_date, location, date_issue); +DROP INDEX waterway.gauge_predictions_measure_date; + +CREATE INDEX gauge_measurements_location_measure_date_desc + ON waterway.gauge_measurements (location, measure_date DESC) diff -r 9cfc6f478157 -r 1b6e1d79a0ca schema/updates/1005/01.search-only-valid-bottleneck.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/updates/1005/01.search-only-valid-bottleneck.sql Mon Jul 22 15:44:19 2019 +0200 @@ -0,0 +1,18 @@ +CREATE OR REPLACE FUNCTION search_bottlenecks(search_string text) RETURNS jsonb + LANGUAGE plpgsql STABLE PARALLEL SAFE + AS $$ +DECLARE + _result jsonb; +BEGIN + SELECT COALESCE(json_agg(r),'[]') + INTO _result + FROM (SELECT objnam AS name, + ST_AsGeoJSON(ST_Envelope(area::geometry))::json AS geom, + 'bottleneck' AS type + FROM waterway.bottlenecks + WHERE objnam ILIKE '%' || search_string || '%' + AND validity @> 'now'::timestamptz + ORDER BY name) r; + RETURN _result; +END; +$$; diff -r 9cfc6f478157 -r 1b6e1d79a0ca schema/updates/1006/01.fix-search-only-valid-bottleneck.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/updates/1006/01.fix-search-only-valid-bottleneck.sql Mon Jul 22 15:44:19 2019 +0200 @@ -0,0 +1,18 @@ +CREATE OR REPLACE FUNCTION search_bottlenecks(search_string text) RETURNS jsonb + LANGUAGE plpgsql STABLE PARALLEL SAFE + AS $$ +DECLARE + _result jsonb; +BEGIN + SELECT COALESCE(json_agg(r),'[]') + INTO _result + FROM (SELECT objnam AS name, + ST_AsGeoJSON(ST_Envelope(area::geometry))::json AS geom, + 'bottleneck' AS type + FROM waterway.bottlenecks + WHERE objnam ILIKE '%' || search_string || '%' + AND validity @> now() + ORDER BY name) r; + RETURN _result; +END; +$$; diff -r 9cfc6f478157 -r 1b6e1d79a0ca schema/version.sql --- a/schema/version.sql Wed Jul 17 18:47:42 2019 +0200 +++ b/schema/version.sql Mon Jul 22 15:44:19 2019 +0200 @@ -1,1 +1,1 @@ -INSERT INTO gemma_schema_version(version) VALUES (1001); +INSERT INTO gemma_schema_version(version) VALUES (1006);