@opengeoweb/time-series 20.2.0 → 21.0.0-nightly-20261031

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import React, { useCallback, useMemo, useState, useEffect, memo } from 'react';
3
3
  import { useDispatch, useSelector } from 'react-redux';
4
- import { CustomIconButton, dateUtils, TooltipSelect, referenceTimeUtils, CustomAccordion, CustomTooltip, CustomToggleButton, ToolContainerDraggable, ToggleMenu, CustomDialog, SearchField, SearchHighlight, AlertBanner, useConfirmationDialog, SwitchButton, LegendToggleButton, useResizeObserver } from '@opengeoweb/shared';
4
+ import { CustomIconButton, dateUtils, TooltipSelect, referenceTimeUtils, CustomAccordion, CustomTooltip, CustomToggleButton, ToggleMenu, ToolContainerDraggable, CustomDialog, SearchField, SearchHighlight, AlertBanner, useConfirmationDialog, SwitchButton, ResizablePanel, SortablePanels, LegendToggleButton, useResizeObserver } from '@opengeoweb/shared';
5
5
  import { snackbarActions, snackbarTypes, snackbarListener, snackbarReducer } from '@opengeoweb/snackbar';
6
6
  import { mapUtils, selectorMemoizationOptions, genericSelectors, uiSelectors, uiTypes, uiActions, useSetupDialog, mapSelectors, mapListener, serviceListener, layersListener, syncGroupsListener, genericListener, openlayersListener, uiReducer, syncGroupsReducer, layerReducer, serviceReducer, mapReducer, loadingIndicatorActions, useRegisterFeatureSyncSource, useUpdateFeatureSyncLayers, useSyncgroupTimeState, mapActions, layerActions } from '@opengeoweb/store';
7
7
  import { useTheme, MenuItem, LinearProgress, Grid, Box, Typography, ClickAwayListener, Input, Collapse, Button, List, ListItem, ListItemText, InputAdornment, ListItemButton, styled, Card, Stack, Tooltip, ListItemIcon, Checkbox } from '@mui/material';
8
8
  import { isString, trim, trimStart, compact, chain, groupBy, countBy, sortBy, uniqBy, isEqual } from 'lodash';
9
9
  import { ReactSortable } from 'react-sortablejs';
10
- import { Info, ArrowDropDownDown, Copy, Delete, Visibility, VisibilityOff, TimeSeriesSelect as TimeSeriesSelect$1, DragHandle, ChevronUp, ChevronDown, Add, DimensionsTime, DrawRegion, Cached, Edit, Location, useThemeContext, EChartsDarkTheme, EChartsLightTheme, Layers, LockLocked, LockUnlocked } from '@opengeoweb/theme';
10
+ import { Info, ArrowDropDownDown, Copy, Delete, Visibility, VisibilityOff, TimeSeriesSelect as TimeSeriesSelect$1, DragHandle, ChevronUp, ChevronDown, Options, Add, DimensionsTime, DrawRegion, Cached, Edit, Location, EChartsDarkTheme, EChartsLightTheme, Layers, LockLocked, LockUnlocked } from '@opengeoweb/theme';
11
11
  import i18n from 'i18next';
12
12
  import { useTranslation } from 'react-i18next';
13
13
  import '@opengeoweb/core';
