diff --git a/pdb-plotting/src/main/java/org/lucares/pdb/plot/api/DateTimeRange.java b/pdb-plotting/src/main/java/org/lucares/pdb/plot/api/DateTimeRange.java new file mode 100644 index 0000000..f880888 --- /dev/null +++ b/pdb-plotting/src/main/java/org/lucares/pdb/plot/api/DateTimeRange.java @@ -0,0 +1,26 @@ +package org.lucares.pdb.plot.api; + +import java.time.OffsetDateTime; + +public class DateTimeRange { + private final OffsetDateTime start; + private final OffsetDateTime end; + + public DateTimeRange(final OffsetDateTime start, final OffsetDateTime end) { + this.start = start; + this.end = end; + } + + public OffsetDateTime getStart() { + return start; + } + + public OffsetDateTime getEnd() { + return end; + } + + @Override + public String toString() { + return start + "-" + end; + } +} diff --git a/pdb-plotting/src/main/java/org/lucares/pdb/plot/api/PlotSettings.java b/pdb-plotting/src/main/java/org/lucares/pdb/plot/api/PlotSettings.java index 888c59b..d5bb762 100644 --- a/pdb-plotting/src/main/java/org/lucares/pdb/plot/api/PlotSettings.java +++ b/pdb-plotting/src/main/java/org/lucares/pdb/plot/api/PlotSettings.java @@ -1,14 +1,13 @@ package org.lucares.pdb.plot.api; -import java.time.Instant; import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; import java.util.List; +import java.util.regex.Pattern; -import org.apache.commons.lang3.StringUtils; +import com.google.common.base.Preconditions; public class PlotSettings { @@ -30,9 +29,7 @@ public class PlotSettings { private int limit; - private String dateFrom; - - private String dateRange; + private String dateRangeAsString; private AxisScale yAxisScale; @@ -110,68 +107,24 @@ public class PlotSettings { this.limit = limit; } - public String getDateFrom() { - return dateFrom; - } - - public void setDateFrom(final String dateFrom) { - this.dateFrom = dateFrom; - } - public String getDateRange() { - return dateRange; + return dateRangeAsString; } - public void setDateRange(final String dateRange) { - this.dateRange = dateRange; + public void setDateRange(final String dateRangeAsString) { + this.dateRangeAsString = dateRangeAsString; } - public OffsetDateTime dateFrom() { + public DateTimeRange dateRange() { - if (StringUtils.isEmpty(dateFrom)) { + final String[] startEnd = dateRangeAsString.split(Pattern.quote(" - ")); + Preconditions.checkArgument(startEnd.length == 2, "invalid date range"); - return OffsetDateTime.ofInstant(Instant.ofEpochMilli(Long.MIN_VALUE), ZoneOffset.UTC); - } else { - return LocalDateTime.parse(dateFrom, DATE_FORMAT).atOffset(ZoneOffset.UTC); - } - } + final OffsetDateTime startDate = LocalDateTime.parse(startEnd[0], DATE_FORMAT).atOffset(ZoneOffset.UTC); + final OffsetDateTime endDate = LocalDateTime.parse(startEnd[1], DATE_FORMAT).atOffset(ZoneOffset.UTC); - public OffsetDateTime dateTo() { + return new DateTimeRange(startDate, endDate); - if (StringUtils.isEmpty(dateRange)) { - return OffsetDateTime.ofInstant(Instant.ofEpochMilli(Long.MAX_VALUE), ZoneOffset.UTC); - } else { - final int period = Integer.parseInt(dateRange.split(" ")[0]); - final ChronoUnit unit = toChronoUnit(dateRange.split(" ")[1]); - - return dateFrom().plus(period, unit); - } - } - - private ChronoUnit toChronoUnit(final String string) { - - switch (string) { - case "second": - case "seconds": - return ChronoUnit.SECONDS; - case "minute": - case "minutes": - return ChronoUnit.MINUTES; - case "hour": - case "hours": - return ChronoUnit.HOURS; - case "day": - case "days": - return ChronoUnit.DAYS; - case "week": - case "weeks": - return ChronoUnit.WEEKS; - case "month": - case "months": - return ChronoUnit.MONTHS; - default: - throw new IllegalArgumentException(string + " is an unknown chrono unit"); - } } public void setYAxisScale(final AxisScale axisScale) { @@ -186,7 +139,7 @@ public class PlotSettings { public String toString() { return "PlotSettings [query=" + query + ", height=" + height + ", width=" + width + ", thumbnailMaxWidth=" + thumbnailMaxWidth + ", thumbnailMaxHeight=" + thumbnailMaxHeight + ", groupBy=" + groupBy - + ", limitBy=" + limitBy + ", limit=" + limit + ", dateFrom=" + dateFrom + ", dateRange=" + dateRange + + ", limitBy=" + limitBy + ", limit=" + limit + ", dateRangeAsString=" + dateRangeAsString + ", yAxisScale=" + yAxisScale + ", aggregate=" + aggregate + ", yRangeMin=" + yRangeMin + ", yRangeMax=" + yRangeMax + ", yRangeUnit=" + yRangeUnit + ", keyOutside=" + keyOutside + ", generateThumbnail=" + generateThumbnail + "]"; diff --git a/pdb-plotting/src/main/java/org/lucares/recommind/logs/ScatterPlot.java b/pdb-plotting/src/main/java/org/lucares/recommind/logs/ScatterPlot.java index a0c4ce6..f50e31b 100644 --- a/pdb-plotting/src/main/java/org/lucares/recommind/logs/ScatterPlot.java +++ b/pdb-plotting/src/main/java/org/lucares/recommind/logs/ScatterPlot.java @@ -28,6 +28,7 @@ import org.lucares.pdb.api.GroupResult; import org.lucares.pdb.api.Result; import org.lucares.pdb.api.Tags; import org.lucares.pdb.plot.api.CustomAggregator; +import org.lucares.pdb.plot.api.DateTimeRange; import org.lucares.pdb.plot.api.Limit; import org.lucares.pdb.plot.api.PlotSettings; import org.lucares.pdb.plot.api.TimeRangeUnitInternal; @@ -78,8 +79,9 @@ public class ScatterPlot { final List groupBy = plotSettings.getGroupBy(); final int height = plotSettings.getHeight(); final int width = plotSettings.getWidth(); - final OffsetDateTime dateFrom = plotSettings.dateFrom(); - final OffsetDateTime dateTo = plotSettings.dateTo(); + final DateTimeRange dateRange = plotSettings.dateRange(); + final OffsetDateTime dateFrom = dateRange.getStart(); + final OffsetDateTime dateTo = dateRange.getEnd(); final Result result = db.get(query, groupBy); @@ -117,7 +119,7 @@ public class ScatterPlot { final GnuplotSettings gnuplotSettings = new GnuplotSettings(outputFile); gnuplotSettings.setHeight(height); gnuplotSettings.setWidth(width); - defineXAxis(gnuplotSettings, plotSettings.dateFrom(), plotSettings.dateTo()); + defineXAxis(gnuplotSettings, plotSettings.dateRange()); gnuplotSettings.setYAxisScale(plotSettings.getYAxisScale()); gnuplotSettings.setAggregate(plotSettings.getAggregate()); @@ -134,7 +136,7 @@ public class ScatterPlot { final GnuplotSettings gnuplotSettings = new GnuplotSettings(thumbnail); gnuplotSettings.setHeight(plotSettings.getThumbnailMaxHeight()); gnuplotSettings.setWidth(plotSettings.getThumbnailMaxWidth()); - defineXAxis(gnuplotSettings, plotSettings.dateFrom(), plotSettings.dateTo()); + defineXAxis(gnuplotSettings, plotSettings.dateRange()); gnuplotSettings.setYAxisScale(plotSettings.getYAxisScale()); gnuplotSettings.setAggregate(plotSettings.getAggregate()); @@ -169,9 +171,10 @@ public class ScatterPlot { } } - private void defineXAxis(final GnuplotSettings gnuplotSettings, final OffsetDateTime minDate, - final OffsetDateTime maxDate) { + private void defineXAxis(final GnuplotSettings gnuplotSettings, final DateTimeRange dateTimeRange) { + final OffsetDateTime minDate = dateTimeRange.getStart(); + final OffsetDateTime maxDate = dateTimeRange.getEnd(); String formatX; int rotateX; String formattedMinDate; diff --git a/pdb-ui/src/main/java/org/lucares/pdbui/PdbController.java b/pdb-ui/src/main/java/org/lucares/pdbui/PdbController.java index 954f08c..a8c6cfe 100644 --- a/pdb-ui/src/main/java/org/lucares/pdbui/PdbController.java +++ b/pdb-ui/src/main/java/org/lucares/pdbui/PdbController.java @@ -150,8 +150,7 @@ public class PdbController implements HardcodedValues, PropertyKeys { @RequestParam(name = "groupBy[]", defaultValue = "") final List aGroupBy, @RequestParam(name = "limitBy.number", defaultValue = "10") final int limit, @RequestParam(name = "limitBy.selected", defaultValue = "NO_LIMIT") final Limit limitBy, - @RequestParam(name = "dateFrom", defaultValue = "") final String dateFrom, - @RequestParam(name = "dateRange", defaultValue = "1 week") final String dateRange, + @RequestParam(name = "dateRange") final String dateRange, @RequestParam(name = "axisScale", defaultValue = "LINEAR") final AxisScale axisScale, @RequestParam(name = "aggregate", defaultValue = "NONE") final Aggregate aggregate, @RequestParam(name = "keyOutside", defaultValue = "false") final boolean keyOutside, @@ -163,6 +162,10 @@ public class PdbController implements HardcodedValues, PropertyKeys { throw new BadRequest("The query must not be empty!"); } + if (StringUtils.isBlank(dateRange)) { + throw new BadRequest("The parameter 'dateRange' must be set."); + } + final PlotSettings plotSettings = new PlotSettings(); plotSettings.setQuery(query); plotSettings.setGroupBy(aGroupBy); @@ -170,7 +173,6 @@ public class PdbController implements HardcodedValues, PropertyKeys { plotSettings.setWidth(hidth); plotSettings.setLimit(limit); plotSettings.setLimitBy(limitBy); - plotSettings.setDateFrom(dateFrom); plotSettings.setDateRange(dateRange); plotSettings.setYAxisScale(axisScale); plotSettings.setAggregate(PlotSettingsTransformer.toAggregateInternal(aggregate)); diff --git a/pdb-ui/src/main/java/org/lucares/pdbui/PlotSettingsTransformer.java b/pdb-ui/src/main/java/org/lucares/pdbui/PlotSettingsTransformer.java index 378dd26..20fb1eb 100644 --- a/pdb-ui/src/main/java/org/lucares/pdbui/PlotSettingsTransformer.java +++ b/pdb-ui/src/main/java/org/lucares/pdbui/PlotSettingsTransformer.java @@ -21,7 +21,6 @@ class PlotSettingsTransformer { result.setWidth(request.getWidth()); result.setLimit(request.getLimit()); result.setLimitBy(request.getLimitBy()); - result.setDateFrom(request.getDateFrom()); result.setDateRange(request.getDateRange()); result.setYAxisScale(request.getAxisScale()); result.setAggregate(toAggregateInternal(request.getAggregate())); diff --git a/pdb-ui/src/main/java/org/lucares/pdbui/domain/PlotRequest.java b/pdb-ui/src/main/java/org/lucares/pdbui/domain/PlotRequest.java index 77c1e6e..3c06b57 100644 --- a/pdb-ui/src/main/java/org/lucares/pdbui/domain/PlotRequest.java +++ b/pdb-ui/src/main/java/org/lucares/pdbui/domain/PlotRequest.java @@ -24,8 +24,6 @@ public class PlotRequest { private int limit = Integer.MAX_VALUE; - private String dateFrom; - private String dateRange; private Aggregate aggregate = Aggregate.NONE; @@ -107,22 +105,11 @@ public class PlotRequest { this.limit = limit; } - public String getDateFrom() { - return dateFrom; - } - - public void setDateFrom(final String dateFrom) { - this.dateFrom = dateFrom; - } - public String getDateRange() { return dateRange; } public void setDateRange(final String dateRange) { - if (!dateRange.matches("\\d+ (second|minute|hour|day|week|month)s?")) { - throw new IllegalArgumentException(dateRange + " is not a valid range"); - } this.dateRange = dateRange; } diff --git a/pdb-ui/src/main/resources/resources/css/design.css b/pdb-ui/src/main/resources/resources/css/design.css index d0b771f..291c534 100644 --- a/pdb-ui/src/main/resources/resources/css/design.css +++ b/pdb-ui/src/main/resources/resources/css/design.css @@ -138,8 +138,8 @@ textarea { width: 4em; } -.input_date { - max-width: 10em; +#search-date-range { + width: 38ex; } #add-filter { diff --git a/pdb-ui/src/main/resources/resources/js/ui.js b/pdb-ui/src/main/resources/resources/js/ui.js index f41b6c2..4db7529 100644 --- a/pdb-ui/src/main/resources/resources/js/ui.js +++ b/pdb-ui/src/main/resources/resources/js/ui.js @@ -11,6 +11,8 @@ function ffHasParentWithId(el, id) { return false; }; +const DATE_PATTERN = "YYYY-MM-DD HH:mm:ss"; // for moment-JS + window.onload=function(){ const gnuplotLMargin = 110; // The left margin configured for gnuplot @@ -24,6 +26,8 @@ moment.locale('en', { } }); + + Vue.config.keyCodes.arrowUp = 38; Vue.config.keyCodes.arrowDown = 40; @@ -225,23 +229,22 @@ Vue.component('result-view', { return x > gnuplotLMargin && x < imageWith - gnuplotRMargin; }, drag_start: function(event) { + event.preventDefault(); if (event.buttons == 1 && this.isInPlot(event.x) && !data.searchBar.imageLastUsedParams.keyOutside) { - //console.log("drag-start " +event.x+ " " + event.buttons); this.in_drag_mode = true; this.drag_start_x = event.x; this.drag_end_x = event.x; } }, dragging: function(event) { + if (this.in_drag_mode && event.buttons == 1 && this.isInPlot(event.x) && !data.searchBar.imageLastUsedParams.keyOutside){ - //console.log("dragging " + event.layerX+ " " + event.x + " button: " + event.buttons); this.drag_end_x = event.x; const left = this.drag_start_x < this.drag_end_x ? this.drag_start_x : this.drag_end_x; const width = Math.abs(this.drag_start_x - this.drag_end_x); this.zoomInSliderStyle="position: absolute; left: "+left+"px; width: "+width+"px; top:"+gnuplotTMargin+"px; bottom: "+gnuplotBMargin+"px;"; - //console.log(this.zoomInSliderStyle); } }, drag_stop: function(event) { @@ -251,9 +254,7 @@ Vue.component('result-view', { // Zoom in if the selected area has some arbitrary minimal size if (Math.abs(this.drag_start_x - this.drag_end_x) > 10) { - const dateFrom = data.searchBar.imageLastUsedParams.dateFrom; - const dateRange = data.searchBar.imageLastUsedParams.dateRange; - + const dateRange = parseDateRange(data.searchBar.imageLastUsedParams.dateRange); const startPxInImage = Math.min(this.drag_start_x, this.drag_end_x); const endPxInImage = Math.max(this.drag_start_x, this.drag_end_x); @@ -264,16 +265,10 @@ Vue.component('result-view', { const endPxWithinPlotArea = endPxInImage - gnuplotLMargin; const startPercentOfDateRange = startPxWithinPlotArea / widthPlotArea; - const intervalPercentOfDateRange = (endPxWithinPlotArea- startPxWithinPlotArea) / widthPlotArea; + const endPercentOfDateRange = 1-endPxWithinPlotArea / widthPlotArea; - const dateRangeInSeconds = this.dateRangeToSeconds(dateRange); - const newStartDate = this.shiftDateBySeconds(dateFrom, dateRangeInSeconds * startPercentOfDateRange); - const newDateRangeInSeconds = Math.max(60, dateRangeInSeconds * intervalPercentOfDateRange); - const newDateRange = Math.ceil(newDateRangeInSeconds) + " seconds"; + shiftDate(data.searchBar.imageLastUsedParams.dateRange, startPercentOfDateRange, -1*endPercentOfDateRange); - console.log("new range: "+newStartDate+" with interval "+newDateRange); - data.searchBar.dateFrom = newStartDate; - data.searchBar.dateRange = newDateRange; plotCurrent(); } } @@ -283,51 +278,6 @@ Vue.component('result-view', { this.drag_start_x = 0; this.drag_end_x = 0; this.zoomInSliderStyle="display: none;"; - }, - shiftDateBySeconds: function(date, shiftInSeconds) { - var oldDate = Date.parse(date); - var newDate = oldDate.add({seconds: shiftInSeconds}); - return newDate.toString("yyyy-MM-dd HH:mm:ss"); - }, - dateRangeToSeconds: function(dateRange){ - var tokens = dateRange.split(/ +/,2); - - var newValue = -1; - if(tokens.length == 2) - { - var value = parseInt(tokens[0]); - var period = tokens[1]; - switch (period) { - case "second": - case "seconds": - newValue = value; - break; - case "minute": - case "minutes": - newValue = value * 60; - break; - case "hour": - case "hours": - newValue = value * 60*60; - break; - case "day": - case "days": - newValue = value * 24*60*60; - break; - case "week": - case "weeks": - newValue = value * 7*24*60*60; - break; - case "month": - case "months": - newValue = value * 30*7*24*60*60; - break; - default: - console.log("unhandled value: "+ period); - break; - } - } - return newValue; } }, computed: { @@ -546,155 +496,33 @@ Vue.component('navigation-bar', { }, zoomIn: function() { - this.shiftDate(0.25); - this.zoom(0.5); + shiftDate(data.searchBar.dateRange, 0.25, -0.25); plotCurrent(); }, zoomOut: function() { - this.shiftDate(-0.5); - this.zoom(2); + shiftDate(data.searchBar.dateRange, -0.5, 0.5); plotCurrent(); }, dateLeftShift: function() { - this.shiftDate(-1); + shiftDate(data.searchBar.dateRange, -1, -1); plotCurrent(); }, dateHalfLeftShift: function() { - this.shiftDate(-0.5); + shiftDate(data.searchBar.dateRange, -0.5, -0.5); plotCurrent(); }, dateHalfRightShift: function() { - this.shiftDate(0.5); + shiftDate(data.searchBar.dateRange, 0.5, 0.5); plotCurrent(); }, dateRightShift: function() { - this.shiftDate(1); + shiftDate(data.searchBar.dateRange, 1, 1); plotCurrent(); - }, - zoom: function(factor) - { - if (!$('#search-date-range').is(":invalid")) { - - var dateRange = data.searchBar.dateRange; - var tokens = dateRange.split(/ +/,2); - - if(tokens.length == 2) - { - var value = parseInt(tokens[0]); - var period = tokens[1]; - - var newValue = value*factor; - while (newValue != Math.round(newValue)){ - - switch (period) { - case "second": - case "seconds": - if (value == 1) { - // we reached the smallest range - } - else if (value % 2 == 1){ - value = value -1; - } - break; - case "minute": - case "minutes": - value = value * 60; - period = "seconds"; - break; - case "hour": - case "hours": - value = value * 60; - period = "minutes"; - break; - case "day": - case "days": - value = value * 24; - period = "hours"; - break; - case "week": - case "weeks": - value = value * 7; - period = "days"; - break; - case "month": - case "months": - value = value * 30; - period = "days"; - break; - default: - console.log("unhandled value: "+ period); - break; - } - - newValue = value*factor - } - - - data.searchBar.dateRange = newValue + " " + period; - } - } - }, - shiftDate: function(directionalFactor) - { - var dateBefore = Date.parse(data.searchBar.dateFrom); - var newDate = this.shiftByInterval(dateBefore, directionalFactor); - data.searchBar.dateFrom = newDate.toString("yyyy-MM-dd HH:mm:ss"); - }, - shiftByInterval: function(date, directionalFactor) - { - if (!$('#search-date-range').is(":invalid")) { - - var dateRange = data.searchBar.dateRange; - var tokens = dateRange.split(/ +/,2); - - if(tokens.length == 2) - { - var value = parseInt(tokens[0]); - var period = tokens[1]; - var config = {}; - - value = directionalFactor * value; - - switch (period) { - case "second": - case "seconds": - config = { seconds: value }; - break; - case "minute": - case "minutes": - config = { minutes: value }; - break; - case "hour": - case "hours": - config = { minutes: 60*value }; - break; - case "day": - case "days": - config = { days: value }; - break; - case "week": - case "weeks": - config = { days: 7*value }; - break; - case "month": - case "months": - config = { days: 30*value }; - break; - - default: - break; - } - - var newDate = date.add(config); - return newDate; - } - } - return date; } }, computed: { @@ -733,10 +561,8 @@ Vue.component('group-by-item', { Vue.component('search-bar', { props: ['searchBar'], mounted: function() { - $('#search-date-from').daterangepicker({ + $('#search-date-range').daterangepicker({ timePicker: true, - singleDatePicker: true, - startDate: Date.parse(data.searchBar.dateFrom), minDate: "2017-01-01", maxDate: moment(), maxYear: parseInt(moment().format('YYYY'),10), @@ -758,15 +584,18 @@ Vue.component('search-bar', { 'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')] }, }); - $('#search-date-from').on('apply.daterangepicker', function(ev, picker) { - data.searchBar.dateFrom = picker.startDate.format('YYYY-MM-DD HH:mm:ss'); + $('#search-date-range').on('apply.daterangepicker', function(ev, picker) { + setDateRange(picker.startDate, picker.endDate); }); }, watch: { - // whenever searchBar.dateFrom changes, this function will run - 'searchBar.dateFrom': function (newDateFrom, oldDateFrom) { - const newDate = Date.parse(newDateFrom); - $('#search-date-from').data('daterangepicker').setStartDate(newDate); + // whenever searchBar.dateRange changes, this function will run + 'searchBar.dateRange': function (newdateRangeAsString, olddateRangeAsString) { + if (newdateRangeAsString) { + const newdateRange = parseDateRange(newdateRangeAsString); + $('#search-date-range').data('daterangepicker').setStartDate(newdateRange.startDate); + $('#search-date-range').data('daterangepicker').setEndDate(newdateRange.endDate); + } } }, methods: { @@ -825,7 +654,6 @@ Vue.component('search-bar', { 'splitByKeys.selected': data.searchBar.splitByKeys.selected, 'limitBy.selected': data.searchBar.limitBy.selected, 'limitBy.number': data.searchBar.limitBy.number, - 'dateFrom': data.searchBar.dateFrom, 'dateRange': data.searchBar.dateRange, 'axisScale': data.searchBar.axisScale, 'aggregate': data.searchBar.aggregate, @@ -888,40 +716,13 @@ Vue.component('search-bar', {
- + - -
- -
- - - -
@@ -1049,8 +850,7 @@ var data = { 'selected': GetURLParameter('limitBy.selected','NO_LIMIT'), 'number': GetURLParameter('limitBy.number',10) }, - dateFrom: GetURLParameter('dateFrom', Date.now().add({ days: -7 }).toString("yyyy-MM-dd HH:mm:ss")), // '2018-01-05 09:03' - dateRange: GetURLParameter('dateRange','1 week'), + dateRange: GetURLParameter('dateRange', moment().add({ days: -6 }).startOf('day').format(DATE_PATTERN)+ ' - '+ moment().endOf('day').format(DATE_PATTERN)), // '2018-01-05 09:03:03' axisScale: GetURLParameter('axisScale','LOG10'), aggregate: GetURLParameter('aggregate','NONE'), yRange: { @@ -1096,6 +896,46 @@ var data = { } }; +function parseDateRange(dateRangeAsString){ + + if (dateRangeAsString) { + const startDate = moment(dateRangeAsString.slice(0, 19)); + const endDate = moment(dateRangeAsString.slice(22, 41)); + + return { + startDate: startDate, + endDate: endDate, + duration: moment.duration(endDate.diff(startDate)) + }; + } +} + +function setDateRange(startDate, endDate) { + const formattedStartDate = startDate.format(DATE_PATTERN); + const formattedEndDate = endDate.format(DATE_PATTERN); + + data.searchBar.dateRange = formattedStartDate+" - "+formattedEndDate; +} + +/** + * Zoom in/out or shift date by adding factorStartDate*dateRangeInSeconds seconds to the start date + * and factorEndDate*dateRangeInSeconds seconds to the end date. + * + * shiftDate(dateRangeAsString, 0.25, -0.25) will zoom in, making the range half its size + * shiftDate(dateRangeAsString, -0.5, 0.5) will zoom out, making the range double its size + * shiftDate(dateRangeAsString, -0.5, -0.5) will move the range by half its size to older values + * shiftDate(dateRangeAsString, 1, 1) will move the range by its size to newer values + */ +function shiftDate(dateRange, factorStartDate, factorEndDate) +{ + const dateRangeParsed = parseDateRange(dateRange); + const dateRangeInSeconds = dateRangeParsed.duration.asSeconds(); + + const newStartDate = dateRangeParsed.startDate.add({seconds: dateRangeInSeconds*factorStartDate}); + const newEndDate = dateRangeParsed.endDate.add({seconds: dateRangeInSeconds*factorEndDate}); + + setDateRange(newStartDate, newEndDate); +} function showLoadingIcon() { @@ -1165,7 +1005,6 @@ function createRequest(query, generateThumbnail){ request['groupBy'] = groupBy(); request['limitBy'] = data.searchBar.limitBy.selected; request['limit'] = parseInt(data.searchBar.limitBy.number); - request['dateFrom'] = data.searchBar.dateFrom; request['dateRange'] = data.searchBar.dateRange; request['axisScale'] = data.searchBar.axisScale; request['aggregate'] = data.searchBar.aggregate; @@ -1219,7 +1058,6 @@ function updateImageLink(query) { 'splitByKeys.selected': data.searchBar.splitByKeys.selected, 'limitBy.selected': data.searchBar.limitBy.selected, 'limitBy.number': data.searchBar.limitBy.number, - 'dateFrom': data.searchBar.dateFrom, 'dateRange': data.searchBar.dateRange, 'axisScale': data.searchBar.axisScale, 'aggregate': data.searchBar.aggregate,