@@ -63,6 +63,8 @@ var en = {
63
63
  "timeseries-plot": "Plot",
64
64
  "timeseries-remove": "Remove",
65
65
  "timeseries-remove-confirm": "Are you sure you want to remove plot \"{{ id }}\"?",
66
+ "timeseries-plot-options": "Options",
67
+ "timeseries-plot-copy-title": "{{title}} (copy {{count}})",
66
68
  "timeseries-duplicate": "Duplicate",
67
69
  "timeseries-drag": "Drag",
68
70
  "timeseries-edit-title": "Edit title",
@@ -178,6 +180,8 @@ var fi = {
178
180
  "timeseries-plot": "Kuvaaja",
179
181
  "timeseries-remove": "Poista",
180
182
  "timeseries-remove-confirm": "Oletko varma, että haluat poistaa kuvaajan: {{ id }}",
183
+ "timeseries-plot-options": "Valinnat",
184
+ "timeseries-plot-copy-title": "{{title}} (copy {{count}})",
181
185
  "timeseries-duplicate": "Monista",
182
186
  "timeseries-drag": "Raahaa",
183
187
  "timeseries-edit-title": "Muokkaa otsikkoa",
@@ -292,6 +296,8 @@ var no = {
292
296
  "timeseries-plot": "Plott",
293
297
  "timeseries-remove": "Fjern",
294
298
  "timeseries-remove-confirm": "Er du sikker på at du vil fjerne plott \"{{ id }}\"?",
299
+ "timeseries-plot-options": "Alternativer",
300
+ "timeseries-plot-copy-title": "{{title}} (copy {{count}})",
295
301
  "timeseries-duplicate": "Dupliser",
296
302
  "timeseries-drag": "Dra",
297
303
  "timeseries-edit-title": "Endre tittel",
@@ -410,6 +416,8 @@ var nl = {
410
416
  "timeseries-plot": "Plot",
411
417
  "timeseries-remove": "Verwijderen",
412
418
  "timeseries-remove-confirm": "Weet je zeker dat je plot \"{{ id }}\" wilt verwijderen?",
419
+ "timeseries-plot-options": "Opties",
420
+ "timeseries-plot-copy-title": "{{title}} (copy {{count}})",
413
421
  "timeseries-duplicate": "Dupliceren",
414
422
  "timeseries-drag": "Slepen",
415
423
  "timeseries-edit-title": "Titel bewerken",
@@ -1208,6 +1216,55 @@ var panelSlice = createSlice({
1208
1216
  plotId: generateTimeSeriesId()
1209
1217
  });
1210
1218
  },
1219
+ setPlotIsOpen: function setPlotIsOpen(draft, action) {
1220
+ var _draft$plotPreset;
1221
+ var plot = (_draft$plotPreset = draft.plotPreset) == null ? void 0 : _draft$plotPreset.plots.find(function (item) {
1222
+ return item.plotId === action.payload.plotId;
1223
+ });
1224
+ if (plot) {
1225
+ plot.isOpen = action.payload.isOpen;
1226
+ }
1227
+ },
1228
+ setPlotSize: function setPlotSize(draft, action) {
1229
+ draft.plotPreset.plots = draft.plotPreset.plots.map(function (plot) {
1230
+ if (plot.plotId === action.payload.plotId) {
1231
+ return Object.assign({}, plot, {
1232
+ customSize: action.payload.size
1233
+ });
1234
+ }
1235
+ return plot;
1236
+ });
1237
+ },
1238
+ duplicatePlot: function duplicatePlot(draft, action) {
1239
+ var _preset$parameters;
1240
+ var preset = draft.plotPreset;
1241
+ var sourceIndex = preset ? preset.plots.findIndex(function (plot) {
1242
+ return plot.plotId === action.payload.plotId;
1243
+ }) : -1;
1244
+ if (!preset || sourceIndex < 0) {
1245
+ return;
1246
+ }
1247
+ var source = preset.plots[sourceIndex];
1248
+ var newPlotId = generateTimeSeriesId();
1249
+ var duplicatedPlot = Object.assign({}, source, {
1250
+ title: action.payload.title,
1251
+ plotId: newPlotId
1252
+ });
1253
+ var duplicatedParameters = preset.parameters.filter(function (parameter) {
1254
+ return parameter.plotId === source.plotId;
1255
+ }).map(function (parameter) {
1256
+ return Object.assign({}, parameter, {
1257
+ id: generateParameterId(),
1258
+ plotId: newPlotId
1259
+ }, parameter.dimensions ? {
1260
+ dimensions: parameter.dimensions.map(function (dimension) {
1261
+ return Object.assign({}, dimension);
1262
+ })
1263
+ } : {});
1264
+ });
1265
+ preset.plots.splice(sourceIndex + 1, 0, duplicatedPlot);
1266
+ (_preset$parameters = preset.parameters).push.apply(_preset$parameters, duplicatedParameters);
1267
+ },
1211
1268
  deleteParameter: function deleteParameter(draft, action) {
1212
1269
  draft.plotPreset.parameters = draft.plotPreset.parameters.filter(function (parameter) {
1213
1270
  return parameter.id !== action.payload.parameterId;
@@ -1249,8 +1306,8 @@ var panelSlice = createSlice({
1249
1306
  });
1250
1307
  },
1251
1308
  updateTitle: function updateTitle(draft, action) {
1252
- var _draft$plotPreset;
1253
- var plot = (_draft$plotPreset = draft.plotPreset) == null ? void 0 : _draft$plotPreset.plots.find(function (elem) {
1309
+ var _draft$plotPreset2;
1310
+ var plot = (_draft$plotPreset2 = draft.plotPreset) == null ? void 0 : _draft$plotPreset2.plots.find(function (elem) {
1254
1311
  return elem.plotId === action.payload.plotId;
1255
1312
  });
1256
1313
  if (plot) {
@@ -1264,15 +1321,43 @@ var panelSlice = createSlice({
1264
1321
  }
1265
1322
  },
1266
1323
  movePlot: function movePlot(draft, action) {
1267
- var _draft$plotPreset2;
1324
+ var _draft$plotPreset3;
1268
1325
  var _action$payload = action.payload,
1269
1326
  oldIndex = _action$payload.oldIndex,
1270
1327
  newIndex = _action$payload.newIndex;
1271
- if (!((_draft$plotPreset2 = draft.plotPreset) != null && _draft$plotPreset2.plots)) {
1328
+ if (!((_draft$plotPreset3 = draft.plotPreset) != null && _draft$plotPreset3.plots)) {
1272
1329
  return;
1273
1330
  }
1274
1331
  draft.plotPreset.plots = mapUtils.moveArrayElements(draft.plotPreset.plots, oldIndex, newIndex);
1275
1332
  },
1333
+ reorderPlots: function reorderPlots(draft, action) {
1334
+ var _draft$plotPreset4;
1335
+ var newOrder = action.payload.newOrder;
1336
+ if (!((_draft$plotPreset4 = draft.plotPreset) != null && _draft$plotPreset4.plots)) {
1337
+ return;
1338
+ }
1339
+ var plotsById = new Map(draft.plotPreset.plots.map(function (plot) {
1340
+ return [plot.plotId, plot];
1341
+ }));
1342
+ var orderedPlots = Array.from(new Set(newOrder)).map(function (id) {
1343
+ return plotsById.get(id);
1344
+ }).filter(function (plot) {
1345
+ return plot !== undefined;
1346
+ });
1347
+ var reorderedIds = new Set(orderedPlots.map(function (plot) {
1348
+ return plot.plotId;
1349
+ }));
1350
+ var nextIndex = 0;
1351
+ // Hidden plots are absent from the sortable list and retain their position.
1352
+ draft.plotPreset.plots = draft.plotPreset.plots.map(function (plot) {
1353
+ if (!reorderedIds.has(plot.plotId)) {
1354
+ return plot;
1355
+ }
1356
+ var reorderedPlot = orderedPlots[nextIndex];
1357
+ nextIndex += 1;
1358
+ return reorderedPlot;
1359
+ });
1360
+ },
1276
1361
  moveParameter: function moveParameter(draft, action) {
1277
1362
  var _action$payload2 = action.payload,
1278
1363
  oldIndex = _action$payload2.oldIndex,
@@ -1864,6 +1949,20 @@ var getPlotState = function getPlotState(state, panelId) {
1864
1949
  var _getPanelState;
1865
1950
  return (_getPanelState = getPanelState(state, panelId)) == null ? void 0 : _getPanelState.plotPreset;
1866
1951
  };
1952
+ var getPlotById = function getPlotById(state, panelId, plotId) {
1953
+ var _getPlotState;
1954
+ return (_getPlotState = getPlotState(state, panelId)) == null ? void 0 : _getPlotState.plots.find(function (plot) {
1955
+ return plot.plotId === plotId;
1956
+ });
1957
+ };
1958
+ var getPlotIsOpen = function getPlotIsOpen(state, panelId, plotId) {
1959
+ var plot = getPlotById(state, panelId, plotId);
1960
+ return !!plot && plot.isOpen !== false;
1961
+ };
1962
+ var getPlotCustomSize = function getPlotCustomSize(state, panelId, plotId) {
1963
+ var _getPlotById;
1964
+ return (_getPlotById = getPlotById(state, panelId, plotId)) == null ? void 0 : _getPlotById.customSize;
1965
+ };
1867
1966
  var getTimeSeriesState = function getTimeSeriesState(state, panelId) {
1868
1967
  return getPanelState(state, panelId);
1869
1968
  };
@@ -2166,6 +2265,9 @@ var selectors = /*#__PURE__*/Object.freeze({
2166
2265
  getParameterById: getParameterById,
2167
2266
  getParameterInfoParameter: getParameterInfoParameter,
2168
2267
  getParametersInUse: getParametersInUse,
2268
+ getPlotById: getPlotById,
2269
+ getPlotCustomSize: getPlotCustomSize,
2270
+ getPlotIsOpen: getPlotIsOpen,
2169
2271
  getPlotState: getPlotState,
2170
2272
  getPlotWithParameters: getPlotWithParameters,
2171
2273
  getSearchFilter: getSearchFilter,
@@ -4115,6 +4217,7 @@ var PlotRows = function PlotRows(_ref) {
4115
4217
  rowIndex = _ref.rowIndex,
4116
4218
  showTooltip = _ref.showTooltip,
4117
4219
  deletePlot = _ref.deletePlot,
4220
+ duplicatePlot = _ref.duplicatePlot,
4118
4221
  togglePlot = _ref.togglePlot,
4119
4222
  deleteParameter = _ref.deleteParameter,
4120
4223
  selectPlotId = _ref.selectPlotId,
@@ -4153,17 +4256,10 @@ var PlotRows = function PlotRows(_ref) {
4153
4256
  actions: jsxs(Grid, {
4154
4257
  container: true,
4155
4258
  sx: {
4156
- justifyContent: 'space-between'
4259
+ alignItems: 'center',
4260
+ justifyContent: 'flex-end'
4157
4261
  },
4158
4262
  children: [jsx(CustomIconButton, {
4159
- "data-testid": "deleteButton",
4160
- onClick: function onClick() {
4161
- deletePlot(plot.plotId);
4162
- },
4163
- shouldShowAsDisabled: !plotIsEnabled,
4164
- tooltipTitle: t('timeseries-remove') + " " + plot.title,
4165
- children: jsx(Delete, {})
4166
- }), jsx(CustomIconButton, {
4167
4263
  "data-testid": "openParameterListButton",
4168
4264
  onClick: function onClick(event) {
4169
4265
  event.stopPropagation();
@@ -4171,6 +4267,30 @@ var PlotRows = function PlotRows(_ref) {
4171
4267
  },
4172
4268
  tooltipTitle: t('timeseries-open-param-list'),
4173
4269
  children: openParameterList ? jsx(ChevronUp, {}) : jsx(ChevronDown, {})
4270
+ }), jsx(ToggleMenu, {
4271
+ buttonIcon: jsx(Options, {}),
4272
+ buttonSx: {
4273
+ margin: '0 2px',
4274
+ '&.MuiButtonBase-root': {
4275
+ backgroundColor: 'transparent'
4276
+ }
4277
+ },
4278
+ buttonTestId: "duplicatePlotMenu_" + plot.plotId,
4279
+ menuItems: [{
4280
+ text: t('timeseries-duplicate'),
4281
+ action: function action() {
4282
+ return duplicatePlot(plot.plotId);
4283
+ },
4284
+ icon: jsx(Copy, {})
4285
+ }, {
4286
+ text: t('timeseries-remove'),
4287
+ action: function action() {
4288
+ return deletePlot(plot.plotId);
4289
+ },
4290
+ icon: jsx(Delete, {})
4291
+ }],
4292
+ tooltipTitle: t('timeseries-plot-options'),
4293
+ variant: "flat"
4174
4294
  })]
4175
4295
  }),
4176
4296
  collection: jsx(TimeSeriesSelectButtonConnect, {
@@ -4371,6 +4491,7 @@ var TimeSeriesManager = function TimeSeriesManager(_ref) {
4371
4491
  plotState = _ref.plotState,
4372
4492
  addPlot = _ref.addPlot,
4373
4493
  deletePlot = _ref.deletePlot,
4494
+ duplicatePlot = _ref.duplicatePlot,
4374
4495
  togglePlot = _ref.togglePlot,
4375
4496
  addParameter = _ref.addParameter,
4376
4497
  deleteParameter = _ref.deleteParameter,
@@ -4500,6 +4621,7 @@ var TimeSeriesManager = function TimeSeriesManager(_ref) {
4500
4621
  addParameter: addParameter,
4501
4622
  deleteParameter: deleteParameter,
4502
4623
  deletePlot: deletePlot,
4624
+ duplicatePlot: duplicatePlot,
4503
4625
  moveParameter: moveParameter,
4504
4626
  panelId: panelId,
4505
4627
  patchParameter: patchParameter,
@@ -6334,6 +6456,41 @@ var TimeSeriesSelectConnect = function TimeSeriesSelectConnect(_ref) {
6334
6456
 
6335
6457
  var DIALOG_TYPE_MANAGER = uiTypes.DialogTypes.TimeSeriesManager;
6336
6458
  var origin = TimeSeriesActionOrigin.timeSeriesManager;
6459
+ var getNextPlotCopyTitle = function getNextPlotCopyTitle(sourceTitle, plots, t) {
6460
+ var _sourceCopy$baseTitle, _sourceCopy$copyNumbe;
6461
+ var titleToken = '__PLOT_TITLE__';
6462
+ var countToken = '__COPY_NUMBER__';
6463
+ var template = t('timeseries-plot-copy-title', {
6464
+ title: titleToken,
6465
+ count: countToken
6466
+ });
6467
+ var titleTokenIndex = template.indexOf(titleToken);
6468
+ var countTokenIndex = template.indexOf(countToken);
6469
+ var prefix = template.slice(0, titleTokenIndex);
6470
+ var numberPrefix = template.slice(titleTokenIndex + titleToken.length, countTokenIndex);
6471
+ var suffix = template.slice(countTokenIndex + countToken.length);
6472
+ var copyTitlePattern = new RegExp("^" + escapeRegExp(prefix) + "(.*?)" + escapeRegExp(numberPrefix) + "(\\d+)" + escapeRegExp(suffix) + "$");
6473
+ var getCopyTitleParts = function getCopyTitleParts(title) {
6474
+ var match = title.match(copyTitlePattern);
6475
+ return match ? {
6476
+ baseTitle: match[1],
6477
+ copyNumber: Number(match[2])
6478
+ } : undefined;
6479
+ };
6480
+ var sourceCopy = getCopyTitleParts(sourceTitle);
6481
+ var baseTitle = (_sourceCopy$baseTitle = sourceCopy == null ? void 0 : sourceCopy.baseTitle) != null ? _sourceCopy$baseTitle : sourceTitle;
6482
+ var highestCopyNumber = plots.reduce(function (highest, plot) {
6483
+ var plotCopy = getCopyTitleParts(plot.title);
6484
+ return (plotCopy == null ? void 0 : plotCopy.baseTitle) === baseTitle ? Math.max(highest, plotCopy.copyNumber) : highest;
6485
+ }, (_sourceCopy$copyNumbe = sourceCopy == null ? void 0 : sourceCopy.copyNumber) != null ? _sourceCopy$copyNumbe : 0);
6486
+ return t('timeseries-plot-copy-title', {
6487
+ title: baseTitle,
6488
+ count: highestCopyNumber + 1
6489
+ });
6490
+ };
6491
+ var escapeRegExp = function escapeRegExp(value) {
6492
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
6493
+ };
6337
6494
  var TimeSeriesManagerConnect = function TimeSeriesManagerConnect(_ref) {
6338
6495
  var preloadedTimeseriesServices = _ref.preloadedTimeseriesServices;
6339
6496
  var panelId = useSelector(function (store) {
@@ -6397,6 +6554,20 @@ var TimeSeriesManagerConnect = function TimeSeriesManagerConnect(_ref) {
6397
6554
  title: title
6398
6555
  }));
6399
6556
  };
6557
+ var duplicatePlot = function duplicatePlot(plotId) {
6558
+ var plot = plotState == null ? void 0 : plotState.plots.find(function (item) {
6559
+ return item.plotId === plotId;
6560
+ });
6561
+ if (!plot || !plotState) {
6562
+ return;
6563
+ }
6564
+ dispatch(timeSeriesActions.duplicatePlot({
6565
+ panelId: panelId,
6566
+ origin: origin,
6567
+ plotId: plotId,
6568
+ title: getNextPlotCopyTitle(plot.title, plotState.plots, t)
6569
+ }));
6570
+ };
6400
6571
  var deleteParameter = function deleteParameter(parameterId) {
6401
6572
  dispatch(timeSeriesActions.deleteParameter({
6402
6573
  panelId: panelId,
@@ -6460,6 +6631,7 @@ var TimeSeriesManagerConnect = function TimeSeriesManagerConnect(_ref) {
6460
6631
  addPlot: addPlot,
6461
6632
  deleteParameter: deleteParameter,
6462
6633
  deletePlot: deletePlot,
6634
+ duplicatePlot: duplicatePlot,
6463
6635
  isOpen: isDialogOpen,
6464
6636
  moveParameter: moveParameter,
6465
6637
  movePlot: movePlot,
@@ -7308,18 +7480,16 @@ var getYAxis = function getYAxis(plotCharts) {
7308
7480
  parameters = _ref[1];
7309
7481
  var position = unitIndex % 2 === 0 ? 'left' : 'right';
7310
7482
  var offset = Math.floor(unitIndex / 2) * Y_AXIS_OFFSET;
7311
- var name = unitIndex === 0 ? plotChart.title : undefined;
7312
7483
  var allValues = parameters.flatMap(function (parameter) {
7313
7484
  return parameter.value;
7314
7485
  }).filter(function (value) {
7315
7486
  return value !== null && !isNaN(value);
7316
7487
  });
7317
7488
  if (allValues.length === 0) {
7318
- // still show the axis and plot name, but without min/max if there is no data
7489
+ // still show the axis, but without min/max if there is no data
7319
7490
  return {
7320
7491
  type: 'value',
7321
7492
  position: position,
7322
- name: name,
7323
7493
  axisTick: {
7324
7494
  show: false
7325
7495
  },
@@ -7354,7 +7524,6 @@ var getYAxis = function getYAxis(plotCharts) {
7354
7524
  return {
7355
7525
  type: 'value',
7356
7526
  position: position,
7357
- name: name,
7358
7527
  axisTick: {
7359
7528
  show: true
7360
7529
  },
@@ -7431,15 +7600,105 @@ var roundDecimalValues = function roundDecimalValues(value) {
7431
7600
  }
7432
7601
  return Number.isInteger(value) ? value.toString() : value.toFixed(1);
7433
7602
  };
7434
- var getOption = function getOption(plotsWithData, shouldShowLegend) {
7603
+ /** Shared category order for panel charts and their zoom preview. */
7604
+ var getSharedTimesteps = function getSharedTimesteps(plots) {
7605
+ // Keep the time domain stable when collapsing a panel; only its preview contribution changes.
7606
+ var timesteps = new Map();
7607
+ plots.filter(function (plot) {
7608
+ return plot.enabled !== false;
7609
+ }).forEach(function (plot) {
7610
+ plot.parametersWithData.forEach(function (parameter) {
7611
+ parameter.timestep.forEach(function (time) {
7612
+ if (Number.isFinite(time.getTime())) {
7613
+ timesteps.set(time.getTime(), time);
7614
+ }
7615
+ });
7616
+ });
7617
+ });
7618
+ return Array.from(timesteps.values()).sort(function (first, second) {
7619
+ return first.getTime() - second.getTime();
7620
+ });
7621
+ };
7622
+ /** Build a unit-independent overview from visible, open plots and enabled parameters. */
7623
+ var getZoomPreviewPlot = function getZoomPreviewPlot(plots) {
7624
+ var visiblePlots = plots.filter(function (plot) {
7625
+ return plot.enabled !== false;
7626
+ });
7627
+ var contributions = new Map();
7628
+ visiblePlots.filter(function (plot) {
7629
+ return plot.isOpen !== false;
7630
+ }).forEach(function (plot) {
7631
+ var plotValues = new Map();
7632
+ plot.parametersWithData.filter(function (parameter) {
7633
+ return parameter.enabled !== false;
7634
+ }).forEach(function (parameter) {
7635
+ var values = parameter.value.filter(Number.isFinite);
7636
+ if (!values.length) {
7637
+ return;
7638
+ }
7639
+ var minimum = Math.min.apply(Math, values);
7640
+ var range = Math.max.apply(Math, values) - minimum;
7641
+ parameter.timestep.forEach(function (time, index) {
7642
+ var _plotValues$get;
7643
+ var value = parameter.value[index];
7644
+ if (!Number.isFinite(value) || !Number.isFinite(time.getTime())) {
7645
+ return;
7646
+ }
7647
+ var normalized = range ? (value - minimum) / range : 0.5;
7648
+ var samples = (_plotValues$get = plotValues.get(time.getTime())) != null ? _plotValues$get : [];
7649
+ samples.push(normalized);
7650
+ plotValues.set(time.getTime(), samples);
7651
+ });
7652
+ });
7653
+ // Give each plot equal weight, regardless of how many parameters it contains.
7654
+ plotValues.forEach(function (values, time) {
7655
+ var _contributions$get;
7656
+ var samples = (_contributions$get = contributions.get(time)) != null ? _contributions$get : [];
7657
+ samples.push(values.reduce(function (sum, value) {
7658
+ return sum + value;
7659
+ }, 0) / values.length);
7660
+ contributions.set(time, samples);
7661
+ });
7662
+ });
7663
+ var timestep = getSharedTimesteps(plots);
7664
+ var plotId = 'zoom-preview';
7665
+ return {
7666
+ plotId: plotId,
7667
+ title: '',
7668
+ parametersWithData: [{
7669
+ id: plotId,
7670
+ plotId: plotId,
7671
+ propertyName: 'preview',
7672
+ plotType: 'line',
7673
+ serviceId: '',
7674
+ collectionId: '',
7675
+ unit: '',
7676
+ opacity: 100,
7677
+ timestep: timestep,
7678
+ value: timestep.map(function (time) {
7679
+ var values = contributions.get(time.getTime());
7680
+ return values != null && values.length ? values.reduce(function (sum, value) {
7681
+ return sum + value;
7682
+ }, 0) / values.length : NaN;
7683
+ })
7684
+ }]
7685
+ };
7686
+ };
7687
+ var getOption = function getOption(plotsWithData, shouldShowLegend, sharedTimesteps) {
7435
7688
  if (shouldShowLegend === void 0) {
7436
7689
  shouldShowLegend = true;
7437
7690
  }
7438
7691
  var parameterNames = createParameterNames(plotsWithData);
7439
7692
  var plotCharts = getPlotCharts(plotsWithData);
7440
- var xAxis = getXAxis(plotCharts);
7693
+ var xAxis = getXAxis(plotCharts).map(function (axis) {
7694
+ return Object.assign({}, axis, sharedTimesteps && {
7695
+ data: sharedTimesteps.map(function (time) {
7696
+ return time.toISOString();
7697
+ })
7698
+ });
7699
+ });
7441
7700
  var yAxis = getYAxis(plotCharts);
7442
- var series = getSeries(plotCharts, parameterNames);
7701
+ var series = getSeries(plotCharts, parameterNames, sharedTimesteps);
7443
7702
  var grid = getGrid(plotCharts);
7444
7703
  var tooltip = {
7445
7704
  trigger: 'axis',
@@ -7602,7 +7861,7 @@ var getEChartsSeriesDataByTimestep = function getEChartsSeriesDataByTimestep(tim
7602
7861
  });
7603
7862
  return data;
7604
7863
  };
7605
- var getSeries = function getSeries(plotCharts, parameterNames) {
7864
+ var getSeries = function getSeries(plotCharts, parameterNames, sharedTimesteps) {
7606
7865
  var allTimesteps = plotCharts.flatMap(function (plotChart) {
7607
7866
  return Object.values(plotChart.parametersByUnit).flatMap(function (parameters) {
7608
7867
  return parameters.flatMap(function (parameter) {
@@ -7623,7 +7882,7 @@ var getSeries = function getSeries(plotCharts, parameterNames) {
7623
7882
  var color = (_COLOR_NAME_TO_HEX_MA = COLOR_NAME_TO_HEX_MAP[parameter.color]) != null ? _COLOR_NAME_TO_HEX_MA : COLOR_NAME_TO_HEX_MAP[COLOR_MAP[parameter.propertyName]];
7624
7883
  var type = parameter.plotType === 'area' ? 'line' : parameter.plotType;
7625
7884
  return Object.assign({
7626
- data: getEChartsSeriesDataByTimestep(uniqueTimesteps, parameter),
7885
+ data: getEChartsSeriesDataByTimestep(sharedTimesteps != null ? sharedTimesteps : uniqueTimesteps, parameter),
7627
7886
  name: (_parameterNames$find = parameterNames.find(function (pName) {
7628
7887
  return pName.id === getParameterKey$1(parameter);
7629
7888
  })) == null ? void 0 : _parameterNames$find.name,
@@ -7691,6 +7950,177 @@ function getPlotCharts(plotsWithData) {
7691
7950
  return plotCharts;
7692
7951
  }
7693
7952
 
7953
+ /** One clock per view; standalone charts can use their own clock. Times are milliseconds. */
7954
+ var useCurrentTime = function useCurrentTime(enabled) {
7955
+ if (enabled === void 0) {
7956
+ enabled = true;
7957
+ }
7958
+ var _React$useState = React.useState(Date.now),
7959
+ now = _React$useState[0],
7960
+ setNow = _React$useState[1];
7961
+ React.useEffect(function () {
7962
+ if (!enabled) {
7963
+ return undefined;
7964
+ }
7965
+ var update = function update() {
7966
+ return setNow(Date.now());
7967
+ };
7968
+ update();
7969
+ var timer = window.setInterval(update, 60000);
7970
+ return function () {
7971
+ return window.clearInterval(timer);
7972
+ };
7973
+ }, [enabled]);
7974
+ return now;
7975
+ };
7976
+ /** Fractional category index, preserving the spacing of the chart's time axis. */
7977
+ var getCurrentTimeIndex = function getCurrentTimeIndex(timestamps, currentTime) {
7978
+ if (!Number.isFinite(currentTime) || !timestamps.length || currentTime < timestamps[0] || currentTime > timestamps[timestamps.length - 1]) {
7979
+ return undefined;
7980
+ }
7981
+ var next = timestamps.findIndex(function (time) {
7982
+ return time >= currentTime;
7983
+ });
7984
+ if (next < 0) {
7985
+ return undefined;
7986
+ }
7987
+ if (next === 0 || timestamps[next] === currentTime) {
7988
+ return next;
7989
+ }
7990
+ return next - 1 + (currentTime - timestamps[next - 1]) / (timestamps[next] - timestamps[next - 1]);
7991
+ };
7992
+ var getCurrentTimeLines = function getCurrentTimeLines(instance, currentTime, showPlots, showZoom) {
7993
+ if (instance.isDisposed()) {
7994
+ return [];
7995
+ }
7996
+ var api = instance;
7997
+ var model = api.getModel();
7998
+ if (!model) {
7999
+ return [];
8000
+ }
8001
+ var lines = [];
8002
+ model.eachComponent('xAxis', function (axis) {
8003
+ var timestamps = axis.getCategories().map(function (time) {
8004
+ return Date.parse(time);
8005
+ });
8006
+ var index = getCurrentTimeIndex(timestamps, currentTime);
8007
+ if (index === undefined) {
8008
+ return;
8009
+ }
8010
+ var _axis$axis$scale$getE = axis.axis.scale.getExtent(),
8011
+ min = _axis$axis$scale$getE[0],
8012
+ max = _axis$axis$scale$getE[1];
8013
+ if (showPlots && index >= min && index <= max) {
8014
+ var _model$getComponent;
8015
+ var rect = (_model$getComponent = model.getComponent('grid', axis.get('gridIndex'))) == null || (_model$getComponent = _model$getComponent.coordinateSystem) == null ? void 0 : _model$getComponent.getRect();
8016
+ var lower = Math.floor(index);
8017
+ var upper = Math.ceil(index);
8018
+ var left = instance.convertToPixel({
8019
+ xAxisIndex: axis.componentIndex
8020
+ }, lower);
8021
+ var right = instance.convertToPixel({
8022
+ xAxisIndex: axis.componentIndex
8023
+ }, upper);
8024
+ var x = left + (right - left) * (index - lower);
8025
+ if (rect && Number.isFinite(x) && x >= rect.x && x <= rect.x + rect.width) {
8026
+ lines.push({
8027
+ id: "plot-" + axis.componentIndex,
8028
+ x: x,
8029
+ y: rect.y,
8030
+ height: rect.height
8031
+ });
8032
+ }
8033
+ }
8034
+ if (showZoom && axis.componentIndex === 0) {
8035
+ var _displayables$sliderG;
8036
+ var zoom = model.getComponent('dataZoom', 0);
8037
+ var view = zoom && zoom.get('show') && api.getViewOfComponentModel(zoom);
8038
+ var _ref = view || {},
8039
+ displayables = _ref._displayables;
8040
+ var background = displayables == null || (_displayables$sliderG = displayables.sliderGroup) == null ? void 0 : _displayables$sliderG.childAt(0);
8041
+ if (background) {
8042
+ background.getComputedTransform();
8043
+ var start = background.transformCoordToGlobal(0, 0);
8044
+ var end = background.transformCoordToGlobal(background.shape.width, background.shape.height);
8045
+ var fraction = timestamps.length === 1 ? 0.5 : index / (timestamps.length - 1);
8046
+ lines.push({
8047
+ id: 'zoom',
8048
+ x: start[0] + fraction * (end[0] - start[0]),
8049
+ y: Math.min(start[1], end[1]),
8050
+ height: Math.abs(end[1] - start[1])
8051
+ });
8052
+ }
8053
+ }
8054
+ });
8055
+ return lines;
8056
+ };
8057
+ var CurrentTime = function CurrentTime(_ref2) {
8058
+ var instance = _ref2.instance,
8059
+ currentTime = _ref2.currentTime,
8060
+ showPlots = _ref2.showPlots,
8061
+ showZoom = _ref2.showZoom;
8062
+ var theme = useTheme();
8063
+ var _React$useState2 = React.useState([]),
8064
+ lines = _React$useState2[0],
8065
+ setLines = _React$useState2[1];
8066
+ React.useEffect(function () {
8067
+ if (!instance) {
8068
+ return undefined;
8069
+ }
8070
+ var update = function update() {
8071
+ var next = getCurrentTimeLines(instance, currentTime, showPlots, showZoom);
8072
+ setLines(function (previous) {
8073
+ return JSON.stringify(previous) === JSON.stringify(next) ? previous : next;
8074
+ });
8075
+ };
8076
+ update();
8077
+ instance.on('rendered', update);
8078
+ return function () {
8079
+ if (!instance.isDisposed()) {
8080
+ instance.off('rendered', update);
8081
+ }
8082
+ };
8083
+ }, [instance, currentTime, showPlots, showZoom]);
8084
+ var _theme$palette$geoweb = theme.palette.geowebColors.timeSlider,
8085
+ playerNeedleTime = _theme$palette$geoweb.playerNeedleTime,
8086
+ playerNeedleTimeTop = _theme$palette$geoweb.playerNeedleTimeTop;
8087
+ return jsx("svg", {
8088
+ "aria-hidden": "true",
8089
+ "data-testid": "CurrentTime",
8090
+ style: {
8091
+ position: 'absolute',
8092
+ inset: 0,
8093
+ width: '100%',
8094
+ height: '100%',
8095
+ pointerEvents: 'none',
8096
+ overflow: 'hidden'
8097
+ },
8098
+ children: lines.map(function (_ref3) {
8099
+ var id = _ref3.id,
8100
+ x = _ref3.x,
8101
+ y = _ref3.y,
8102
+ height = _ref3.height;
8103
+ return jsxs("g", {
8104
+ children: [jsx("line", {
8105
+ stroke: playerNeedleTime.rgba,
8106
+ strokeWidth: 7,
8107
+ x1: x,
8108
+ x2: x,
8109
+ y1: y,
8110
+ y2: y + height
8111
+ }), jsx("line", {
8112
+ stroke: playerNeedleTimeTop.rgba,
8113
+ strokeWidth: 2,
8114
+ x1: x,
8115
+ x2: x,
8116
+ y1: y,
8117
+ y2: y + height
8118
+ })]
8119
+ }, id);
8120
+ })
8121
+ });
8122
+ };
8123
+
7694
8124
  // Guard: mocked ReactECharts (forwardRef) has no real prototype chain.
7695
8125
  var reactEChartsProto = ReactECharts.prototype;
7696
8126
  var echartsReactCoreProto = reactEChartsProto ? Object.getPrototypeOf(reactEChartsProto) : null;
@@ -7733,10 +8163,20 @@ var useChartHeight = function useChartHeight(_ref) {
7733
8163
  var plotsWithData = _ref.plotsWithData,
7734
8164
  shouldShowLegend = _ref.shouldShowLegend,
7735
8165
  option = _ref.option,
7736
- onLegendHeightChange = _ref.onLegendHeightChange;
7737
- var getDefaultHeight = function getDefaultHeight(plotsWithData) {
8166
+ _ref$fitToContainer = _ref.fitToContainer,
8167
+ fitToContainer = _ref$fitToContainer === void 0 ? false : _ref$fitToContainer,
8168
+ _ref$shouldShowZoom = _ref.shouldShowZoom,
8169
+ shouldShowZoom = _ref$shouldShowZoom === void 0 ? true : _ref$shouldShowZoom,
8170
+ controlsOnly = _ref.controlsOnly;
8171
+ var getDefaultHeight = React.useCallback(function (plotsWithData) {
8172
+ if (controlsOnly === 'legend') {
8173
+ return 32;
8174
+ }
8175
+ if (controlsOnly === 'zoom') {
8176
+ return 52;
8177
+ }
7738
8178
  return 100 + PLOT_HEIGHT * plotsWithData.length;
7739
- };
8179
+ }, [controlsOnly]);
7740
8180
  var _React$useState = React.useState(getDefaultHeight(plotsWithData)),
7741
8181
  chartHeight = _React$useState[0],
7742
8182
  setChartHeight = _React$useState[1];
@@ -7745,6 +8185,12 @@ var useChartHeight = function useChartHeight(_ref) {
7745
8185
  if (echartsInstance.isDisposed()) {
7746
8186
  return;
7747
8187
  }
8188
+ // Use the current container size before measuring a wrapped legend.
8189
+ // This also clears explicit dimensions captured during async init.
8190
+ echartsInstance.resize({
8191
+ width: 'auto',
8192
+ height: 'auto'
8193
+ });
7748
8194
  var legendApi = echartsInstance;
7749
8195
  if (legendApi.getModel() !== null) {
7750
8196
  var _option$grid;
@@ -7752,14 +8198,17 @@ var useChartHeight = function useChartHeight(_ref) {
7752
8198
  var legendView = legendApi.getViewOfComponentModel(legend);
7753
8199
  var _legendView$group$get = legendView.group.getBoundingRect(),
7754
8200
  height = _legendView$group$get.height;
7755
- onLegendHeightChange == null || onLegendHeightChange(shouldShowLegend ? height : 0);
7756
8201
  var grid = (_option$grid = option.grid) != null ? _option$grid : [];
7757
8202
  var gridArray = Array.isArray(grid) ? grid : [];
7758
8203
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
7759
8204
  var newGrid = gridArray.map(function (grid) {
7760
8205
  return Object.assign({}, grid, {
7761
8206
  top: shouldShowLegend ? parseInt(grid.top, 10) + height + "px" : grid.top
7762
- });
8207
+ }, fitToContainer ? {
8208
+ top: shouldShowLegend ? 20 + height : 8,
8209
+ height: 'auto',
8210
+ bottom: shouldShowZoom ? 75 : 24
8211
+ } : {});
7763
8212
  });
7764
8213
  echartsInstance.setOption({
7765
8214
  legend: {
@@ -7767,13 +8216,14 @@ var useChartHeight = function useChartHeight(_ref) {
7767
8216
  height: shouldShowLegend ? height : 0,
7768
8217
  show: shouldShowLegend
7769
8218
  },
7770
- grid: newGrid
8219
+ grid: controlsOnly ? gridArray : newGrid
7771
8220
  });
7772
8221
  var newHeight = getDefaultHeight(plotsWithData) + (shouldShowLegend ? height : 0);
7773
- setChartHeight(newHeight);
7774
- echartsInstance.resize();
8222
+ if (!fitToContainer) {
8223
+ setChartHeight(controlsOnly === 'legend' ? Math.ceil(height) : newHeight);
8224
+ }
7775
8225
  }
7776
- }, [option.grid, plotsWithData, shouldShowLegend, onLegendHeightChange]);
8226
+ }, [option.grid, plotsWithData, shouldShowLegend, fitToContainer, controlsOnly, getDefaultHeight, shouldShowZoom]);
7777
8227
  React.useEffect(function () {
7778
8228
  var _chartRef$current;
7779
8229
  var instance = (_chartRef$current = chartRef.current) == null ? void 0 : _chartRef$current.getEchartsInstance();
@@ -7788,6 +8238,9 @@ var useChartHeight = function useChartHeight(_ref) {
7788
8238
  }
7789
8239
  }, [shouldShowLegend, updateHeight]);
7790
8240
  React.useEffect(function () {
8241
+ if ((fitToContainer || controlsOnly) && typeof ResizeObserver !== 'undefined') {
8242
+ return undefined;
8243
+ }
7791
8244
  var onHeight = function onHeight() {
7792
8245
  var _chartRef$current2;
7793
8246
  var instance = (_chartRef$current2 = chartRef.current) == null ? void 0 : _chartRef$current2.getEchartsInstance();
@@ -7799,13 +8252,78 @@ var useChartHeight = function useChartHeight(_ref) {
7799
8252
  return function () {
7800
8253
  window.removeEventListener('resize', onHeight);
7801
8254
  };
7802
- }, [updateHeight]);
8255
+ }, [fitToContainer, controlsOnly, updateHeight]);
7803
8256
  return {
7804
8257
  chartHeight: chartHeight,
7805
8258
  chartRef: chartRef,
7806
8259
  updateHeight: updateHeight
7807
8260
  };
7808
8261
  };
8262
+ var useChartSynchronization = function useChartSynchronization() {
8263
+ var instances = React.useRef(new Map());
8264
+ var zoomState = React.useRef(null);
8265
+ return React.useMemo(function () {
8266
+ return {
8267
+ zoomState: zoomState,
8268
+ register: function register(instance, syncPointer) {
8269
+ if (syncPointer === void 0) {
8270
+ syncPointer = true;
8271
+ }
8272
+ instances.current.set(instance, syncPointer);
8273
+ if (zoomState.current && !instance.isDisposed()) {
8274
+ instance.dispatchAction(Object.assign({
8275
+ type: 'dataZoom'
8276
+ }, zoomState.current), {
8277
+ silent: true
8278
+ });
8279
+ }
8280
+ },
8281
+ unregister: function unregister(instance) {
8282
+ instances.current["delete"](instance);
8283
+ },
8284
+ zoom: function zoom(state, source) {
8285
+ zoomState.current = state;
8286
+ instances.current.forEach(function (_syncPointer, instance) {
8287
+ if (instance !== source && !instance.isDisposed()) {
8288
+ instance.dispatchAction(Object.assign({
8289
+ type: 'dataZoom'
8290
+ }, state), {
8291
+ silent: true
8292
+ });
8293
+ }
8294
+ });
8295
+ },
8296
+ pointer: function pointer(event, source) {
8297
+ var _event$axesInfo;
8298
+ var axis = (_event$axesInfo = event.axesInfo) == null ? void 0 : _event$axesInfo.find(function (_ref2) {
8299
+ var axisDim = _ref2.axisDim;
8300
+ return axisDim === 'x';
8301
+ });
8302
+ instances.current.forEach(function (syncPointer, instance) {
8303
+ if (syncPointer && instance !== source && !instance.isDisposed()) {
8304
+ instance.dispatchAction(axis ? {
8305
+ type: 'updateAxisPointer',
8306
+ x: instance.convertToPixel({
8307
+ xAxisIndex: 0
8308
+ }, axis.value),
8309
+ y: instance.getHeight() / 2,
8310
+ axesInfo: [{
8311
+ axisDim: 'x',
8312
+ axisIndex: 0,
8313
+ value: axis.value
8314
+ }]
8315
+ } : {
8316
+ type: 'updateAxisPointer',
8317
+ currTrigger: 'leave'
8318
+ }, {
8319
+ silent: true
8320
+ });
8321
+ }
8322
+ });
8323
+ }
8324
+ };
8325
+ }, []);
8326
+ };
7809
8327
  var applyDataZoomState = function applyDataZoomState(option, dataZoomState) {
7810
8328
  if (!dataZoomState || !(option != null && option.dataZoom) || !Array.isArray(option.dataZoom)) {
7811
8329
  return option;
@@ -7834,17 +8352,36 @@ var extractDataZoomState = function extractDataZoomState(params) {
7834
8352
  }
7835
8353
  return null;
7836
8354
  };
7837
- var TimeSeriesChart = function TimeSeriesChart(_ref2) {
7838
- var plotsWithData = _ref2.plotsWithData,
7839
- _ref2$animation = _ref2.animation,
7840
- animation = _ref2$animation === void 0 ? false : _ref2$animation,
7841
- _ref2$shouldShowLegen = _ref2.shouldShowLegend,
7842
- shouldShowLegend = _ref2$shouldShowLegen === void 0 ? true : _ref2$shouldShowLegen,
7843
- onToggleLegendParam = _ref2.onToggleLegendParam,
7844
- onLegendHeightChange = _ref2.onLegendHeightChange;
7845
- var _useThemeContext = useThemeContext(),
7846
- namedTheme = _useThemeContext.namedTheme;
7847
- var isDark = (namedTheme == null ? void 0 : namedTheme.theme.palette.mode) === 'dark';
8355
+ var TimeSeriesChart = function TimeSeriesChart(_ref3) {
8356
+ var plotsWithData = _ref3.plotsWithData,
8357
+ _ref3$animation = _ref3.animation,
8358
+ animation = _ref3$animation === void 0 ? false : _ref3$animation,
8359
+ _ref3$shouldShowLegen = _ref3.shouldShowLegend,
8360
+ shouldShowLegend = _ref3$shouldShowLegen === void 0 ? true : _ref3$shouldShowLegen,
8361
+ onToggleLegendParam = _ref3.onToggleLegendParam,
8362
+ _ref3$fitToContainer = _ref3.fitToContainer,
8363
+ fitToContainer = _ref3$fitToContainer === void 0 ? false : _ref3$fitToContainer,
8364
+ _ref3$shouldShowZoom = _ref3.shouldShowZoom,
8365
+ shouldShowZoom = _ref3$shouldShowZoom === void 0 ? true : _ref3$shouldShowZoom,
8366
+ controlsOnly = _ref3.controlsOnly,
8367
+ synchronization = _ref3.synchronization,
8368
+ sharedTimesteps = _ref3.sharedTimesteps,
8369
+ currentTime = _ref3.currentTime;
8370
+ var now = useCurrentTime(currentTime === undefined && controlsOnly !== 'legend');
8371
+ var _React$useState2 = React.useState(null),
8372
+ indicatorInstance = _React$useState2[0],
8373
+ setIndicatorInstance = _React$useState2[1];
8374
+ var theme = useTheme();
8375
+ var isDark = theme.palette.mode === 'dark';
8376
+ var containerRef = React.useRef(null);
8377
+ var registeredInstance = React.useRef(null);
8378
+ React.useEffect(function () {
8379
+ return function () {
8380
+ if (registeredInstance.current) {
8381
+ synchronization == null || synchronization.unregister(registeredInstance.current);
8382
+ }
8383
+ };
8384
+ }, [synchronization]);
7848
8385
  var dataZoomStateRef = React.useRef(null);
7849
8386
  var lastLegendEventRef = React.useRef(null);
7850
8387
  var enabledPlots = React.useMemo(function () {
@@ -7853,34 +8390,153 @@ var TimeSeriesChart = function TimeSeriesChart(_ref2) {
7853
8390
  });
7854
8391
  }, [plotsWithData]);
7855
8392
  var option = React.useMemo(function () {
7856
- return getOption(enabledPlots, shouldShowLegend);
7857
- }, [enabledPlots, shouldShowLegend]);
8393
+ var base = getOption(controlsOnly === 'zoom' ? [getZoomPreviewPlot(enabledPlots)] : enabledPlots, shouldShowLegend, sharedTimesteps);
8394
+ var dataZoom = Array.isArray(base.dataZoom) ? base.dataZoom : [];
8395
+ if (!controlsOnly) {
8396
+ return Object.assign({}, base, {
8397
+ dataZoom: dataZoom.map(function (zoom) {
8398
+ return Object.assign({}, zoom, {
8399
+ show: shouldShowZoom
8400
+ });
8401
+ })
8402
+ });
8403
+ }
8404
+ return Object.assign({}, base, {
8405
+ tooltip: {
8406
+ show: false
8407
+ },
8408
+ axisPointer: {
8409
+ show: false
8410
+ },
8411
+ grid: (Array.isArray(base.grid) ? base.grid : []).map(function (grid) {
8412
+ return Object.assign({}, grid, {
8413
+ top: 0,
8414
+ height: 0
8415
+ });
8416
+ }),
8417
+ xAxis: (Array.isArray(base.xAxis) ? base.xAxis : []).map(function (axis) {
8418
+ return Object.assign({}, axis, {
8419
+ show: false
8420
+ });
8421
+ }),
8422
+ yAxis: (Array.isArray(base.yAxis) ? base.yAxis : []).map(function (axis) {
8423
+ return Object.assign({}, axis, {
8424
+ show: false
8425
+ });
8426
+ }),
8427
+ series: (Array.isArray(base.series) ? base.series : []).map(function (series) {
8428
+ return Object.assign({}, series, {
8429
+ // The slider needs real values to render its data preview. Hide the
8430
+ // supporting series rather than replacing their values with nulls.
8431
+ data: controlsOnly === 'legend' ? [] : series.data
8432
+ }, controlsOnly === 'zoom' && {
8433
+ lineStyle: {
8434
+ opacity: 0
8435
+ },
8436
+ areaStyle: {
8437
+ opacity: 0
8438
+ },
8439
+ itemStyle: {
8440
+ opacity: 0
8441
+ },
8442
+ label: {
8443
+ show: false
8444
+ },
8445
+ showSymbol: false,
8446
+ emphasis: {
8447
+ disabled: true
8448
+ }
8449
+ }, {
8450
+ silent: true
8451
+ });
8452
+ }),
8453
+ dataZoom: controlsOnly === 'zoom' ? dataZoom.map(function (zoom) {
8454
+ return Object.assign({}, zoom, {
8455
+ top: 4,
8456
+ bottom: undefined,
8457
+ showDataShadow: true
8458
+ });
8459
+ }) : []
8460
+ });
8461
+ }, [enabledPlots, shouldShowLegend, shouldShowZoom, controlsOnly, sharedTimesteps]);
7858
8462
  var optionWithZoom = React.useMemo(function () {
7859
- return applyDataZoomState(option, dataZoomStateRef.current);
7860
- }, [option]);
8463
+ var _synchronization$zoom;
8464
+ return applyDataZoomState(option, (_synchronization$zoom = synchronization == null ? void 0 : synchronization.zoomState.current) != null ? _synchronization$zoom : dataZoomStateRef.current);
8465
+ }, [option, synchronization]);
7861
8466
  var _useChartHeight = useChartHeight({
7862
8467
  plotsWithData: enabledPlots,
7863
8468
  shouldShowLegend: shouldShowLegend,
7864
8469
  option: optionWithZoom,
7865
- onLegendHeightChange: onLegendHeightChange
8470
+ fitToContainer: fitToContainer,
8471
+ shouldShowZoom: shouldShowZoom,
8472
+ controlsOnly: controlsOnly
7866
8473
  }),
7867
8474
  chartHeight = _useChartHeight.chartHeight,
7868
8475
  chartRef = _useChartHeight.chartRef,
7869
8476
  updateHeight = _useChartHeight.updateHeight;
7870
- return option ? jsx("div", {
7871
- "data-testid": "TimeSeriesChart",
7872
- children: jsx(ReactECharts, {
8477
+ var observesContainer = (fitToContainer || !!controlsOnly) && typeof ResizeObserver !== 'undefined';
8478
+ React.useEffect(function () {
8479
+ var container = containerRef.current;
8480
+ if (!observesContainer || !container) {
8481
+ return undefined;
8482
+ }
8483
+ var observer = new ResizeObserver(function () {
8484
+ var instance = registeredInstance.current;
8485
+ if (instance && !instance.isDisposed() && container.clientWidth > 0 && container.clientHeight > 0) {
8486
+ updateHeight(instance);
8487
+ }
8488
+ });
8489
+ observer.observe(container);
8490
+ return function () {
8491
+ return observer.disconnect();
8492
+ };
8493
+ }, [observesContainer, updateHeight]);
8494
+ return option ? jsxs("div", {
8495
+ "data-testid": controlsOnly ? {
8496
+ legend: 'TimeSeriesLegend',
8497
+ zoom: 'TimeSeriesZoom'
8498
+ }[controlsOnly] : 'TimeSeriesChart',
8499
+ ref: containerRef,
8500
+ style: fitToContainer ? {
8501
+ position: 'relative',
8502
+ height: '100%',
8503
+ width: '100%',
8504
+ minHeight: 0
8505
+ } : {
8506
+ position: 'relative'
8507
+ },
8508
+ children: [jsx(ReactECharts, {
8509
+ autoResize: !observesContainer,
7873
8510
  notMerge: true,
7874
- onChartReady: updateHeight,
8511
+ onChartReady: function onChartReady(instance) {
8512
+ if (registeredInstance.current) {
8513
+ synchronization == null || synchronization.unregister(registeredInstance.current);
8514
+ }
8515
+ registeredInstance.current = instance;
8516
+ if (controlsOnly !== 'legend') {
8517
+ synchronization == null || synchronization.register(instance, controlsOnly !== 'zoom');
8518
+ }
8519
+ updateHeight(instance);
8520
+ setIndicatorInstance(instance);
8521
+ },
7875
8522
  // noop, prevent flickering when toggling legend
7876
8523
  onEvents: {
7877
8524
  finished: function finished() {},
7878
8525
  datazoom: function datazoom(params) {
7879
8526
  var newState = extractDataZoomState(params);
7880
8527
  if (newState) {
8528
+ var _registeredInstance$c;
7881
8529
  dataZoomStateRef.current = newState;
8530
+ synchronization == null || synchronization.zoom(newState, (_registeredInstance$c = registeredInstance.current) != null ? _registeredInstance$c : undefined);
7882
8531
  }
7883
8532
  },
8533
+ updateAxisPointer: function updateAxisPointer(event) {
8534
+ var _registeredInstance$c2;
8535
+ if (controlsOnly) {
8536
+ return;
8537
+ }
8538
+ synchronization == null || synchronization.pointer(event, (_registeredInstance$c2 = registeredInstance.current) != null ? _registeredInstance$c2 : undefined);
8539
+ },
7884
8540
  legendselectchanged: function legendselectchanged(params) {
7885
8541
  if (!option.legend) {
7886
8542
  return;
@@ -7899,68 +8555,217 @@ var TimeSeriesChart = function TimeSeriesChart(_ref2) {
7899
8555
  }
7900
8556
  },
7901
8557
  option: Object.assign({}, optionWithZoom, {
8558
+ backgroundColor: 'transparent',
7902
8559
  animation: animation
7903
8560
  }),
7904
8561
  ref: chartRef,
7905
8562
  style: {
7906
- background: 'white',
7907
- height: chartHeight,
7908
- minWidth: MIN_GRAPH_WIDTH
8563
+ background: 'transparent',
8564
+ height: fitToContainer ? '100%' : chartHeight,
8565
+ minWidth: fitToContainer ? 0 : MIN_GRAPH_WIDTH
7909
8566
  },
7910
8567
  theme: isDark ? EChartsDarkTheme : EChartsLightTheme
7911
- })
8568
+ }), controlsOnly !== 'legend' && jsx(CurrentTime, {
8569
+ currentTime: currentTime != null ? currentTime : now,
8570
+ instance: indicatorInstance,
8571
+ showPlots: !controlsOnly,
8572
+ showZoom: controlsOnly === 'zoom' || shouldShowZoom
8573
+ })]
7912
8574
  }) : null;
7913
8575
  };
7914
8576
 
8577
+ var TIME_SERIES_PANEL_MIN_HEIGHT = 90;
8578
+ var TimeSeriesPanelConnect = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
8579
+ var plotId = _ref.panelId,
8580
+ viewId = _ref.viewId,
8581
+ name = _ref.name,
8582
+ children = _ref.children,
8583
+ headerAction = _ref.headerAction,
8584
+ isDisplayed = _ref.isDisplayed,
8585
+ maxWidth = _ref.maxWidth,
8586
+ minWidth = _ref.minWidth,
8587
+ handleButtonComponent = _ref.handleButtonComponent,
8588
+ onOpenChange = _ref.onOpenChange,
8589
+ onResizeStart = _ref.onResizeStart,
8590
+ onResizeEnd = _ref.onResizeEnd,
8591
+ initialSize = _ref.initialSize,
8592
+ allowOverflow = _ref.allowOverflow,
8593
+ onSizeChange = _ref.onSizeChange;
8594
+ if (!plotId || !viewId) {
8595
+ throw new Error('TimeSeriesPanelConnect requires both `plotId` and `viewId` props. ' + 'Use it inside a SortablePanels that has `viewId` set, or pass both directly.');
8596
+ }
8597
+ var dispatch = useDispatch();
8598
+ var isOpen = useSelector(function (store) {
8599
+ return getPlotIsOpen(store, viewId, plotId);
8600
+ });
8601
+ var customSize = useSelector(function (store) {
8602
+ return getPlotCustomSize(store, viewId, plotId);
8603
+ });
8604
+ var handleSetIsOpen = React.useCallback(function (open) {
8605
+ if (isOpen === open) {
8606
+ return;
8607
+ }
8608
+ dispatch(timeSeriesActions.setPlotIsOpen({
8609
+ plotId: plotId,
8610
+ panelId: viewId,
8611
+ origin: TimeSeriesActionOrigin.timeSeriesManager,
8612
+ isOpen: open
8613
+ }));
8614
+ onOpenChange == null || onOpenChange(open);
8615
+ }, [isOpen, dispatch, plotId, viewId, onOpenChange]);
8616
+ var handleSetCustomSize = React.useCallback(function (size) {
8617
+ onSizeChange == null || onSizeChange(size);
8618
+ dispatch(timeSeriesActions.setPlotSize({
8619
+ plotId: plotId,
8620
+ panelId: viewId,
8621
+ origin: TimeSeriesActionOrigin.timeSeriesManager,
8622
+ size: size
8623
+ }));
8624
+ }, [dispatch, plotId, viewId, onSizeChange]);
8625
+ return jsx(ResizablePanel, {
8626
+ allowOverflow: allowOverflow,
8627
+ customWidth: customSize,
8628
+ direction: "vertical",
8629
+ handleButtonComponent: handleButtonComponent,
8630
+ headerAction: headerAction,
8631
+ initialSize: initialSize,
8632
+ isDisplayed: isDisplayed,
8633
+ isOpen: isOpen,
8634
+ maxWidth: maxWidth,
8635
+ minWidth: minWidth != null ? minWidth : TIME_SERIES_PANEL_MIN_HEIGHT,
8636
+ name: name,
8637
+ onResizeEnd: onResizeEnd,
8638
+ onResizeStart: onResizeStart,
8639
+ onSetCustomWidth: handleSetCustomSize,
8640
+ onSetIsOpen: handleSetIsOpen,
8641
+ ref: ref,
8642
+ children: children
8643
+ });
8644
+ });
8645
+
8646
+ var TimeSeriesPanelsConnect = function TimeSeriesPanelsConnect(_ref) {
8647
+ var viewId = _ref.viewId,
8648
+ _ref$panelComponent = _ref.panelComponent,
8649
+ panelComponent = _ref$panelComponent === void 0 ? TimeSeriesPanelConnect : _ref$panelComponent,
8650
+ renderPlot = _ref.renderPlot;
8651
+ var dispatch = useDispatch();
8652
+ var panelsInOrder = useSelector(function (store) {
8653
+ var _getPlotState;
8654
+ return ((_getPlotState = getPlotState(store, viewId)) == null ? void 0 : _getPlotState.plots) || [];
8655
+ });
8656
+ var handleOrderChange = function handleOrderChange(newOrder) {
8657
+ var visiblePlots = panelsInOrder.filter(function (plot) {
8658
+ return plot.enabled !== false;
8659
+ });
8660
+ if (newOrder.length === visiblePlots.length && newOrder.every(function (_ref2, index) {
8661
+ var id = _ref2.id;
8662
+ return id === visiblePlots[index].plotId;
8663
+ })) {
8664
+ return;
8665
+ }
8666
+ dispatch(timeSeriesActions.reorderPlots({
8667
+ panelId: viewId,
8668
+ origin: TimeSeriesActionOrigin.timeSeriesManager,
8669
+ newOrder: newOrder.map(function (_ref3) {
8670
+ var id = _ref3.id;
8671
+ return id;
8672
+ })
8673
+ }));
8674
+ };
8675
+ var panels = panelsInOrder.filter(function (plot) {
8676
+ return plot.enabled !== false;
8677
+ }).map(function (_ref4) {
8678
+ var id = _ref4.plotId,
8679
+ name = _ref4.title,
8680
+ isOpen = _ref4.isOpen,
8681
+ customSize = _ref4.customSize;
8682
+ return {
8683
+ id: id,
8684
+ name: name,
8685
+ isDisplayed: true,
8686
+ isOpen: isOpen !== false,
8687
+ customSize: customSize,
8688
+ minWidth: TIME_SERIES_PANEL_MIN_HEIGHT,
8689
+ render: function render() {
8690
+ return renderPlot(id);
8691
+ }
8692
+ };
8693
+ });
8694
+ return jsx(SortablePanels, {
8695
+ allowOverflow: true,
8696
+ direction: "vertical",
8697
+ onOrderChange: handleOrderChange,
8698
+ panelComponent: panelComponent,
8699
+ panels: panels,
8700
+ sizing: "untilManualResize",
8701
+ viewId: viewId
8702
+ }, viewId);
8703
+ };
8704
+
7915
8705
  var getParameterKey = function getParameterKey(param) {
7916
8706
  return param.serviceId + "|" + param.collectionId + "|" + param.propertyName;
7917
8707
  };
7918
- var PlotErrorBanners = function PlotErrorBanners(_ref) {
7919
- var plotsWithData = _ref.plotsWithData,
8708
+ var getErrorTitle = function getErrorTitle(parameters) {
8709
+ var propertyNames = parameters.map(function (param) {
8710
+ return param.propertyName;
8711
+ });
8712
+ if (propertyNames.length > 1) {
8713
+ return "\"" + propertyNames.join('", "') + "\"";
8714
+ }
8715
+ return "\"" + (propertyNames[0] || '') + "\"";
8716
+ };
8717
+ var getErrorTranslationKey = function getErrorTranslationKey(errorKey, parameterCount) {
8718
+ // Use plural translation only when multiple parameters fail with error-message-general
8719
+ return errorKey === 'error-message-general' && parameterCount > 1 ? 'error-message-general-plural' : errorKey;
8720
+ };
8721
+ var TimeSeriesPlot = function TimeSeriesPlot(_ref) {
8722
+ var _plot$failedParameter, _plot$failedParameter2, _plot$errors;
8723
+ var plot = _ref.plot,
7920
8724
  parametersFailingInAllPlots = _ref.parametersFailingInAllPlots,
7921
- legendHeight = _ref.legendHeight,
7922
- getErrorTitle = _ref.getErrorTitle,
7923
- getErrorTranslationKey = _ref.getErrorTranslationKey,
7924
- t = _ref.t;
7925
- return jsx(Fragment, {
7926
- children: plotsWithData.map(function (plot, index) {
7927
- var _plot$failedParameter, _plot$errors;
7928
- var parametersFailingKeys = new Set(parametersFailingInAllPlots.map(getParameterKey));
7929
- var plotSpecificFailedParameters = ((_plot$failedParameter = plot.failedParameters) == null ? void 0 : _plot$failedParameter.filter(function (param) {
7930
- return !parametersFailingKeys.has(getParameterKey(param));
7931
- })) || [];
7932
- if (plotSpecificFailedParameters.length === 0) {
7933
- return null;
7934
- }
7935
- var errorTitle = getErrorTitle(plotSpecificFailedParameters);
7936
- var errorKey = ((_plot$errors = plot.errors) == null ? void 0 : _plot$errors[0]) || 'error-message-general';
7937
- var translationKey = getErrorTranslationKey(errorKey, plotSpecificFailedParameters.length);
7938
- var errorInfo = t(translationKey);
7939
- return jsx(Box, {
7940
- sx: {
7941
- position: 'absolute',
7942
- top: legendHeight + PLOT_HEIGHT * index + 35,
7943
- left: 0,
7944
- right: 0,
7945
- zIndex: 10,
7946
- pointerEvents: 'none'
7947
- },
7948
- children: jsx(Box, {
7949
- sx: {
7950
- pointerEvents: 'auto'
7951
- },
7952
- children: jsx(AlertBanner, {
7953
- info: errorInfo,
7954
- shouldClose: true,
7955
- title: errorTitle
7956
- })
7957
- })
7958
- }, "error-" + plot.plotId);
7959
- })
8725
+ synchronization = _ref.synchronization,
8726
+ sharedTimesteps = _ref.sharedTimesteps,
8727
+ currentTime = _ref.currentTime;
8728
+ var _useTimeseriesTransla = useTimeseriesTranslation(),
8729
+ t = _useTimeseriesTransla.t;
8730
+ var commonKeys = new Set(parametersFailingInAllPlots.map(getParameterKey));
8731
+ var failedParameters = (_plot$failedParameter = (_plot$failedParameter2 = plot.failedParameters) == null ? void 0 : _plot$failedParameter2.filter(function (parameter) {
8732
+ return !commonKeys.has(getParameterKey(parameter));
8733
+ })) != null ? _plot$failedParameter : [];
8734
+ var errorKey = ((_plot$errors = plot.errors) == null ? void 0 : _plot$errors[0]) || 'error-message-general';
8735
+ var errorInfo = t(getErrorTranslationKey(errorKey, failedParameters.length));
8736
+ var errorTitle = getErrorTitle(failedParameters);
8737
+ return jsxs(Box, {
8738
+ sx: {
8739
+ display: 'flex',
8740
+ flexDirection: 'column',
8741
+ width: '100%',
8742
+ height: '100%',
8743
+ minHeight: 0
8744
+ },
8745
+ children: [!!failedParameters.length && jsx(AlertBanner, {
8746
+ info: errorInfo,
8747
+ shouldClose: true,
8748
+ title: errorTitle
8749
+ }), jsx(Box, {
8750
+ sx: {
8751
+ flex: 1,
8752
+ minHeight: 0
8753
+ },
8754
+ children: jsx(TimeSeriesChart, {
8755
+ currentTime: currentTime,
8756
+ fitToContainer: true,
8757
+ plotsWithData: [plot],
8758
+ sharedTimesteps: sharedTimesteps,
8759
+ shouldShowLegend: false,
8760
+ shouldShowZoom: false,
8761
+ synchronization: synchronization
8762
+ })
8763
+ })]
7960
8764
  });
7961
8765
  };
7962
8766
  var TimeSeriesView = /*#__PURE__*/React.memo(function (_ref2) {
7963
- var plotPreset = _ref2.plotPreset,
8767
+ var viewId = _ref2.viewId,
8768
+ plotPreset = _ref2.plotPreset,
7964
8769
  selectedLocation = _ref2.selectedLocation,
7965
8770
  services = _ref2.services,
7966
8771
  splitGeoJsonByCollection = _ref2.splitGeoJsonByCollection,
@@ -7969,32 +8774,21 @@ var TimeSeriesView = /*#__PURE__*/React.memo(function (_ref2) {
7969
8774
  shouldShowLegend = _ref2$shouldShowLegen === void 0 ? true : _ref2$shouldShowLegen,
7970
8775
  onToggleLegendParam = _ref2.onToggleLegendParam,
7971
8776
  syncgroupTimeState = _ref2.syncgroupTimeState;
7972
- var _useTimeseriesTransla = useTimeseriesTranslation(),
7973
- t = _useTimeseriesTransla.t;
7974
- var _React$useState = React.useState(0),
7975
- legendHeight = _React$useState[0],
7976
- setLegendHeight = _React$useState[1];
8777
+ var _useTimeseriesTransla2 = useTimeseriesTranslation(),
8778
+ t = _useTimeseriesTransla2.t;
8779
+ var synchronization = useChartSynchronization();
8780
+ var currentTime = useCurrentTime();
7977
8781
  var _useGetPlotsWithData = useGetPlotsWithData(plotPreset, selectedLocation, services, splitGeoJsonByCollection, t, syncgroupTimeState),
7978
8782
  plotsWithData = _useGetPlotsWithData.data,
7979
8783
  isFetchingPlots = _useGetPlotsWithData.isFetching;
8784
+ var sharedTimesteps = React.useMemo(function () {
8785
+ return getSharedTimesteps(plotsWithData != null ? plotsWithData : []);
8786
+ }, [plotsWithData]);
7980
8787
  React.useEffect(function () {
7981
8788
  if (isLoading) {
7982
8789
  isLoading(isFetchingPlots);
7983
8790
  }
7984
8791
  }, [isFetchingPlots, isLoading]);
7985
- var getErrorTitle = function getErrorTitle(parameters) {
7986
- var propertyNames = parameters.map(function (param) {
7987
- return param.propertyName;
7988
- });
7989
- if (propertyNames.length > 1) {
7990
- return "\"" + propertyNames.join('", "') + "\"";
7991
- }
7992
- return "\"" + (propertyNames[0] || '') + "\"";
7993
- };
7994
- var getErrorTranslationKey = function getErrorTranslationKey(errorKey, parameterCount) {
7995
- // Use plural translation only when multiple parameters fail with error-message-general
7996
- return errorKey === 'error-message-general' && parameterCount > 1 ? 'error-message-general-plural' : errorKey;
7997
- };
7998
8792
  var getCombinedErrorInfo = React.useCallback(function (parametersFailingInAllPlots, plotsWithData, totalPlotCount) {
7999
8793
  var _plotsWithData$;
8000
8794
  if (parametersFailingInAllPlots.length === 0 || totalPlotCount === 0) {
@@ -8011,8 +8805,8 @@ var TimeSeriesView = /*#__PURE__*/React.memo(function (_ref2) {
8011
8805
  }
8012
8806
  var parameterCounts = {};
8013
8807
  plotsWithData.forEach(function (plot) {
8014
- var _plot$failedParameter2;
8015
- (_plot$failedParameter2 = plot.failedParameters) == null || _plot$failedParameter2.forEach(function (param) {
8808
+ var _plot$failedParameter3;
8809
+ (_plot$failedParameter3 = plot.failedParameters) == null || _plot$failedParameter3.forEach(function (param) {
8016
8810
  var key = getParameterKey(param);
8017
8811
  if (parameterCounts[key]) {
8018
8812
  parameterCounts[key].count += 1;
@@ -8041,8 +8835,28 @@ var TimeSeriesView = /*#__PURE__*/React.memo(function (_ref2) {
8041
8835
  var combinedErrorInfo = React.useMemo(function () {
8042
8836
  return hasParametersFailingInAllPlots ? getCombinedErrorInfo(parametersFailingInAllPlots, plotsWithData, totalPlotCount) : '';
8043
8837
  }, [getCombinedErrorInfo, hasParametersFailingInAllPlots, parametersFailingInAllPlots, plotsWithData, totalPlotCount]);
8044
- return jsxs(Box, {
8838
+ var renderPlot = function renderPlot(plotId) {
8839
+ var plot = plotsWithData == null ? void 0 : plotsWithData.find(function (item) {
8840
+ return item.plotId === plotId;
8841
+ });
8842
+ return plot ? jsx(TimeSeriesPlot, {
8843
+ currentTime: currentTime,
8844
+ parametersFailingInAllPlots: parametersFailingInAllPlots,
8845
+ plot: plot,
8846
+ sharedTimesteps: sharedTimesteps,
8847
+ synchronization: synchronization
8848
+ }) : null;
8849
+ };
8850
+ return jsxs(Card, {
8045
8851
  "data-testid": "TimeSeriesView",
8852
+ sx: {
8853
+ width: '100%',
8854
+ height: '100%',
8855
+ position: 'relative',
8856
+ display: 'flex',
8857
+ flexDirection: 'column',
8858
+ gap: 1
8859
+ },
8046
8860
  children: [hasParametersFailingInAllPlots ? jsx(Card, {
8047
8861
  sx: {
8048
8862
  border: 'solid 1px',
@@ -8057,37 +8871,53 @@ var TimeSeriesView = /*#__PURE__*/React.memo(function (_ref2) {
8057
8871
  title: combinedErrorTitle
8058
8872
  })
8059
8873
  })
8060
- }) : null, !!plotsWithData && plotsWithData.length > 0 && jsxs(Card, {
8874
+ }) : null, !!(plotsWithData != null && plotsWithData.length) && !!shouldShowLegend && jsx(Box, {
8061
8875
  sx: {
8062
- border: 'solid 1px',
8063
- borderColor: 'geowebColors.cards.cardContainerBorder',
8064
- boxShadow: 'none',
8065
- position: 'relative'
8876
+ flex: '0 0 auto',
8877
+ mb: -1
8066
8878
  },
8067
- children: [!!plotsWithData && plotsWithData.length > 0 && jsx(PlotErrorBanners, {
8068
- getErrorTitle: getErrorTitle,
8069
- getErrorTranslationKey: getErrorTranslationKey,
8070
- legendHeight: legendHeight,
8071
- parametersFailingInAllPlots: parametersFailingInAllPlots,
8072
- plotsWithData: plotsWithData,
8073
- t: t
8074
- }), jsx(TimeSeriesChart, {
8075
- onLegendHeightChange: setLegendHeight,
8879
+ children: jsx(TimeSeriesChart, {
8880
+ controlsOnly: "legend",
8076
8881
  onToggleLegendParam: onToggleLegendParam,
8077
8882
  plotsWithData: plotsWithData,
8078
- shouldShowLegend: shouldShowLegend
8079
- })]
8883
+ shouldShowZoom: false
8884
+ })
8885
+ }), !!(plotsWithData != null && plotsWithData.length) && jsx(Box, {
8886
+ sx: {
8887
+ flex: 1,
8888
+ minHeight: 0,
8889
+ width: '100%',
8890
+ overflow: 'auto'
8891
+ },
8892
+ children: jsx(TimeSeriesPanelsConnect, {
8893
+ renderPlot: renderPlot,
8894
+ viewId: viewId
8895
+ })
8896
+ }), !!(plotsWithData != null && plotsWithData.length) && jsx(Box, {
8897
+ sx: {
8898
+ flex: '0 0 auto'
8899
+ },
8900
+ children: jsx(TimeSeriesChart, {
8901
+ controlsOnly: "zoom",
8902
+ currentTime: currentTime,
8903
+ plotsWithData: plotsWithData,
8904
+ sharedTimesteps: sharedTimesteps,
8905
+ shouldShowLegend: false,
8906
+ synchronization: synchronization
8907
+ })
8080
8908
  })]
8081
8909
  });
8082
8910
  }, function (previousProps, nextProps) {
8083
8911
  var _previousProps$syncgr, _nextProps$syncgroupT, _previousProps$syncgr2, _nextProps$syncgroupT2;
8912
+ var sameView = previousProps.viewId === nextProps.viewId;
8913
+ var sameCallbacks = previousProps.isLoading === nextProps.isLoading && previousProps.onToggleLegendParam === nextProps.onToggleLegendParam;
8084
8914
  var samePreset = previousProps.plotPreset === nextProps.plotPreset;
8085
8915
  var sameLocation = isEqual(previousProps.selectedLocation, nextProps.selectedLocation);
8086
8916
  var sameGeoJson = isEqual(previousProps.splitGeoJsonByCollection, nextProps.splitGeoJsonByCollection);
8087
8917
  var sameLegend = previousProps.shouldShowLegend === nextProps.shouldShowLegend;
8088
8918
  var sameServices = isEqual(previousProps.services, nextProps.services);
8089
8919
  var sameTime = ((_previousProps$syncgr = previousProps.syncgroupTimeState) == null ? void 0 : _previousProps$syncgr.start) === ((_nextProps$syncgroupT = nextProps.syncgroupTimeState) == null ? void 0 : _nextProps$syncgroupT.start) && ((_previousProps$syncgr2 = previousProps.syncgroupTimeState) == null ? void 0 : _previousProps$syncgr2.end) === ((_nextProps$syncgroupT2 = nextProps.syncgroupTimeState) == null ? void 0 : _nextProps$syncgroupT2.end);
8090
- return samePreset && sameLocation && sameGeoJson && sameLegend && sameServices && sameTime;
8920
+ return sameView && sameCallbacks && samePreset && sameLocation && sameGeoJson && sameLegend && sameServices && sameTime;
8091
8921
  });
8092
8922
 
8093
8923
  /* *
@@ -8466,7 +9296,8 @@ var TimeSeriesConnect = function TimeSeriesConnect(_ref2) {
8466
9296
  })
8467
9297
  }), !!timeSeriesLocation && !!plotPresetState && jsx(Box, {
8468
9298
  sx: {
8469
- overflow: 'auto'
9299
+ flex: 1,
9300
+ minHeight: 0
8470
9301
  },
8471
9302
  children: !!plotPresetState && jsx(TimeSeriesView, {
8472
9303
  isLoading: isLoading,
@@ -8476,7 +9307,8 @@ var TimeSeriesConnect = function TimeSeriesConnect(_ref2) {
8476
9307
  services: services,
8477
9308
  shouldShowLegend: shouldShowLegend,
8478
9309
  splitGeoJsonByCollection: splitGeoJsonByCollection,
8479
- syncgroupTimeState: syncgroupTimeState
9310
+ syncgroupTimeState: syncgroupTimeState,
9311
+ viewId: panelId
8480
9312
  })
8481
9313
  })]
8482
9314
  });