@opengeoweb/workspace 15.3.0 → 16.0.0

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/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createEntityAdapter, createSlice, createSelector, createListenerMiddleware, isAnyOf, combineReducers, configureStore } from '@reduxjs/toolkit';
2
2
  import { handleResponse, getHeaders, getQueryClient, QueryClientProviderWrapper, useAuthenticationContext as useAuthenticationContext$1, GEOWEB_ROLE_PRESETS_ADMIN as GEOWEB_ROLE_PRESETS_ADMIN$1 } from '@opengeoweb/api';
3
- import { syncGroupsTypes, syncGroupsActions, layerActions, mapActions, uiActions, genericActions, layerTypes, mapEnums, selectorMemoizationOptions, genericSelectors, mapSelectors, syncGroupsSelectors, routerActions, createViewObjectForNewMap, mapListener, serviceListener, layersListener, syncGroupsListener, openlayersListener, uiReducer, loadingIndicatorReducer, syncGroupsReducer, layerReducer, serviceReducer, mapReducer, uiTypes, linkComponentTypesConstants, loadingIndicatorSelectors, uiSelectors } from '@opengeoweb/store';
3
+ import { syncGroupsTypes, syncGroupsActions, layerActions, mapActions, uiActions, genericActions, layerTypes, mapEnums, selectorMemoizationOptions, genericSelectors, mapSelectors, syncGroupsSelectors, routerActions, createViewObjectForNewMap, mapListener, serviceListener, layersListener, syncGroupsListener, openlayersListener, uiReducer, loadingIndicatorReducer, syncGroupsReducer, layerReducer, serviceReducer, mapReducer, uiTypes, linkComponentTypesConstants, constructSyncSourceDisplayName, loadingIndicatorSelectors, uiSelectors } from '@opengeoweb/store';
4
4
  import { timeSeriesActions, TimeSeriesTypes, timeSeriesSelectors, timeSeriesReducer } from '@opengeoweb/time-series';
5
5
  import { chunk, cloneDeep, union, pick, isEqual, isString } from 'lodash';
6
6
  import { getLeaves, createBalancedTreeFromLeaves, MosaicContext, getAndAssertNodeAtPathExists, MosaicWindow, Mosaic } from 'react-mosaic-component';
@@ -14,13 +14,13 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
14
14
  import { useTranslation, I18nextProvider } from 'react-i18next';
15
15
  import { Provider, useDispatch, useSelector, useStore, shallowEqual } from 'react-redux';
16
16
  import { AuthenticationProvider, useAuthenticationContext, GEOWEB_ROLE_PRESETS_ADMIN } from '@opengeoweb/authentication';
17
- import { ThemeWrapper, lightTheme, Link, LinkOff, SplitVertical, SplitHorizontal, Expand, UnExpand, Close, ChevronUp, ChevronDown, LockLocked, Info, WorkspacePresetsSystemIcon, SharedPresetsMyUser, SharedPresetsOtherUsers, WorkspacePresetsMyIcon, BackdropStyle, Options, CloudLoading, CloudIdle, WebAssetOff, Exclamation } from '@opengeoweb/theme';
17
+ import { ThemeWrapper, lightTheme, Link, LinkOff, SplitHorizontal, SplitVertical, SplitHorizontalWithContent, SplitVerticalWithContent, Expand, UnExpand, ChevronDown, Close, ChevronUp, LockLocked, Info, WorkspacePresetsSystemIcon, SharedPresetsMyUser, SharedPresetsOtherUsers, WorkspacePresetsMyIcon, BackdropStyle, Options, CloudLoading, CloudIdle, WebAssetOff, Exclamation } from '@opengeoweb/theme';
18
18
  import i18n from 'i18next';
19
19
  import { coreTranslations, CORE_NAMESPACE, LoadingIndicatorProgressBar } from '@opengeoweb/core';
20
20
  import { formFieldsTranslations, FORM_FIELDS_NAMESPACE, ReactHookFormHiddenInput, ReactHookFormTextField, ReactHookFormProvider, defaultFormOptions } from '@opengeoweb/form-fields';
21
21
  import { webmapReactTranslations, WEBMAP_REACT_NAMESPACE } from '@opengeoweb/webmap-react';
22
22
  import React, { useEffect, useCallback } from 'react';
23
- import { Menu, Typography, List, ListItem, ListItemButton, ListItemIcon, Checkbox, ListItemText, LinearProgress, Box, Button, Stack, FormControlLabel, Chip, Popper, ClickAwayListener, Paper, IconButton, Collapse, Divider, Grid, useTheme, ListSubheader, MenuItem, Tabs } from '@mui/material';
23
+ import { Menu, Typography, List, ListItem, ListItemButton, ListItemIcon, Checkbox, ListItemText, MenuItem, useTheme, Box, LinearProgress, Button, Stack, FormControlLabel, Chip, Popper, ClickAwayListener, Paper, IconButton, Collapse, Divider, Grid, TextField, ListSubheader, Tabs } from '@mui/material';
24
24
  import 'react-mosaic-component/react-mosaic-component.css';
25
25
  import { useFormContext, useWatch, useForm, FormProvider } from 'react-hook-form';
26
26
  import { List as List$1 } from 'react-window';
@@ -60,8 +60,11 @@ var en = {
60
60
  "workspace-control-split-horizontal": "Split window horizontally",
61
61
  "workspace-control-split-vertical": "Split window vertically",
62
62
  "workspace-control-split-shift": "Hold shift to copy viewpreset content",
63
+ "workspace-control-split-horizontal-with-data": "Split window horizontally and copy over viewpreset content",
64
+ "workspace-control-split-vertical-with-data": "Split window vertically and copy over viewpreset content",
63
65
  "workspace-control-expand": "Expand window",
64
66
  "workspace-control-unexpand": "Unexpand window",
67
+ "workspace-control-show-options": "Show options",
65
68
  "workspace-control-close": "Close window",
66
69
  "workspace-control-close-message-title": "Whoops",
67
70
  "workspace-control-close-message-description": "Are you sure you want to close this window? All changes will be lost.",
@@ -147,7 +150,29 @@ var en = {
147
150
  "workspace-label-active": "ACTIVE",
148
151
  "fetch-config-error-retry": "Retry",
149
152
  "fetch-config-error-title": "An error has occured whilst fetching the label configuration",
150
- "fetch-config-no-labels-available": "There are no labels available, please contact your administrator"
153
+ "fetch-config-no-labels-available": "There are no labels available, please contact your administrator",
154
+ "workspace-copy-to-clipboard": "Copy workspace",
155
+ "workspace-paste-from-clipboard": "Paste workspace",
156
+ "workspace-copy-viewpreset-to-clipboard": "Copy view preset",
157
+ "workspace-paste-viewpreset-from-clipboard": "Paste view preset",
158
+ "workspace-paste-dialog-title": "Paste workspace from clipboard",
159
+ "workspace-paste-viewpreset-dialog-title": "Paste view preset from clipboard",
160
+ "workspace-paste-load-button": "Load workspace",
161
+ "workspace-paste-load-viewpreset-button": "Load view preset",
162
+ "workspace-paste-placeholder": "Paste workspace from clipboard",
163
+ "workspace-paste-viewpreset-placeholder": "Paste view preset from clipboard",
164
+ "workspace-paste-field-label": "Workspace JSON",
165
+ "workspace-paste-viewpreset-field-label": "View preset JSON",
166
+ "workspace-copy-success": "Workspace copied",
167
+ "workspace-paste-success": "Workspace loaded",
168
+ "workspace-copy-viewpreset-success": "View preset copied",
169
+ "workspace-paste-viewpreset-success": "View preset loaded",
170
+ "workspace-paste-validation-invalid-json": "Invalid JSON: {{ERROR}}",
171
+ "workspace-paste-validation-not-object": "Input must be a JSON object",
172
+ "workspace-paste-validation-missing-field": "Missing required field: \"{{ERROR}}\"",
173
+ "workspace-paste-validation-unexpanded-views": "Workspace contains view preset references. Use the Copy button to get a portable version.",
174
+ "workspace-paste-validation-wrong-preset-type": "The clipboard contains a view preset, not a workspace preset.",
175
+ "viewpreset-paste-validation-wrong-preset-type": "The clipboard contains a workspace preset, not a view preset."
151
176
  };
152
177
  var fi = {
153
178
  "workspace-menu": "Workspace menu",
@@ -182,8 +207,11 @@ var fi = {
182
207
  "workspace-control-split-horizontal": "Jaa ikkuna vaakasuoraan",
183
208
  "workspace-control-split-vertical": "Jaa ikkuna pystysuoraan",
184
209
  "workspace-control-split-shift": "Pidä Shift painettuna kopioidaksesi näkymän sisällön",
210
+ "workspace-control-split-horizontal-with-data": "Jaa ikkuna vaakasuunnassa kopioitaessa sisällön päälle",
211
+ "workspace-control-split-vertical-with-data": "Jaa ikkuna pystysuunnassa kopioitaessa sisällön päälle",
185
212
  "workspace-control-expand": "Laajenna ikkuna",
186
213
  "workspace-control-unexpand": "Supista ikkuna",
214
+ "workspace-control-show-options": "Näytä asetukset",
187
215
  "workspace-control-close": "Sulje ikkuna",
188
216
  "workspace-control-close-message-title": "Hups",
189
217
  "workspace-control-close-message-description": "Oletko varma, että haluat sulkea tämän ikkunan? Kaikki muutokset menetetään",
@@ -262,7 +290,29 @@ var fi = {
262
290
  "workspace-labels-dataSource": "ei käännetty",
263
291
  "workspace-labels-viewType": "ei käännetty",
264
292
  "workspace-presets-form-active-labels": "ei käännetty ({{count}})",
265
- "workspace-label-active": "ACTIVE"
293
+ "workspace-label-active": "ACTIVE",
294
+ "workspace-copy-to-clipboard": "Copy workspace",
295
+ "workspace-paste-from-clipboard": "Paste workspace",
296
+ "workspace-copy-viewpreset-to-clipboard": "Copy view preset",
297
+ "workspace-paste-viewpreset-from-clipboard": "Paste view preset",
298
+ "workspace-paste-dialog-title": "Paste workspace",
299
+ "workspace-paste-viewpreset-dialog-title": "Paste view preset",
300
+ "workspace-paste-load-button": "Load workspace",
301
+ "workspace-paste-load-viewpreset-button": "Load view preset",
302
+ "workspace-paste-placeholder": "Paste workspace JSON here",
303
+ "workspace-paste-viewpreset-placeholder": "Paste view preset JSON here",
304
+ "workspace-paste-field-label": "Workspace JSON",
305
+ "workspace-paste-viewpreset-field-label": "View preset JSON",
306
+ "workspace-copy-success": "Workspace JSON copied to clipboard",
307
+ "workspace-paste-success": "Workspace loaded",
308
+ "workspace-copy-viewpreset-success": "View preset JSON copied to clipboard",
309
+ "workspace-paste-viewpreset-success": "View preset loaded",
310
+ "workspace-paste-validation-invalid-json": "Invalid JSON: {{ERROR}}",
311
+ "workspace-paste-validation-not-object": "Input must be a JSON object",
312
+ "workspace-paste-validation-missing-field": "Missing required field: \"{{ERROR}}\"",
313
+ "workspace-paste-validation-unexpanded-views": "Workspace contains view preset references. Use the Copy button to get a portable version.",
314
+ "workspace-paste-validation-wrong-preset-type": "The clipboard contains a view preset, not a workspace preset.",
315
+ "viewpreset-paste-validation-wrong-preset-type": "The clipboard contains a workspace preset, not a view preset."
266
316
  };
267
317
  var no = {
268
318
  "workspace-menu": "Arbeidsflater",
@@ -298,8 +348,11 @@ var no = {
298
348
  "workspace-control-split-horizontal": "Splitt vindu horisontalt",
299
349
  "workspace-control-split-vertical": "Splitt vindu vertikalt",
300
350
  "workspace-control-split-shift": "Hold shift for å kopiere viewpreset-innhold",
351
+ "workspace-control-split-horizontal-with-data": "Splitt vindu horisontalt og kopierer viewpreset-innhold",
352
+ "workspace-control-split-vertical-with-data": "Splitt vindu vertikalt og kopierer viewpreset-innhold",
301
353
  "workspace-control-expand": "Utvid vindu",
302
354
  "workspace-control-unexpand": "Krymp vindu",
355
+ "workspace-control-show-options": "Vis alternativer",
303
356
  "workspace-control-close": "Lukk vindu",
304
357
  "workspace-control-close-message-title": "Whoops",
305
358
  "workspace-control-close-message-description": "Er du sikker på at du vil lukke vinduet? Alle endringer vil slettes.",
@@ -378,7 +431,29 @@ var no = {
378
431
  "workspace-labels-dataSource": "Datakilde",
379
432
  "workspace-labels-viewType": "Komponent",
380
433
  "workspace-presets-form-active-labels": "Aktive valg ({{count}})",
381
- "workspace-label-active": "AKTIV"
434
+ "workspace-label-active": "AKTIV",
435
+ "workspace-copy-to-clipboard": "Kopier arbeidsflate som JSON",
436
+ "workspace-paste-from-clipboard": "Last arbeidsflate fra JSON",
437
+ "workspace-copy-viewpreset-to-clipboard": "Kopier snarvei som JSON",
438
+ "workspace-paste-viewpreset-from-clipboard": "Last snarvei fra JSON",
439
+ "workspace-paste-dialog-title": "Last inn arbeidsflate fra JSON",
440
+ "workspace-paste-viewpreset-dialog-title": "Last snarvei fra JSON",
441
+ "workspace-paste-load-button": "Last inn arbeidsflate",
442
+ "workspace-paste-load-viewpreset-button": "Last inn snarvei",
443
+ "workspace-paste-placeholder": "Lim inn arbeidsflate-JSON her",
444
+ "workspace-paste-viewpreset-placeholder": "Lim inn snarvei-JSON her",
445
+ "workspace-paste-field-label": "Arbeidsflate-JSON",
446
+ "workspace-paste-viewpreset-field-label": "Snarvei-JSON",
447
+ "workspace-copy-success": "Arbeidsflate-JSON kopiert til utklippstavlen",
448
+ "workspace-paste-success": "Arbeidsflate lastet inn",
449
+ "workspace-copy-viewpreset-success": "Snarvei-JSON kopiert til utklippstavlen",
450
+ "workspace-paste-viewpreset-success": "Snarvei lastet inn",
451
+ "workspace-paste-validation-invalid-json": "Ugyldig JSON: {{ERROR}}",
452
+ "workspace-paste-validation-not-object": "Inndata må være et JSON-objekt",
453
+ "workspace-paste-validation-missing-field": "Mangler påkrevd felt: \"{{ERROR}}\"",
454
+ "workspace-paste-validation-unexpanded-views": "Arbeidsflaten inneholder referanser til snarveier. Bruk Kopier-knappen for å få en kompatibel versjon.",
455
+ "workspace-paste-validation-wrong-preset-type": "Utklippstavlen inneholder en Snarvei, ikke en Arbeidsflate.",
456
+ "viewpreset-paste-validation-wrong-preset-type": "Utklippstavlen inneholder en Arbeidsflate, ikke en Snarvei."
382
457
  };
383
458
  var nl = {
384
459
  "workspace-menu": "Workspace menu",
@@ -414,8 +489,11 @@ var nl = {
414
489
  "workspace-control-split-horizontal": "Splits paneel horizontaal",
415
490
  "workspace-control-split-vertical": "Splits paneel verticaal",
416
491
  "workspace-control-split-shift": "Houdt Shift ingedrukt om viewpreset te kopieren",
492
+ "workspace-control-split-horizontal-with-data": "Splits paneel horizontaal en kopieer de viewpreset",
493
+ "workspace-control-split-vertical-with-data": "Splits paneel verticaal en kopieer de viewpreset",
417
494
  "workspace-control-expand": "Vergroot paneel",
418
495
  "workspace-control-unexpand": "Verklein paneel",
496
+ "workspace-control-show-options": "Opties weergeven",
419
497
  "workspace-control-close": "Sluit paneel",
420
498
  "workspace-control-close-message-title": "Oeps",
421
499
  "workspace-control-close-message-description": "Weet je zeker dat je dit paneel wilt sluiten? Alle wijzigingen zullen verloren gaan",
@@ -499,7 +577,29 @@ var nl = {
499
577
  "workspace-label-active": "ACTIVE",
500
578
  "fetch-config-error-retry": "Opnieuw proberen",
501
579
  "fetch-config-error-title": "Het ophalen van de label configuratie is mislukt",
502
- "fetch-config-no-labels-available": "Er zijn geen labels beschikbaar, neem contact op met de administrator"
580
+ "fetch-config-no-labels-available": "Er zijn geen labels beschikbaar, neem contact op met de administrator",
581
+ "workspace-copy-to-clipboard": "Kopieer als JSON",
582
+ "workspace-paste-from-clipboard": "Laad vanuit JSON",
583
+ "workspace-copy-viewpreset-to-clipboard": "Kopieer view preset als JSON",
584
+ "workspace-paste-viewpreset-from-clipboard": "Laad view preset vanuit JSON",
585
+ "workspace-paste-dialog-title": "Laad workspace vanuit JSON",
586
+ "workspace-paste-viewpreset-dialog-title": "Laad view preset vanuit JSON",
587
+ "workspace-paste-load-button": "Laad workspace",
588
+ "workspace-paste-load-viewpreset-button": "Laad view preset",
589
+ "workspace-paste-placeholder": "Plak workspace JSON hier",
590
+ "workspace-paste-viewpreset-placeholder": "Plak view preset JSON hier",
591
+ "workspace-paste-field-label": "Workspace JSON",
592
+ "workspace-paste-viewpreset-field-label": "View preset JSON",
593
+ "workspace-copy-success": "Workspace JSON is gekopieerd naar het clipboard",
594
+ "workspace-paste-success": "Workspace geladen",
595
+ "workspace-copy-viewpreset-success": "View preset JSON is gekopieerd naar het clipboard",
596
+ "workspace-paste-viewpreset-success": "View preset is geladen",
597
+ "workspace-paste-validation-invalid-json": "Ongeldige JSON: {{ERROR}}",
598
+ "workspace-paste-validation-not-object": "De invoer moet een geldig JSON-object zijn.",
599
+ "workspace-paste-validation-missing-field": "Ontbrekend verplicht veld: \"{{ERROR}}\"",
600
+ "workspace-paste-validation-unexpanded-views": "Workspace contains view preset references. Use the Copy button to get a portable version.",
601
+ "workspace-paste-validation-wrong-preset-type": "Het klembord bevat een weergave-opmaakprofiel, geen werkruimte-opmaakprofiel.",
602
+ "viewpreset-paste-validation-wrong-preset-type": "Het klembord bevat een werkruimte-opmaakprofiel, geen weergave-opmaakprofiel."
503
603
  };
504
604
  var workspaceTranslations = {
505
605
  en: en,
@@ -1266,6 +1366,7 @@ var WorkspacePresetAction;
1266
1366
  WorkspacePresetAction["SHARE"] = "SHARE";
1267
1367
  WorkspacePresetAction["OPEN_TAB"] = "OPEN_TAB";
1268
1368
  WorkspacePresetAction["EDIT_TITLE"] = "EDIT_TITLE";
1369
+ WorkspacePresetAction["COPY_TO_CLIPBOARD"] = "COPY_TO_CLIPBOARD";
1269
1370
  })(WorkspacePresetAction || (WorkspacePresetAction = {}));
1270
1371
  var WorkspaceErrorType;
1271
1372
  (function (WorkspaceErrorType) {
@@ -1564,7 +1665,7 @@ var viewPresetsAdapter = createEntityAdapter({
1564
1665
  var initialState$1 = viewPresetsAdapter.getInitialState();
1565
1666
  var warningsPresetChangeActions = [warningsFiltersActions.setWarningFilters];
1566
1667
  var syncGroupChangeActions = [syncGroupsActions.syncGroupRemoveTarget, syncGroupsActions.syncGroupAddTarget];
1567
- var mapPresetChangeActions = [layerActions.setBaseLayers, layerActions.layerDelete, layerActions.addLayer, layerActions.duplicateMapLayer, layerActions.layerChangeEnabled, layerActions.layerChangeName, layerActions.layerChangeStyle, layerActions.layerChangeOpacity, layerActions.layerChangeDimension, layerActions.layerChangeAcceptanceTime, mapActions.layerMoveLayer, mapActions.setAutoLayerId, mapActions.setAutoTimestepLayerId, mapActions.setAutoUpdateLayerId, mapActions.toggleAutoUpdate, mapActions.mapStartAnimation, mapActions.mapStopAnimation, mapActions.toggleTimeSliderIsVisible, mapActions.setTimeStep, mapActions.setTimeSliderSpan, mapActions.toggleTimeSpanAuto, mapActions.setAnimationDelay, mapActions.toggleTimestepAuto, mapActions.setAnimationStartTime, mapActions.setAnimationEndTime, mapActions.changeOverlayer, uiActions.setActiveMapIdForDialog, uiActions.setToggleOpenDialog, genericActions.setBbox, mapActions.setBbox, mapActions.toggleClock, mapActions.setClockPositionSize, mapActions.setDockedLayerManagerSize, mapActions.setDockedLayerManagerPosition, mapActions.setDockedLayerManagerDimensions];
1668
+ var mapPresetChangeActions = [layerActions.setBaseLayers, layerActions.layerDelete, layerActions.addLayer, layerActions.duplicateMapLayer, layerActions.layerChangeEnabled, layerActions.layerChangeName, layerActions.layerChangeStyle, layerActions.layerChangeOpacity, layerActions.layerChangeDimension, layerActions.layerChangeAcceptanceTime, mapActions.layerMoveLayer, mapActions.setAutoLayerId, mapActions.setAutoTimestepLayerId, mapActions.setAutoUpdateLayerId, mapActions.toggleAutoUpdate, mapActions.mapStartAnimation, mapActions.mapStopAnimation, mapActions.toggleTimeSliderIsVisible, mapActions.setTimeStep, mapActions.setTimeSliderSpan, mapActions.toggleTimeSpanAuto, mapActions.setAnimationDelay, mapActions.toggleTimestepAuto, mapActions.setAnimationStartTime, mapActions.setAnimationEndTime, mapActions.changeOverlayer, uiActions.setActiveMapIdForDialog, uiActions.setToggleOpenDialog, genericActions.setBbox, mapActions.setBbox, mapActions.toggleClock, mapActions.toggleClockOptions, mapActions.setClockPositionSize, mapActions.setDockedLayerManagerSize, mapActions.setDockedLayerManagerPosition, mapActions.setDockedLayerManagerDimensions];
1568
1669
  var timeSeriesPresetChangeActions = [timeSeriesActions.addParameter, timeSeriesActions.addPlot, timeSeriesActions.deleteParameter, timeSeriesActions.deletePlot, timeSeriesActions.moveParameter, timeSeriesActions.movePlot, timeSeriesActions.toggleParameter, timeSeriesActions.togglePlot, timeSeriesActions.patchParameter, timeSeriesActions.updateTitle];
1569
1670
  var soundingsChangeActions = [soundingsActions.updateSelectedSource, soundingsActions.updateSelectedLocation, soundingsActions.updateSelectedTime, soundingsActions.updateDiagramType, soundingsActions.toggleLocationMarkers, soundingsActions.changeSoundingPanelOrder, soundingsActions.toggleSoundingPanelVisibility];
1570
1671
  var supportedMapActionOrigins = [layerTypes.LayerActionOrigin.layerManager, layerTypes.LayerActionOrigin.wmsLoader, mapEnums.MapActionOrigin.map];
@@ -2214,7 +2315,8 @@ var getEmptyWorkspacePreset = function getEmptyWorkspacePreset() {
2214
2315
  }
2215
2316
  },
2216
2317
  mosaicNode: '1_screen',
2217
- viewType: 'singleWindow'
2318
+ viewType: 'singleWindow',
2319
+ username: 'global'
2218
2320
  };
2219
2321
  };
2220
2322
  var createCustomEmptyMapWorkspace = function createCustomEmptyMapWorkspace(emptyWorkspaceTitle, emptyMapWorkspaceTitle, customMapPreset) {
@@ -2335,7 +2437,9 @@ var slice = createSlice({
2335
2437
  draft.description = workspacePreset.description;
2336
2438
  draft.labels = workspacePreset.labels;
2337
2439
  draft.scope = workspacePreset.scope;
2440
+ draft.username = workspacePreset.username;
2338
2441
  draft.syncGroups = [];
2442
+ draft.username = workspacePreset.username;
2339
2443
  },
2340
2444
  changeToEmptyMapWorkspace: function changeToEmptyMapWorkspace(draft, action) {
2341
2445
  return draft;
@@ -2370,6 +2474,7 @@ var slice = createSlice({
2370
2474
  draft.isTimeScrollingEnabled = action.payload.workspacePreset.isTimeScrollingEnabled;
2371
2475
  draft.labels = action.payload.workspacePreset.labels;
2372
2476
  draft.description = action.payload.workspacePreset.description;
2477
+ draft.username = action.payload.workspacePreset.username;
2373
2478
  return draft;
2374
2479
  },
2375
2480
  setPreventCloseView: function setPreventCloseView(draft, action) {
@@ -2396,6 +2501,7 @@ var slice = createSlice({
2396
2501
  draft["abstract"] = ws["abstract"];
2397
2502
  draft.labels = ws.labels;
2398
2503
  draft.description = ws.description;
2504
+ draft.username = typeof ws.username === 'string' ? ws.username : undefined;
2399
2505
  var wsViews = ws.views;
2400
2506
  var viewsArray = [];
2401
2507
  if (Array.isArray(wsViews)) {
@@ -2464,6 +2570,7 @@ var slice = createSlice({
2464
2570
  draft.labels = action.payload.labels;
2465
2571
  draft.hasChanges = false;
2466
2572
  draft.scope = action.payload.scope || 'user';
2573
+ draft.username = 'username' in action.payload && typeof action.payload.username === 'string' ? action.payload.username : undefined;
2467
2574
  }
2468
2575
  if ((action.payload.action === WorkspacePresetAction.EDIT || action.payload.action === WorkspacePresetAction.EDIT_TITLE) && action.payload.workspaceId === draft.id) {
2469
2576
  var _draft$views;
@@ -2490,7 +2597,9 @@ var slice = createSlice({
2490
2597
  draft.title = action.payload.emptyWorkspacePresetTitle;
2491
2598
  draft["abstract"] = getEmptyMapWorkspace()["abstract"];
2492
2599
  draft.scope = getEmptyMapWorkspace().scope;
2600
+ draft.username = undefined;
2493
2601
  draft.hasChanges = true;
2602
+ draft.username = '';
2494
2603
  }
2495
2604
  }).addCase(viewPresetActions.fetchedViewPreset, function (draft, action) {
2496
2605
  var _action$payload4 = action.payload,
@@ -2709,6 +2818,10 @@ var getComponentTypesFromActiveViews = createSelector([function (state) {
2709
2818
  var getMosaicNode = createSelector(getWorkspaceState, function (state) {
2710
2819
  return state == null ? void 0 : state.mosaicNode;
2711
2820
  }, selectorMemoizationOptions);
2821
+ var getWorkspaceId = function getWorkspaceId(store) {
2822
+ var _getWorkspaceState;
2823
+ return (_getWorkspaceState = getWorkspaceState(store)) == null ? void 0 : _getWorkspaceState.id;
2824
+ };
2712
2825
  /**
2713
2826
  * Gets view from workspace state
2714
2827
  *
@@ -2823,7 +2936,8 @@ var getWorkspaceData = createSelector(getWorkspaceState, genericSelectors.getSyn
2823
2936
  linking: linkedState,
2824
2937
  labels: workspaceStore.labels,
2825
2938
  description: workspaceStore.description,
2826
- updated: workspaceStore.updated
2939
+ updated: workspaceStore.updated,
2940
+ username: workspaceStore.username
2827
2941
  };
2828
2942
  }, selectorMemoizationOptions);
2829
2943
  var getViewComponentType = createSelector(getViewById, function (store) {
@@ -2884,6 +2998,7 @@ var selectors$2 = /*#__PURE__*/Object.freeze({
2884
2998
  getViewsById: getViewsById,
2885
2999
  getWorkspaceData: getWorkspaceData,
2886
3000
  getWorkspaceError: getWorkspaceError,
3001
+ getWorkspaceId: getWorkspaceId,
2887
3002
  getWorkspaceState: getWorkspaceState,
2888
3003
  hasWorkspaceChanges: hasWorkspaceChanges,
2889
3004
  isWorkspaceLoading: isWorkspaceLoading
@@ -3551,7 +3666,8 @@ workspaceListListener.startListening({
3551
3666
  description: data.description,
3552
3667
  labels: data.labels,
3553
3668
  updated: data.updated,
3554
- updatedBy: data.updatedBy
3669
+ updatedBy: data.updatedBy,
3670
+ username: data.username
3555
3671
  });
3556
3672
  _context2.next = 16;
3557
3673
  return getQueryClient().fetchQuery(workspaceQueryOptions.saveWorkspacePreset(presetId, workspaceDataNewTitle, credentials));
@@ -3568,6 +3684,7 @@ workspaceListListener.startListening({
3568
3684
  labels: data.labels,
3569
3685
  updated: data.updated,
3570
3686
  updatedBy: data.updatedBy,
3687
+ username: data.username,
3571
3688
  scope: scope
3572
3689
  }));
3573
3690
  case 19:
@@ -3605,6 +3722,7 @@ workspaceListListener.startListening({
3605
3722
  // keep original workspace title/abstract untouched
3606
3723
  title: _originalData.title,
3607
3724
  "abstract": _originalData["abstract"],
3725
+ username: _originalData.username,
3608
3726
  scope: scope,
3609
3727
  // you can send only the edited ones, or the merged full list.
3610
3728
  // Reducer uses mosaicNodeId+title from `views` to patch state.
@@ -3636,7 +3754,8 @@ workspaceListListener.startListening({
3636
3754
  description: data.description,
3637
3755
  labels: data.labels,
3638
3756
  scope: scope,
3639
- views: viewsWithInitialProps
3757
+ views: viewsWithInitialProps,
3758
+ username: (credentials == null ? void 0 : credentials.username) || ''
3640
3759
  });
3641
3760
  if (!(!hasWorkspaceAlreadyBeenSaved && isSaveAsWorkspaceAction)) {
3642
3761
  _context2.next = 44;
@@ -3676,6 +3795,7 @@ workspaceListListener.startListening({
3676
3795
  "abstract": newWorkspace["abstract"],
3677
3796
  description: newWorkspace.description,
3678
3797
  labels: newWorkspace.labels,
3798
+ username: newWorkspace.username,
3679
3799
  scope: scope
3680
3800
  }));
3681
3801
  listenerApi.dispatch(routerActions.navigateToUrl({
@@ -3884,7 +4004,13 @@ workspaceListener.startListening({
3884
4004
  isInline: hasInlineConfig
3885
4005
  }));
3886
4006
  });
3887
- case 18:
4007
+ if (payload.markAsChanged) {
4008
+ listenerApi.dispatch(workspaceActions.markWorkspaceChanged());
4009
+ listenerApi.dispatch(routerActions.navigateToUrl({
4010
+ url: getWorkspaceRouteUrl()
4011
+ }));
4012
+ }
4013
+ case 19:
3888
4014
  case "end":
3889
4015
  return _context4.stop();
3890
4016
  }
@@ -4109,7 +4235,7 @@ workspaceListener.startListening({
4109
4235
  actionCreator: workspaceActions.saveWorkspacePreset,
4110
4236
  effect: function () {
4111
4237
  var _effect6 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee0(_ref9, listenerApi) {
4112
- var payload, workspace, _listenerApi$getState3, _workspace$scope, credentials;
4238
+ var payload, workspace, _listenerApi$getState3, _workspace$scope, _workspace$username, credentials;
4113
4239
  return _regeneratorRuntime().wrap(function _callee0$(_context0) {
4114
4240
  while (1) switch (_context0.prev = _context0.next) {
4115
4241
  case 0:
@@ -4131,7 +4257,8 @@ workspaceListener.startListening({
4131
4257
  workspaceId: workspace.id,
4132
4258
  title: workspace.title,
4133
4259
  scope: (_workspace$scope = workspace.scope) != null ? _workspace$scope : 'user',
4134
- views: workspace.views || [emptyWorkspaceBEData]
4260
+ views: workspace.views || [emptyWorkspaceBEData],
4261
+ username: (_workspace$username = workspace.username) != null ? _workspace$username : ''
4135
4262
  }));
4136
4263
  _context0.next = 16;
4137
4264
  break;
@@ -4702,12 +4829,12 @@ var WorkspaceI18nProvider = function WorkspaceI18nProvider(_ref5) {
4702
4829
  });
4703
4830
  };
4704
4831
 
4705
- var _excluded$5 = ["component", "payload"];
4832
+ var _excluded$6 = ["component", "payload"];
4706
4833
  // takes a component and connects module methods with workspace store
4707
4834
  var ComponentsLookUpWrapper = function ComponentsLookUpWrapper(_ref) {
4708
4835
  var component = _ref.component,
4709
4836
  payload = _ref.payload,
4710
- props = _objectWithoutPropertiesLoose(_ref, _excluded$5);
4837
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$6);
4711
4838
  var RenderComponent = component;
4712
4839
  var dispatch = useDispatch();
4713
4840
  var viewId = payload.id;
@@ -4905,6 +5032,7 @@ var LinkMenuConnect = function LinkMenuConnect(_ref) {
4905
5032
  children: maps.map(function (mapId) {
4906
5033
  var _viewsById$mapId;
4907
5034
  var labelId = "checkbox-link-label-" + mapId;
5035
+ var mapTitle = constructSyncSourceDisplayName(mapId, viewsById[mapId], ((_viewsById$mapId = viewsById[mapId]) == null ? void 0 : _viewsById$mapId.title) || mapId);
4908
5036
  return jsx(ListItem, {
4909
5037
  dense: true,
4910
5038
  disablePadding: true,
@@ -4933,8 +5061,7 @@ var LinkMenuConnect = function LinkMenuConnect(_ref) {
4933
5061
  })
4934
5062
  }), jsx(ListItemText, {
4935
5063
  id: labelId,
4936
- primary: (_viewsById$mapId = viewsById[mapId]) == null ? void 0 : _viewsById$mapId.title,
4937
- secondary: mapId
5064
+ primary: mapTitle
4938
5065
  })]
4939
5066
  })
4940
5067
  }, mapId);
@@ -4944,13 +5071,29 @@ var LinkMenuConnect = function LinkMenuConnect(_ref) {
4944
5071
  });
4945
5072
  };
4946
5073
 
5074
+ var wrapInMenuItem = function wrapInMenuItem(inMenuItem, component, isDisabled) {
5075
+ if (isDisabled === void 0) {
5076
+ isDisabled = false;
5077
+ }
5078
+ if (inMenuItem) {
5079
+ return jsx(MenuItem, {
5080
+ disabled: isDisabled,
5081
+ children: component
5082
+ });
5083
+ }
5084
+ return component;
5085
+ };
4947
5086
  var buttonStyle$1 = {
4948
5087
  marginLeft: 0.5,
4949
5088
  marginRight: 0.5
4950
5089
  };
4951
5090
  var SplitButtonsConnect = function SplitButtonsConnect(_ref) {
4952
5091
  var panelId = _ref.panelId,
4953
- path = _ref.path;
5092
+ path = _ref.path,
5093
+ _ref$inMenuItem = _ref.inMenuItem,
5094
+ inMenuItem = _ref$inMenuItem === void 0 ? false : _ref$inMenuItem,
5095
+ _ref$isVerticalSplitD = _ref.isVerticalSplitDisabled,
5096
+ isVerticalSplitDisabled = _ref$isVerticalSplitD === void 0 ? false : _ref$isVerticalSplitD;
4954
5097
  var _useWorkspaceTranslat = useWorkspaceTranslation(),
4955
5098
  t = _useWorkspaceTranslat.t;
4956
5099
  var _React$useContext = React.useContext(MosaicContext),
@@ -4965,19 +5108,19 @@ var SplitButtonsConnect = function SplitButtonsConnect(_ref) {
4965
5108
  var addView = React.useCallback(function (view) {
4966
5109
  dispatch(workspaceActions.setNewWorkspaceView(view));
4967
5110
  }, [dispatch]);
4968
- var createNode = React.useCallback(function (shiftPressed) {
5111
+ var createNode = React.useCallback(function (copyContent) {
4969
5112
  var newId = getUniqueId(viewIds);
4970
5113
  addView({
4971
- // If shift not pressed - open new map
4972
- componentType: shiftPressed ? viewComponentType : 'Map',
5114
+ // If content not copied - open new map
5115
+ componentType: copyContent ? viewComponentType : 'Map',
4973
5116
  mosaicNodeId: panelId,
4974
5117
  newId: newId,
4975
- copyOriginalcontent: shiftPressed
5118
+ copyOriginalcontent: copyContent
4976
5119
  });
4977
5120
  return newId;
4978
5121
  }, [addView, panelId, viewComponentType, viewIds]);
4979
5122
  return jsxs(Fragment, {
4980
- children: [jsx(CustomIconButton, {
5123
+ children: [wrapInMenuItem(inMenuItem, jsx(CustomIconButton, {
4981
5124
  "data-testid": "split-horizontal-btn",
4982
5125
  onClick: function onClick(event) {
4983
5126
  var newNode = createNode(event.shiftKey);
@@ -4990,9 +5133,10 @@ var SplitButtonsConnect = function SplitButtonsConnect(_ref) {
4990
5133
  },
4991
5134
  sx: buttonStyle$1,
4992
5135
  tooltipTitle: t('workspace-control-split-horizontal') + " - " + t('workspace-control-split-shift'),
4993
- children: jsx(SplitVertical, {})
4994
- }), jsx(CustomIconButton, {
5136
+ children: jsx(SplitHorizontal, {})
5137
+ })), wrapInMenuItem(inMenuItem, jsx(CustomIconButton, {
4995
5138
  "data-testid": "split-vertical-btn",
5139
+ disabled: isVerticalSplitDisabled,
4996
5140
  onClick: function onClick(event) {
4997
5141
  var newNode = createNode(event.shiftKey);
4998
5142
  var previousNode = getAndAssertNodeAtPathExists(actions.getRoot(), path);
@@ -5004,8 +5148,39 @@ var SplitButtonsConnect = function SplitButtonsConnect(_ref) {
5004
5148
  },
5005
5149
  sx: buttonStyle$1,
5006
5150
  tooltipTitle: t('workspace-control-split-vertical') + " - " + t('workspace-control-split-shift'),
5007
- children: jsx(SplitHorizontal, {})
5008
- })]
5151
+ children: jsx(SplitVertical, {})
5152
+ }), isVerticalSplitDisabled), wrapInMenuItem(inMenuItem, jsx(CustomIconButton, {
5153
+ "data-testid": "split-horizontal-btn-copy-content",
5154
+ onClick: function onClick(event) {
5155
+ // Always copy over content
5156
+ var newNode = createNode(true);
5157
+ var previousNode = getAndAssertNodeAtPathExists(actions.getRoot(), path);
5158
+ actions.replaceWith(path, {
5159
+ direction: 'column',
5160
+ first: previousNode,
5161
+ second: newNode
5162
+ });
5163
+ },
5164
+ sx: buttonStyle$1,
5165
+ tooltipTitle: t('workspace-control-split-horizontal-with-data'),
5166
+ children: jsx(SplitHorizontalWithContent, {})
5167
+ })), wrapInMenuItem(inMenuItem, jsx(CustomIconButton, {
5168
+ "data-testid": "split-vertical-btn-copy-content",
5169
+ disabled: isVerticalSplitDisabled,
5170
+ onClick: function onClick(event) {
5171
+ // Always copy over content
5172
+ var newNode = createNode(true);
5173
+ var previousNode = getAndAssertNodeAtPathExists(actions.getRoot(), path);
5174
+ actions.replaceWith(path, {
5175
+ direction: 'row',
5176
+ first: previousNode,
5177
+ second: newNode
5178
+ });
5179
+ },
5180
+ sx: buttonStyle$1,
5181
+ tooltipTitle: t('workspace-control-split-vertical-with-data'),
5182
+ children: jsx(SplitVerticalWithContent, {})
5183
+ }), isVerticalSplitDisabled)]
5009
5184
  });
5010
5185
  };
5011
5186
 
@@ -5014,12 +5189,21 @@ var buttonStyle = {
5014
5189
  marginRight: 0.5
5015
5190
  };
5016
5191
  var WorkspaceControls = function WorkspaceControls(_ref) {
5192
+ var _sx, _sx2;
5017
5193
  var panelId = _ref.panelId;
5018
5194
  _ref.createNode;
5019
5195
  var path = _ref.path,
5020
5196
  _ref$shouldPreventClo = _ref.shouldPreventCloseView,
5021
5197
  shouldPreventCloseView = _ref$shouldPreventClo === void 0 ? false : _ref$shouldPreventClo,
5022
5198
  removeLinkedMap = _ref.removeLinkedMap;
5199
+ var theme = useTheme();
5200
+ var _React$useState = React.useState(null),
5201
+ anchorEl = _React$useState[0],
5202
+ setAnchorEl = _React$useState[1];
5203
+ var isOpen = Boolean(anchorEl);
5204
+ var handleClick = function handleClick(event) {
5205
+ setAnchorEl(anchorEl ? null : event.currentTarget);
5206
+ };
5023
5207
  var confirmDialog = useConfirmationDialog();
5024
5208
  var _React$useContext = React.useContext(MosaicContext),
5025
5209
  actions = _React$useContext.mosaicActions;
@@ -5028,15 +5212,15 @@ var WorkspaceControls = function WorkspaceControls(_ref) {
5028
5212
  var mosaicNode = useSelector(function (store) {
5029
5213
  return getMosaicNode(store);
5030
5214
  });
5031
- var _React$useState = React.useState(),
5032
- stateAfterExpand = _React$useState[0],
5033
- setStateAfterExpand = _React$useState[1];
5034
- var _React$useState2 = React.useState(mosaicNode),
5035
- stateBeforeExpand = _React$useState2[0],
5036
- setStateBeforeExpand = _React$useState2[1];
5037
- var _React$useState3 = React.useState(false),
5038
- enableUnexpand = _React$useState3[0],
5039
- setEnableUnexpand = _React$useState3[1];
5215
+ var _React$useState2 = React.useState(),
5216
+ stateAfterExpand = _React$useState2[0],
5217
+ setStateAfterExpand = _React$useState2[1];
5218
+ var _React$useState3 = React.useState(mosaicNode),
5219
+ stateBeforeExpand = _React$useState3[0],
5220
+ setStateBeforeExpand = _React$useState3[1];
5221
+ var _React$useState4 = React.useState(false),
5222
+ enableUnexpand = _React$useState4[0],
5223
+ setEnableUnexpand = _React$useState4[1];
5040
5224
  React.useEffect(function () {
5041
5225
  if (enableUnexpand) {
5042
5226
  if (stateAfterExpand === undefined) {
@@ -5082,31 +5266,100 @@ var WorkspaceControls = function WorkspaceControls(_ref) {
5082
5266
  return _ref2.apply(this, arguments);
5083
5267
  };
5084
5268
  }();
5269
+ var expandButton = !enableUnexpand || isString(mosaicNode) ? jsx(CustomIconButton, {
5270
+ "data-testid": "expand-btn",
5271
+ onClick: function onClick() {
5272
+ setStateBeforeExpand(mosaicNode);
5273
+ setEnableUnexpand(true);
5274
+ actions.expand(path, 70);
5275
+ },
5276
+ sx: buttonStyle,
5277
+ tooltipTitle: t('workspace-control-expand'),
5278
+ children: jsx(Expand, {})
5279
+ }) : jsx(CustomIconButton, {
5280
+ "data-testid": "unexpand-btn",
5281
+ onClick: function onClick() {
5282
+ var stateBeforeExpandCopy = isString(stateBeforeExpand) ? stateBeforeExpand : Object.assign({}, stateBeforeExpand);
5283
+ actions.replaceWith([], stateBeforeExpandCopy);
5284
+ },
5285
+ sx: buttonStyle,
5286
+ tooltipTitle: t('workspace-control-unexpand'),
5287
+ children: jsx(UnExpand, {})
5288
+ });
5085
5289
  return jsxs(Fragment, {
5086
- children: [jsx(LinkMenuConnect, {
5087
- panelId: panelId
5088
- }), jsx(SplitButtonsConnect, {
5089
- panelId: panelId,
5090
- path: path
5091
- }), !enableUnexpand || isString(mosaicNode) ? jsx(CustomIconButton, {
5092
- "data-testid": "expand-btn",
5093
- onClick: function onClick() {
5094
- setStateBeforeExpand(mosaicNode);
5095
- setEnableUnexpand(true);
5096
- actions.expand(path, 70);
5097
- },
5098
- sx: buttonStyle,
5099
- tooltipTitle: t('workspace-control-expand'),
5100
- children: jsx(Expand, {})
5101
- }) : jsx(CustomIconButton, {
5102
- "data-testid": "unexpand-btn",
5103
- onClick: function onClick() {
5104
- var stateBeforeExpandCopy = isString(stateBeforeExpand) ? stateBeforeExpand : Object.assign({}, stateBeforeExpand);
5105
- actions.replaceWith([], stateBeforeExpandCopy);
5106
- },
5107
- sx: buttonStyle,
5108
- tooltipTitle: t('workspace-control-unexpand'),
5109
- children: jsx(UnExpand, {})
5290
+ children: [jsxs(Box, {
5291
+ "data-testid": "workspace-view-controls-options-dropdown",
5292
+ sx: (_sx = {}, _sx["@container workspace-view-container (min-width: 495px)"] = {
5293
+ display: 'none'
5294
+ }, _sx.paddingLeft = '8px', _sx),
5295
+ children: [jsx(LinkMenuConnect, {
5296
+ panelId: panelId
5297
+ }), jsxs(CustomIconButton, {
5298
+ "aria-label": "workspace view controls",
5299
+ "data-testid": "workspace-view-controls",
5300
+ isSelected: isOpen,
5301
+ onClick: handleClick,
5302
+ sx: {
5303
+ '&&': {
5304
+ backgroundColor: !isOpen ? 'transparent' : 'geowebColors.workspace.tabButtonHover',
5305
+ '&:hover': {
5306
+ backgroundColor: 'geowebColors.workspace.tabButtonHover'
5307
+ },
5308
+ '.MuiSvgIcon-root > path': {
5309
+ fill: isOpen ? theme.palette.geowebColors.iconButtons.tool.active.color : undefined
5310
+ }
5311
+ }
5312
+ },
5313
+ tooltipTitle: t('workspace-control-show-options'),
5314
+ variant: "tool",
5315
+ children: [jsx(ChevronDown, {}), jsxs(Menu, {
5316
+ anchorEl: anchorEl,
5317
+ anchorOrigin: {
5318
+ vertical: 21,
5319
+ horizontal: 6
5320
+ },
5321
+ onClose: function onClose() {
5322
+ return setAnchorEl(null);
5323
+ },
5324
+ open: !!isOpen,
5325
+ slotProps: {
5326
+ backdrop: {
5327
+ style: {
5328
+ opacity: 0,
5329
+ transition: 'none'
5330
+ }
5331
+ }
5332
+ },
5333
+ sx: {
5334
+ '& .MuiMenu-list': {
5335
+ padding: 0
5336
+ },
5337
+ '& .MuiMenuItem-root': {
5338
+ padding: '2px',
5339
+ minHeight: '32px !important'
5340
+ }
5341
+ },
5342
+ children: [jsx(SplitButtonsConnect, {
5343
+ inMenuItem: true,
5344
+ isVerticalSplitDisabled: true,
5345
+ panelId: panelId,
5346
+ path: path
5347
+ }), jsx(MenuItem, {
5348
+ children: expandButton
5349
+ })]
5350
+ })]
5351
+ })]
5352
+ }), jsxs(Box, {
5353
+ "data-testid": "workspace-view-controls-options-buttons",
5354
+ sx: (_sx2 = {}, _sx2["@container workspace-view-container (max-width: 494px)"] = {
5355
+ display: 'none'
5356
+ }, _sx2.paddingLeft = '4px', _sx2),
5357
+ children: [jsx(LinkMenuConnect, {
5358
+ panelId: panelId
5359
+ }), jsx(SplitButtonsConnect, {
5360
+ panelId: panelId,
5361
+ path: path
5362
+ }), expandButton]
5110
5363
  }), jsx(CustomIconButton, {
5111
5364
  "data-testid": "close-btn",
5112
5365
  id: "close-window-button",
@@ -5324,6 +5577,201 @@ var useViewPresets = function useViewPresets() {
5324
5577
  return useQuery(viewpresetQueryOptions.getViewPresets(auth));
5325
5578
  };
5326
5579
 
5580
+ var _excluded$5 = ["originalViewPresetId"];
5581
+ var writeToClipboard = /*#__PURE__*/function () {
5582
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(text) {
5583
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
5584
+ while (1) switch (_context.prev = _context.next) {
5585
+ case 0:
5586
+ window.focus();
5587
+ _context.next = 3;
5588
+ return navigator.clipboard.writeText(text);
5589
+ case 3:
5590
+ case "end":
5591
+ return _context.stop();
5592
+ }
5593
+ }, _callee);
5594
+ }));
5595
+ return function writeToClipboard(_x) {
5596
+ return _ref.apply(this, arguments);
5597
+ };
5598
+ }();
5599
+ /**
5600
+ * For each view that only has a viewPresetId reference (old-style), fetch
5601
+ * the full view preset from BE and replaces the reference with inline
5602
+ * componentType + initialProps.
5603
+ */
5604
+ var expandWorkspaceViewPresets = /*#__PURE__*/function () {
5605
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(preset, auth) {
5606
+ var expandedViews;
5607
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
5608
+ while (1) switch (_context3.prev = _context3.next) {
5609
+ case 0:
5610
+ _context3.next = 2;
5611
+ return Promise.all(preset.views.map(/*#__PURE__*/function () {
5612
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(view) {
5613
+ var _view$title;
5614
+ var fullPreset;
5615
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
5616
+ while (1) switch (_context2.prev = _context2.next) {
5617
+ case 0:
5618
+ if (!(!view.viewPresetId || view.componentType)) {
5619
+ _context2.next = 2;
5620
+ break;
5621
+ }
5622
+ return _context2.abrupt("return", view);
5623
+ case 2:
5624
+ _context2.next = 4;
5625
+ return getQueryClient().fetchQuery(viewpresetQueryOptions.getViewPreset(view.viewPresetId, auth));
5626
+ case 4:
5627
+ fullPreset = _context2.sent;
5628
+ return _context2.abrupt("return", {
5629
+ mosaicNodeId: view.mosaicNodeId,
5630
+ title: (_view$title = view.title) != null ? _view$title : fullPreset.title,
5631
+ componentType: fullPreset.componentType,
5632
+ initialProps: fullPreset.initialProps
5633
+ });
5634
+ case 6:
5635
+ case "end":
5636
+ return _context2.stop();
5637
+ }
5638
+ }, _callee2);
5639
+ }));
5640
+ return function (_x4) {
5641
+ return _ref3.apply(this, arguments);
5642
+ };
5643
+ }()));
5644
+ case 2:
5645
+ expandedViews = _context3.sent;
5646
+ return _context3.abrupt("return", Object.assign({}, preset, {
5647
+ views: expandedViews
5648
+ }));
5649
+ case 4:
5650
+ case "end":
5651
+ return _context3.stop();
5652
+ }
5653
+ }, _callee3);
5654
+ }));
5655
+ return function expandWorkspaceViewPresets(_x2, _x3) {
5656
+ return _ref2.apply(this, arguments);
5657
+ };
5658
+ }();
5659
+ var sanitizeWorkspaceForClipboard = function sanitizeWorkspaceForClipboard(preset) {
5660
+ var views = Array.isArray(preset.views) ? preset.views.map(function (_ref4) {
5661
+ _ref4.originalViewPresetId;
5662
+ var view = _objectWithoutPropertiesLoose(_ref4, _excluded$5);
5663
+ return view;
5664
+ }) : preset.views;
5665
+ return Object.assign({}, preset, {
5666
+ id: undefined,
5667
+ views: views,
5668
+ is_shared: false,
5669
+ scope: 'user'
5670
+ });
5671
+ };
5672
+ var sanitizeViewPresetForClipboard = function sanitizeViewPresetForClipboard(preset) {
5673
+ var _preset$keywords;
5674
+ return Object.assign({}, preset, {
5675
+ keywords: (_preset$keywords = preset.keywords) != null ? _preset$keywords : '',
5676
+ id: undefined,
5677
+ is_shared: false,
5678
+ scope: 'user'
5679
+ });
5680
+ };
5681
+ var validateWorkspacePresetJson = function validateWorkspacePresetJson(jsonString) {
5682
+ var parsed;
5683
+ try {
5684
+ parsed = JSON.parse(jsonString);
5685
+ } catch (e) {
5686
+ return {
5687
+ error: 'workspace-paste-validation-invalid-json',
5688
+ errorParam: e instanceof Error ? e.message : String(e)
5689
+ };
5690
+ }
5691
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
5692
+ return {
5693
+ error: 'workspace-paste-validation-not-object'
5694
+ };
5695
+ }
5696
+ var obj = parsed;
5697
+ if (typeof obj['componentType'] === 'string') {
5698
+ return {
5699
+ error: 'workspace-paste-validation-wrong-preset-type'
5700
+ };
5701
+ }
5702
+ if (typeof obj['title'] !== 'string' || !obj['title'].trim()) {
5703
+ return {
5704
+ error: 'workspace-paste-validation-missing-field',
5705
+ errorParam: 'title'
5706
+ };
5707
+ }
5708
+ if (!Array.isArray(obj['views'])) {
5709
+ return {
5710
+ error: 'workspace-paste-validation-missing-field',
5711
+ errorParam: 'views'
5712
+ };
5713
+ }
5714
+ if (obj['mosaicNode'] === undefined || obj['mosaicNode'] === null) {
5715
+ return {
5716
+ error: 'workspace-paste-validation-missing-field',
5717
+ errorParam: 'mosaicNode'
5718
+ };
5719
+ }
5720
+ var hasUnexpandedViews = obj['views'].some(function (view) {
5721
+ return 'viewPresetId' in view && !('componentType' in view);
5722
+ });
5723
+ if (hasUnexpandedViews) {
5724
+ return {
5725
+ error: 'workspace-paste-validation-unexpanded-views'
5726
+ };
5727
+ }
5728
+ return null;
5729
+ };
5730
+ /**
5731
+ * Validates that the parsed value is a valid ViewPreset structure.
5732
+ */
5733
+ var validateViewPresetJson = function validateViewPresetJson(jsonString) {
5734
+ var parsed;
5735
+ try {
5736
+ parsed = JSON.parse(jsonString);
5737
+ } catch (e) {
5738
+ return {
5739
+ error: 'workspace-paste-validation-invalid-json',
5740
+ errorParam: e instanceof Error ? e.message : String(e)
5741
+ };
5742
+ }
5743
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
5744
+ return {
5745
+ error: 'workspace-paste-validation-not-object'
5746
+ };
5747
+ }
5748
+ var obj = parsed;
5749
+ if (Array.isArray(obj['views'])) {
5750
+ return {
5751
+ error: 'viewpreset-paste-validation-wrong-preset-type'
5752
+ };
5753
+ }
5754
+ if (typeof obj['title'] !== 'string' || !obj['title'].trim()) {
5755
+ return {
5756
+ error: 'workspace-paste-validation-missing-field',
5757
+ errorParam: 'title'
5758
+ };
5759
+ }
5760
+ if (typeof obj['componentType'] !== 'string' || !obj['componentType']) {
5761
+ return {
5762
+ error: 'workspace-paste-validation-missing-field',
5763
+ errorParam: 'componentType'
5764
+ };
5765
+ }
5766
+ if (typeof obj['keywords'] !== 'string') {
5767
+ return {
5768
+ error: 'workspace-paste-validation-missing-field',
5769
+ errorParam: 'keywords'
5770
+ };
5771
+ }
5772
+ return null;
5773
+ };
5774
+
5327
5775
  var VIEW_TYPE_KEY = 'viewType';
5328
5776
  var normalizeLabels = function normalizeLabels(labels, available) {
5329
5777
  var result = {};
@@ -5839,7 +6287,8 @@ var useCreateWorkspacePreset = function useCreateWorkspacePreset() {
5839
6287
  workspaceId: newId,
5840
6288
  action: variables.action || WorkspacePresetAction.SAVE_AS,
5841
6289
  title: variables.data.title,
5842
- scope: scope
6290
+ scope: scope,
6291
+ username: variables.data.username || ''
5843
6292
  }));
5844
6293
  },
5845
6294
  onError: function onError(error) {
@@ -6353,6 +6802,11 @@ var WorkspaceSelectListRow = function WorkspaceSelectListRow(_ref) {
6353
6802
  action: function action() {
6354
6803
  return onClick(WorkspacePresetAction.OPEN_TAB);
6355
6804
  }
6805
+ }, {
6806
+ text: testIdPrefix === 'viewpreset' ? t('workspace-copy-viewpreset-to-clipboard') : t('workspace-copy-to-clipboard'),
6807
+ action: function action() {
6808
+ return onClick(WorkspacePresetAction.COPY_TO_CLIPBOARD);
6809
+ }
6356
6810
  }];
6357
6811
  // Show "Edit" if it's your own user-scoped preset OR you're an admin
6358
6812
  if (workspacePreset.scope === SystemScope.user && (auth == null ? void 0 : auth.username) === workspacePreset.username || isAdmin) {
@@ -6760,123 +7214,156 @@ var ViewPresetMenuListConnect = function ViewPresetMenuListConnect(_ref) {
6760
7214
  return undefined;
6761
7215
  }
6762
7216
  };
6763
- var onClickViewPresetOption = function onClickViewPresetOption(presetId, workspaceAction, preset) {
6764
- switch (workspaceAction) {
6765
- case WorkspacePresetAction.DUPLICATE:
6766
- {
6767
- getQueryClient().fetchQuery(viewpresetQueryOptions.getViewPreset(presetId, auth)).then(function (presetFromBE) {
6768
- var _getViewById, _ref3, _preset$initialProps;
6769
- var preset = presetFromBE;
6770
- var fallbackInitialProps = (_getViewById = getViewById(store.getState(), panelId)) == null ? void 0 : _getViewById.initialProps;
6771
- var initialPropsForForm = (_ref3 = (_preset$initialProps = preset.initialProps) != null ? _preset$initialProps : fallbackInitialProps) != null ? _ref3 : constructInitialProps();
6772
- openViewPresetsDialog({
6773
- title: t('workspace-mappreset-save-as'),
6774
- action: PresetAction.SAVE_AS,
6775
- viewPresetId: presetId,
6776
- panelId: panelId,
6777
- shouldSetActiveViewPreset: false,
6778
- formValues: {
6779
- title: preset.title,
6780
- description: preset.description,
6781
- initialProps: initialPropsForForm,
6782
- "abstract": preset["abstract"],
6783
- labels: preset.labels,
6784
- componentType: preset.componentType
6785
- }
7217
+ var onClickViewPresetOption = /*#__PURE__*/function () {
7218
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(presetId, workspaceAction, preset) {
7219
+ var presetTitle, fullPreset, sanitized;
7220
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
7221
+ while (1) switch (_context2.prev = _context2.next) {
7222
+ case 0:
7223
+ _context2.t0 = workspaceAction;
7224
+ _context2.next = _context2.t0 === WorkspacePresetAction.DUPLICATE ? 3 : _context2.t0 === WorkspacePresetAction.EDIT ? 5 : _context2.t0 === WorkspacePresetAction.SHARE ? 9 : _context2.t0 === WorkspacePresetAction.DELETE_SYSTEM_PRESET ? 11 : _context2.t0 === WorkspacePresetAction.DELETE ? 11 : _context2.t0 === WorkspacePresetAction.COPY_TO_CLIPBOARD ? 13 : 27;
7225
+ break;
7226
+ case 3:
7227
+ getQueryClient().fetchQuery(viewpresetQueryOptions.getViewPreset(presetId, auth)).then(function (presetFromBE) {
7228
+ var _getViewById, _ref4, _preset$initialProps;
7229
+ var preset = presetFromBE;
7230
+ var fallbackInitialProps = (_getViewById = getViewById(store.getState(), panelId)) == null ? void 0 : _getViewById.initialProps;
7231
+ var initialPropsForForm = (_ref4 = (_preset$initialProps = preset.initialProps) != null ? _preset$initialProps : fallbackInitialProps) != null ? _ref4 : constructInitialProps();
7232
+ openViewPresetsDialog({
7233
+ title: t('workspace-mappreset-save-as'),
7234
+ action: PresetAction.SAVE_AS,
7235
+ viewPresetId: presetId,
7236
+ panelId: panelId,
7237
+ shouldSetActiveViewPreset: false,
7238
+ formValues: {
7239
+ title: preset.title,
7240
+ description: preset.description,
7241
+ initialProps: initialPropsForForm,
7242
+ "abstract": preset["abstract"],
7243
+ labels: preset.labels,
7244
+ componentType: preset.componentType
7245
+ }
7246
+ });
7247
+ })["catch"](function () {
7248
+ openViewPresetsDialog({
7249
+ title: t('workspace-mappreset-save-as'),
7250
+ action: PresetAction.SAVE_AS,
7251
+ viewPresetId: presetId,
7252
+ panelId: panelId,
7253
+ shouldSetActiveViewPreset: false,
7254
+ formValues: {
7255
+ title: preset.title,
7256
+ description: preset.description,
7257
+ initialProps: constructInitialProps(),
7258
+ "abstract": preset["abstract"],
7259
+ labels: preset.labels,
7260
+ componentType: viewComponentType
7261
+ }
7262
+ });
6786
7263
  });
6787
- })["catch"](function () {
7264
+ return _context2.abrupt("break", 28);
7265
+ case 5:
7266
+ presetTitle = (preset == null ? void 0 : preset.title) || '';
6788
7267
  openViewPresetsDialog({
6789
- title: t('workspace-mappreset-save-as'),
6790
- action: PresetAction.SAVE_AS,
6791
- viewPresetId: presetId,
7268
+ title: t('workspace-mappreset-dialog-title-edit'),
7269
+ action: PresetAction.EDIT,
6792
7270
  panelId: panelId,
6793
- shouldSetActiveViewPreset: false,
7271
+ viewPresetId: presetId,
6794
7272
  formValues: {
6795
- title: preset.title,
7273
+ title: presetTitle,
6796
7274
  description: preset.description,
6797
- initialProps: constructInitialProps(),
6798
7275
  "abstract": preset["abstract"],
6799
7276
  labels: preset.labels,
6800
- componentType: viewComponentType
7277
+ updated: new Date().toISOString()
6801
7278
  }
6802
7279
  });
6803
- });
6804
- break;
6805
- }
6806
- case WorkspacePresetAction.EDIT:
6807
- {
6808
- var presetTitle = (preset == null ? void 0 : preset.title) || '';
6809
- openViewPresetsDialog({
6810
- title: t('workspace-mappreset-dialog-title-edit'),
6811
- action: PresetAction.EDIT,
6812
- panelId: panelId,
6813
- viewPresetId: presetId,
6814
- formValues: {
6815
- title: presetTitle,
6816
- description: preset.description,
6817
- "abstract": preset["abstract"],
6818
- labels: preset.labels,
6819
- updated: new Date().toISOString()
6820
- }
6821
- });
6822
- void getQueryClient().fetchQuery(viewpresetQueryOptions.getViewPreset(presetId, auth)).then(function (fullPreset) {
7280
+ void getQueryClient().fetchQuery(viewpresetQueryOptions.getViewPreset(presetId, auth)).then(function (fullPreset) {
7281
+ openViewPresetsDialog({
7282
+ title: t('workspace-mappreset-dialog-title-edit'),
7283
+ action: PresetAction.EDIT,
7284
+ panelId: panelId,
7285
+ viewPresetId: presetId,
7286
+ formValues: {
7287
+ title: fullPreset.title,
7288
+ description: fullPreset.description,
7289
+ "abstract": fullPreset["abstract"],
7290
+ labels: fullPreset.labels,
7291
+ componentType: fullPreset.componentType,
7292
+ initialProps: fullPreset.initialProps
7293
+ }
7294
+ });
7295
+ })["catch"](function () {
7296
+ // Leave dialog with initial data if fetch fails; errors handled elsewhere
7297
+ });
7298
+ return _context2.abrupt("break", 28);
7299
+ case 9:
7300
+ void getQueryClient().fetchQuery(viewpresetQueryOptions.getViewPreset(presetId, auth)).then(function (preset) {
7301
+ return void updateViewPreset(presetId, Object.assign({}, preset, {
7302
+ is_shared: !preset.is_shared
7303
+ }), auth).then(function () {
7304
+ dispatch(viewPresetActions.onSuccessViewPresetAction({
7305
+ panelId: panelId,
7306
+ viewPresetId: presetId,
7307
+ activeViewPresetId: activeViewPresetId,
7308
+ action: PresetAction.SHARE,
7309
+ title: preset.title,
7310
+ description: preset.description,
7311
+ scope: scope,
7312
+ "abstract": preset["abstract"],
7313
+ is_shared: preset.is_shared
7314
+ }));
7315
+ fetchViewPresets();
7316
+ });
7317
+ });
7318
+ return _context2.abrupt("break", 28);
7319
+ case 11:
6823
7320
  openViewPresetsDialog({
6824
- title: t('workspace-mappreset-dialog-title-edit'),
6825
- action: PresetAction.EDIT,
6826
- panelId: panelId,
7321
+ title: t('workspace-mappreset-dialog-title-delete'),
7322
+ action: PresetAction.DELETE,
6827
7323
  viewPresetId: presetId,
7324
+ panelId: panelId,
6828
7325
  formValues: {
6829
- title: fullPreset.title,
6830
- description: fullPreset.description,
6831
- "abstract": fullPreset["abstract"],
6832
- labels: fullPreset.labels,
6833
- componentType: fullPreset.componentType,
6834
- initialProps: fullPreset.initialProps
7326
+ title: preset.title
6835
7327
  }
6836
7328
  });
6837
- })["catch"](function () {
6838
- // Leave dialog with initial data if fetch fails; errors handled elsewhere
6839
- });
6840
- break;
6841
- }
6842
- case WorkspacePresetAction.SHARE:
6843
- {
6844
- void getQueryClient().fetchQuery(viewpresetQueryOptions.getViewPreset(presetId, auth)).then(function (preset) {
6845
- return void updateViewPreset(presetId, Object.assign({}, preset, {
6846
- is_shared: !preset.is_shared
6847
- }), auth).then(function () {
6848
- dispatch(viewPresetActions.onSuccessViewPresetAction({
6849
- panelId: panelId,
6850
- viewPresetId: presetId,
6851
- activeViewPresetId: activeViewPresetId,
6852
- action: PresetAction.SHARE,
6853
- title: preset.title,
6854
- description: preset.description,
6855
- scope: scope,
6856
- "abstract": preset["abstract"],
6857
- is_shared: preset.is_shared
6858
- }));
6859
- fetchViewPresets();
6860
- });
6861
- });
6862
- break;
6863
- }
6864
- case WorkspacePresetAction.DELETE_SYSTEM_PRESET:
6865
- case WorkspacePresetAction.DELETE:
6866
- {
6867
- openViewPresetsDialog({
6868
- title: t('workspace-mappreset-dialog-title-delete'),
6869
- action: PresetAction.DELETE,
6870
- viewPresetId: presetId,
6871
- panelId: panelId,
6872
- formValues: {
6873
- title: preset.title
6874
- }
6875
- });
6876
- break;
7329
+ return _context2.abrupt("break", 28);
7330
+ case 13:
7331
+ _context2.prev = 13;
7332
+ _context2.next = 16;
7333
+ return getQueryClient().fetchQuery(viewpresetQueryOptions.getViewPreset(presetId, auth));
7334
+ case 16:
7335
+ fullPreset = _context2.sent;
7336
+ sanitized = sanitizeViewPresetForClipboard(fullPreset);
7337
+ _context2.next = 20;
7338
+ return writeToClipboard(JSON.stringify(sanitized, null, 2));
7339
+ case 20:
7340
+ dispatch(snackbarActions.openSnackbar({
7341
+ type: snackbarTypes.SnackbarMessageType.VERBATIM_MESSAGE,
7342
+ message: t('workspace-copy-viewpreset-success')
7343
+ }));
7344
+ _context2.next = 26;
7345
+ break;
7346
+ case 23:
7347
+ _context2.prev = 23;
7348
+ _context2.t1 = _context2["catch"](13);
7349
+ dispatch(snackbarActions.openSnackbar({
7350
+ type: snackbarTypes.SnackbarMessageType.VERBATIM_MESSAGE,
7351
+ message: t('workspace-error-generic')
7352
+ }));
7353
+ case 26:
7354
+ return _context2.abrupt("break", 28);
7355
+ case 27:
7356
+ return _context2.abrupt("break", 28);
7357
+ case 28:
7358
+ case "end":
7359
+ return _context2.stop();
6877
7360
  }
6878
- }
6879
- };
7361
+ }, _callee2, null, [[13, 23]]);
7362
+ }));
7363
+ return function onClickViewPresetOption(_x, _x2, _x3) {
7364
+ return _ref3.apply(this, arguments);
7365
+ };
7366
+ }();
6880
7367
  var onSearchFilter = React.useCallback(function (searchQuery) {
6881
7368
  dispatch(viewPresetActions.searchFilter({
6882
7369
  searchQuery: searchQuery,
@@ -7028,16 +7515,16 @@ var ViewPresetMenuListConnect = function ViewPresetMenuListConnect(_ref) {
7028
7515
  children: jsx(LastUpdateTime, {
7029
7516
  hideLabel: true,
7030
7517
  onPressRefresh: function () {
7031
- var _onPressRefresh = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
7032
- return _regeneratorRuntime().wrap(function _callee2$(_context2) {
7033
- while (1) switch (_context2.prev = _context2.next) {
7518
+ var _onPressRefresh = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
7519
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
7520
+ while (1) switch (_context3.prev = _context3.next) {
7034
7521
  case 0:
7035
- return _context2.abrupt("return", refreshViewPresets());
7522
+ return _context3.abrupt("return", refreshViewPresets());
7036
7523
  case 1:
7037
7524
  case "end":
7038
- return _context2.stop();
7525
+ return _context3.stop();
7039
7526
  }
7040
- }, _callee2);
7527
+ }, _callee3);
7041
7528
  }));
7042
7529
  function onPressRefresh() {
7043
7530
  return _onPressRefresh.apply(this, arguments);
@@ -7172,6 +7659,114 @@ var ViewPresetMenu = function ViewPresetMenu(_ref) {
7172
7659
  });
7173
7660
  };
7174
7661
 
7662
+ var PastePresetDialog = function PastePresetDialog(_ref) {
7663
+ var isOpen = _ref.isOpen,
7664
+ mode = _ref.mode,
7665
+ onClose = _ref.onClose,
7666
+ onConfirm = _ref.onConfirm;
7667
+ var _useWorkspaceTranslat = useWorkspaceTranslation(),
7668
+ t = _useWorkspaceTranslat.t;
7669
+ var _React$useState = React.useState(''),
7670
+ pastedText = _React$useState[0],
7671
+ setPastedText = _React$useState[1];
7672
+ var _React$useState2 = React.useState(),
7673
+ validationError = _React$useState2[0],
7674
+ setValidationError = _React$useState2[1];
7675
+ // Reset state when dialog closes
7676
+ React.useEffect(function () {
7677
+ if (!isOpen) {
7678
+ setPastedText('');
7679
+ setValidationError(undefined);
7680
+ }
7681
+ }, [isOpen]);
7682
+ var validate = function validate(value) {
7683
+ if (!value.trim()) {
7684
+ return undefined;
7685
+ }
7686
+ var result = mode === 'workspace' ? validateWorkspacePresetJson(value) : validateViewPresetJson(value);
7687
+ if (!result) {
7688
+ return undefined;
7689
+ }
7690
+ return result.errorParam ? t(result.error, {
7691
+ ERROR: result.errorParam
7692
+ }) : t(result.error);
7693
+ };
7694
+ var handleChange = function handleChange(value) {
7695
+ setPastedText(value);
7696
+ setValidationError(validate(value));
7697
+ };
7698
+ var handleSubmit = function handleSubmit() {
7699
+ var error = validate(pastedText);
7700
+ if (error) {
7701
+ setValidationError(error);
7702
+ return;
7703
+ }
7704
+ onConfirm(pastedText);
7705
+ onClose();
7706
+ };
7707
+ var isWorkspace = mode === 'workspace';
7708
+ var dialogTitle = isWorkspace ? t('workspace-paste-dialog-title') : t('workspace-paste-viewpreset-dialog-title');
7709
+ var confirmLabel = isWorkspace ? t('workspace-paste-load-button') : t('workspace-paste-load-viewpreset-button');
7710
+ var fieldLabel = isWorkspace ? t('workspace-paste-field-label') : t('workspace-paste-viewpreset-field-label');
7711
+ var isConfirmDisabled = !pastedText.trim() || Boolean(validationError);
7712
+ return jsx(CustomDialog, {
7713
+ actions: jsxs(Box, {
7714
+ sx: {
7715
+ display: 'flex',
7716
+ gap: 1,
7717
+ justifyContent: 'flex-end'
7718
+ },
7719
+ children: [jsx(Button, {
7720
+ "data-testid": "paste-preset-cancel",
7721
+ onClick: onClose,
7722
+ variant: "tertiary",
7723
+ children: t('workspace-cancel')
7724
+ }), jsx(Button, {
7725
+ "data-testid": "paste-preset-confirm",
7726
+ disabled: isConfirmDisabled,
7727
+ onClick: handleSubmit,
7728
+ variant: "primary",
7729
+ children: confirmLabel
7730
+ })]
7731
+ }),
7732
+ "data-testid": "paste-preset-dialog",
7733
+ onClose: onClose,
7734
+ open: isOpen,
7735
+ sx: {
7736
+ width: 800,
7737
+ height: 'auto',
7738
+ mx: 'auto'
7739
+ },
7740
+ title: dialogTitle,
7741
+ children: jsx(TextField, {
7742
+ "data-testid": "paste-preset-textarea",
7743
+ error: Boolean(validationError),
7744
+ fullWidth: true,
7745
+ helperText: validationError,
7746
+ label: fieldLabel,
7747
+ multiline: true,
7748
+ onChange: function onChange(e) {
7749
+ return handleChange(e.target.value);
7750
+ },
7751
+ onKeyDown: function onKeyDown(e) {
7752
+ var allowed = e.ctrlKey || e.metaKey || e.key === 'Tab';
7753
+ if (!allowed) {
7754
+ e.preventDefault();
7755
+ }
7756
+ },
7757
+ rows: 8,
7758
+ sx: {
7759
+ '& .MuiInputBase-input': {
7760
+ fontFamily: 'monospace',
7761
+ fontSize: 12
7762
+ }
7763
+ },
7764
+ value: pastedText,
7765
+ variant: "filled"
7766
+ })
7767
+ });
7768
+ };
7769
+
7175
7770
  var WorkspaceSelectListConnect = function WorkspaceSelectListConnect(_ref) {
7176
7771
  var _useSelector, _GENERIC$AUTH$error$c;
7177
7772
  var _ref$isLabelFilterOpe = _ref.isLabelFilterOpen,
@@ -7318,7 +7913,7 @@ var WorkspaceSelectListConnect = function WorkspaceSelectListConnect(_ref) {
7318
7913
  }, [currentView]);
7319
7914
  var onClickWorkspacePresetOption = /*#__PURE__*/function () {
7320
7915
  var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(presetId, workspaceAction) {
7321
- var affectedPreset, presetTitle, _currentView$syncGrou, currentViews, adminMetadata, buildFormValues, url;
7916
+ var affectedPreset, presetTitle, _currentView$syncGrou, currentViews, adminMetadata, buildFormValues, url, preset, expanded, sanitized;
7322
7917
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
7323
7918
  while (1) switch (_context2.prev = _context2.next) {
7324
7919
  case 0:
@@ -7328,7 +7923,7 @@ var WorkspaceSelectListConnect = function WorkspaceSelectListConnect(_ref) {
7328
7923
  });
7329
7924
  presetTitle = affectedPreset == null ? void 0 : affectedPreset.title;
7330
7925
  _context2.t0 = workspaceAction;
7331
- _context2.next = _context2.t0 === WorkspacePresetAction.DUPLICATE ? 5 : _context2.t0 === WorkspacePresetAction.EDIT ? 8 : _context2.t0 === WorkspacePresetAction.DELETE ? 16 : _context2.t0 === WorkspacePresetAction.DELETE_SYSTEM_PRESET ? 18 : _context2.t0 === WorkspacePresetAction.SHARE ? 20 : _context2.t0 === WorkspacePresetAction.OPEN_TAB ? 22 : 25;
7926
+ _context2.next = _context2.t0 === WorkspacePresetAction.DUPLICATE ? 5 : _context2.t0 === WorkspacePresetAction.EDIT ? 8 : _context2.t0 === WorkspacePresetAction.DELETE ? 16 : _context2.t0 === WorkspacePresetAction.DELETE_SYSTEM_PRESET ? 18 : _context2.t0 === WorkspacePresetAction.SHARE ? 20 : _context2.t0 === WorkspacePresetAction.OPEN_TAB ? 22 : _context2.t0 === WorkspacePresetAction.COPY_TO_CLIPBOARD ? 25 : 42;
7332
7927
  break;
7333
7928
  case 5:
7334
7929
  currentViews = currentViewsToBE();
@@ -7346,7 +7941,7 @@ var WorkspaceSelectListConnect = function WorkspaceSelectListConnect(_ref) {
7346
7941
  syncGroups: (_currentView$syncGrou = currentView.syncGroups) != null ? _currentView$syncGrou : []
7347
7942
  }
7348
7943
  });
7349
- return _context2.abrupt("break", 26);
7944
+ return _context2.abrupt("break", 43);
7350
7945
  case 8:
7351
7946
  adminMetadata = isAdmin && auth != null && auth.username ? {
7352
7947
  updated: new Date().toISOString(),
@@ -7377,7 +7972,7 @@ var WorkspaceSelectListConnect = function WorkspaceSelectListConnect(_ref) {
7377
7972
  presetId: presetId,
7378
7973
  formValues: buildFormValues(currentView, currentViewsToBE())
7379
7974
  });
7380
- return _context2.abrupt("break", 26);
7975
+ return _context2.abrupt("break", 43);
7381
7976
  case 13:
7382
7977
  // Open dialog immediately with basic data, then hydrate with full preset once fetched
7383
7978
  setWorkspaceActionDialogOptions({
@@ -7401,7 +7996,7 @@ var WorkspaceSelectListConnect = function WorkspaceSelectListConnect(_ref) {
7401
7996
  }
7402
7997
  }));
7403
7998
  });
7404
- return _context2.abrupt("break", 26);
7999
+ return _context2.abrupt("break", 43);
7405
8000
  case 16:
7406
8001
  setWorkspaceActionDialogOptions({
7407
8002
  action: workspaceAction,
@@ -7411,7 +8006,7 @@ var WorkspaceSelectListConnect = function WorkspaceSelectListConnect(_ref) {
7411
8006
  scope: scope
7412
8007
  }
7413
8008
  });
7414
- return _context2.abrupt("break", 26);
8009
+ return _context2.abrupt("break", 43);
7415
8010
  case 18:
7416
8011
  setWorkspaceActionDialogOptions({
7417
8012
  action: workspaceAction,
@@ -7421,7 +8016,7 @@ var WorkspaceSelectListConnect = function WorkspaceSelectListConnect(_ref) {
7421
8016
  scope: scope
7422
8017
  }
7423
8018
  });
7424
- return _context2.abrupt("break", 26);
8019
+ return _context2.abrupt("break", 43);
7425
8020
  case 20:
7426
8021
  void getWorkspace(presetId, auth).then(/*#__PURE__*/function () {
7427
8022
  var _ref5 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(preset) {
@@ -7457,18 +8052,47 @@ var WorkspaceSelectListConnect = function WorkspaceSelectListConnect(_ref) {
7457
8052
  return _ref5.apply(this, arguments);
7458
8053
  };
7459
8054
  }());
7460
- return _context2.abrupt("break", 26);
8055
+ return _context2.abrupt("break", 43);
7461
8056
  case 22:
7462
8057
  url = getWorkspaceRouteUrl(presetId);
7463
8058
  window.open(url, '_blank');
7464
- return _context2.abrupt("break", 26);
8059
+ return _context2.abrupt("break", 43);
7465
8060
  case 25:
7466
- return _context2.abrupt("break", 26);
7467
- case 26:
8061
+ _context2.prev = 25;
8062
+ _context2.next = 28;
8063
+ return getWorkspace(presetId, auth);
8064
+ case 28:
8065
+ preset = _context2.sent;
8066
+ _context2.next = 31;
8067
+ return expandWorkspaceViewPresets(preset, auth);
8068
+ case 31:
8069
+ expanded = _context2.sent;
8070
+ sanitized = sanitizeWorkspaceForClipboard(expanded);
8071
+ _context2.next = 35;
8072
+ return writeToClipboard(JSON.stringify(sanitized, null, 2));
8073
+ case 35:
8074
+ dispatch(snackbarActions.openSnackbar({
8075
+ type: snackbarTypes.SnackbarMessageType.VERBATIM_MESSAGE,
8076
+ message: t('workspace-copy-success')
8077
+ }));
8078
+ _context2.next = 41;
8079
+ break;
8080
+ case 38:
8081
+ _context2.prev = 38;
8082
+ _context2.t1 = _context2["catch"](25);
8083
+ dispatch(snackbarActions.openSnackbar({
8084
+ type: snackbarTypes.SnackbarMessageType.VERBATIM_MESSAGE,
8085
+ message: t('workspace-error-generic')
8086
+ }));
8087
+ case 41:
8088
+ return _context2.abrupt("break", 43);
8089
+ case 42:
8090
+ return _context2.abrupt("break", 43);
8091
+ case 43:
7468
8092
  case "end":
7469
8093
  return _context2.stop();
7470
8094
  }
7471
- }, _callee2);
8095
+ }, _callee2, null, [[25, 38]]);
7472
8096
  }));
7473
8097
  return function onClickWorkspacePresetOption(_x, _x2) {
7474
8098
  return _ref2.apply(this, arguments);
@@ -7798,6 +8422,10 @@ var WorkspaceOptions = function WorkspaceOptions(_ref) {
7798
8422
  handleEditTitle = _ref.handleEditTitle,
7799
8423
  handleDelete = _ref.handleDelete,
7800
8424
  handleReset = _ref.handleReset,
8425
+ handleCopyToClipboard = _ref.handleCopyToClipboard,
8426
+ handlePasteFromClipboard = _ref.handlePasteFromClipboard,
8427
+ copyToClipboardLabel = _ref.copyToClipboardLabel,
8428
+ pasteFromClipboardLabel = _ref.pasteFromClipboardLabel,
7801
8429
  _ref$isDisabled = _ref.isDisabled,
7802
8430
  isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
7803
8431
  _ref$isDefaultOpen = _ref.isDefaultOpen,
@@ -7829,6 +8457,12 @@ var WorkspaceOptions = function WorkspaceOptions(_ref) {
7829
8457
  }] : [], [{
7830
8458
  title: t('workspace-reset'),
7831
8459
  callback: handleReset
8460
+ }, {
8461
+ title: copyToClipboardLabel != null ? copyToClipboardLabel : t('workspace-copy-to-clipboard'),
8462
+ callback: handleCopyToClipboard
8463
+ }, {
8464
+ title: pasteFromClipboardLabel != null ? pasteFromClipboardLabel : t('workspace-paste-from-clipboard'),
8465
+ callback: handlePasteFromClipboard
7832
8466
  }, {
7833
8467
  title: t('workspace-delete'),
7834
8468
  callback: handleDelete
@@ -7950,7 +8584,7 @@ var LoadingIndicatorConnect = function LoadingIndicatorConnect(_ref) {
7950
8584
 
7951
8585
  var _excluded$4 = ["title", "scope"];
7952
8586
  var WorkspaceViewTitleConnectNoMemo = function WorkspaceViewTitleConnectNoMemo(_ref) {
7953
- var _currentWorkspace$sco, _currentViewPreset$ab, _currentViewPreset$de, _currentViewPreset$la, _currentWorkspacePres;
8587
+ var _currentWorkspace$sco, _currentViewPreset$ab, _currentViewPreset$de, _currentViewPreset$la, _ref7, _currentWorkspacePres;
7954
8588
  var panelId = _ref.panelId,
7955
8589
  isViewPresetDialogOpen = _ref.isViewPresetDialogOpen;
7956
8590
  var dispatch = useDispatch();
@@ -7982,6 +8616,9 @@ var WorkspaceViewTitleConnectNoMemo = function WorkspaceViewTitleConnectNoMemo(_
7982
8616
  scope: scope
7983
8617
  }, restProps);
7984
8618
  }, shallowEqual);
8619
+ var liveViewPreset = useSelector(function (store) {
8620
+ return getViewPresetToSendToBackend(store, panelId);
8621
+ });
7985
8622
  // whole workspace (id/title/abstract/scope + views)
7986
8623
  var currentWorkspace = useSelector(function (store) {
7987
8624
  return getWorkspaceState(store);
@@ -8024,6 +8661,8 @@ var WorkspaceViewTitleConnectNoMemo = function WorkspaceViewTitleConnectNoMemo(_
8024
8661
  var showChangedInViewTitle = !!hasViewPresetChanges;
8025
8662
  var isNewForDisplay = isNewActive && !hasViewPresetChanges;
8026
8663
  var fullTitle = getPresetTitle(title, showChangedInViewTitle, isNewForDisplay, t);
8664
+ // Whether or not to display the panelId next to the preset title
8665
+ var showPanelId = constructSyncSourceDisplayName(panelId, workspaceView, title + " (" + panelId + ")").includes("(" + panelId + ")");
8027
8666
  var openViewPresetsDialog = React.useCallback(function (viewPresetDialogOptions) {
8028
8667
  dispatch(viewPresetActions.openViewPresetDialog({
8029
8668
  viewPresetDialog: viewPresetDialogOptions
@@ -8159,9 +8798,97 @@ var WorkspaceViewTitleConnectNoMemo = function WorkspaceViewTitleConnectNoMemo(_
8159
8798
  });
8160
8799
  }
8161
8800
  }, [isPlainWorkspaceView, currentWorkspace, thisView, panelId, dispatch, openViewPresetsDialog, activeViewPresetId, title, t]);
8162
- var toggleViewPresetDialog = React.useCallback(function (_ref5) {
8163
- var panelId = _ref5.panelId,
8164
- isViewPresetDialogOpen = _ref5.isViewPresetDialogOpen;
8801
+ var _React$useState = React.useState(false),
8802
+ isPasteDialogOpen = _React$useState[0],
8803
+ setIsPasteDialogOpen = _React$useState[1];
8804
+ var onCopyToClipboard = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
8805
+ var fullPreset, sanitized, json;
8806
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
8807
+ while (1) switch (_context.prev = _context.next) {
8808
+ case 0:
8809
+ _context.prev = 0;
8810
+ if (!isActiveWorkspaceView) {
8811
+ _context.next = 5;
8812
+ break;
8813
+ }
8814
+ fullPreset = Object.assign({}, liveViewPreset, {
8815
+ title: title
8816
+ });
8817
+ _context.next = 16;
8818
+ break;
8819
+ case 5:
8820
+ _context.prev = 5;
8821
+ _context.next = 8;
8822
+ return getQueryClient().fetchQuery(viewpresetQueryOptions.getViewPreset(activeViewPresetId, auth));
8823
+ case 8:
8824
+ fullPreset = _context.sent;
8825
+ _context.next = 16;
8826
+ break;
8827
+ case 11:
8828
+ _context.prev = 11;
8829
+ _context.t0 = _context["catch"](5);
8830
+ if (liveViewPreset.initialProps) {
8831
+ _context.next = 15;
8832
+ break;
8833
+ }
8834
+ throw new Error('View preset not available');
8835
+ case 15:
8836
+ fullPreset = liveViewPreset;
8837
+ case 16:
8838
+ sanitized = sanitizeViewPresetForClipboard(fullPreset);
8839
+ json = JSON.stringify(sanitized, null, 2);
8840
+ _context.next = 20;
8841
+ return writeToClipboard(json);
8842
+ case 20:
8843
+ dispatch(snackbarActions.openSnackbar({
8844
+ type: snackbarTypes.SnackbarMessageType.VERBATIM_MESSAGE,
8845
+ message: t('workspace-copy-viewpreset-success')
8846
+ }));
8847
+ _context.next = 26;
8848
+ break;
8849
+ case 23:
8850
+ _context.prev = 23;
8851
+ _context.t1 = _context["catch"](0);
8852
+ dispatch(snackbarActions.openSnackbar({
8853
+ type: snackbarTypes.SnackbarMessageType.VERBATIM_MESSAGE,
8854
+ message: t('workspace-error-generic')
8855
+ }));
8856
+ case 26:
8857
+ case "end":
8858
+ return _context.stop();
8859
+ }
8860
+ }, _callee, null, [[0, 23], [5, 11]]);
8861
+ })), [activeViewPresetId, auth, dispatch, isActiveWorkspaceView, liveViewPreset, t, title]);
8862
+ var onPasteFromClipboard = function onPasteFromClipboard() {
8863
+ setIsPasteDialogOpen(true);
8864
+ };
8865
+ var onPasteViewPresetConfirm = React.useCallback(function (jsonString) {
8866
+ var parsed = JSON.parse(jsonString);
8867
+ var sanitized = sanitizeViewPresetForClipboard(parsed);
8868
+ if (sanitized.componentType === 'Map' && sanitized.initialProps) {
8869
+ dispatch(mapActions.setMapPreset({
8870
+ mapId: panelId,
8871
+ initialProps: sanitized.initialProps
8872
+ }));
8873
+ }
8874
+ dispatch(viewPresetActions.fetchedViewPreset({
8875
+ viewPreset: sanitized,
8876
+ viewPresetId: '',
8877
+ panelId: panelId
8878
+ }));
8879
+ dispatch(workspaceActions.updateWorkspaceView({
8880
+ mosaicNodeId: panelId,
8881
+ viewPreset: sanitized
8882
+ }));
8883
+ dispatch(workspaceActions.markWorkspaceChanged());
8884
+ dispatch(snackbarActions.openSnackbar({
8885
+ type: snackbarTypes.SnackbarMessageType.VERBATIM_MESSAGE,
8886
+ message: t('workspace-paste-viewpreset-success')
8887
+ }));
8888
+ }, [dispatch, panelId, t]);
8889
+ var toggleViewPresetDialog = React.useCallback(function (_ref6) {
8890
+ var panelId = _ref6.panelId,
8891
+ isViewPresetDialogOpen = _ref6.isViewPresetDialogOpen;
8165
8892
  dispatch(viewPresetActions.toggleViewPresetListDialog({
8166
8893
  panelId: panelId,
8167
8894
  isViewPresetListDialogOpen: isViewPresetDialogOpen
@@ -8175,14 +8902,14 @@ var WorkspaceViewTitleConnectNoMemo = function WorkspaceViewTitleConnectNoMemo(_
8175
8902
  }, [isViewPresetDialogOpen, panelId, toggleViewPresetDialog]);
8176
8903
  renderCounter.count(WorkspaceViewTitleConnectNoMemo.name);
8177
8904
  var viewpresetCreator = (currentViewPreset == null ? void 0 : currentViewPreset.username) || '';
8178
- var workspaceOwner = (_currentWorkspacePres = currentWorkspacePresetDetails == null ? void 0 : currentWorkspacePresetDetails.username) != null ? _currentWorkspacePres : undefined;
8905
+ var workspaceOwner = (_ref7 = (_currentWorkspacePres = currentWorkspacePresetDetails == null ? void 0 : currentWorkspacePresetDetails.username) != null ? _currentWorkspacePres : currentWorkspace == null ? void 0 : currentWorkspace.username) != null ? _ref7 : undefined;
8179
8906
  var isUserPresetCreator = !isAdmin && !!(auth != null && auth.username) && auth.username === viewpresetCreator;
8180
- var isWorkspaceOwner = !isAdmin && !!workspaceOwner && (auth == null ? void 0 : auth.username) === workspaceOwner;
8907
+ var isWorkspaceOwner = !isAdmin && (!!workspaceOwner && (auth == null ? void 0 : auth.username) === workspaceOwner || !workspaceOwner && workspaceScope === 'user' && isLoggedIn);
8181
8908
  var currentViewScope = (currentViewPreset == null ? void 0 : currentViewPreset.scope) || 'system';
8182
8909
  // Regular viewPresets
8183
8910
  var isEnabled = !isPlainWorkspaceView && isLoggedIn && activeViewPresetId !== '' && (currentViewScope === 'user' && isUserPresetCreator || currentViewScope === 'system' && isAdmin);
8184
8911
  // Workspace views
8185
- var canEditPlainView = isPlainWorkspaceView && isLoggedIn && (workspaceScope === 'user' && isWorkspaceOwner || workspaceScope === 'system' && isAdmin);
8912
+ var canEditWorkspaceViewTitle = isLoggedIn && (workspaceScope === 'user' && isWorkspaceOwner || workspaceScope === 'system' && isAdmin);
8186
8913
  return (
8187
8914
  // Zero-length string assignment prevents showing title as an empty object '[object Object]'.
8188
8915
  // in child components. This is a workaround for a limitation in the Tooltip component.
@@ -8250,7 +8977,7 @@ var WorkspaceViewTitleConnectNoMemo = function WorkspaceViewTitleConnectNoMemo(_
8250
8977
  whiteSpace: 'nowrap',
8251
8978
  width: '100%'
8252
8979
  },
8253
- children: [fullTitle, jsx(Box, {
8980
+ children: [fullTitle, showPanelId ? jsx(Box, {
8254
8981
  component: "span",
8255
8982
  sx: {
8256
8983
  fontStyle: 'normal',
@@ -8259,17 +8986,21 @@ var WorkspaceViewTitleConnectNoMemo = function WorkspaceViewTitleConnectNoMemo(_
8259
8986
  color: isViewPresetDialogOpen ? 'geowebColors.text.inverse' : 'geowebColors.captions.captionStatus.rgba'
8260
8987
  },
8261
8988
  children: panelId
8262
- })]
8989
+ }) : null]
8263
8990
  })
8264
8991
  })
8265
8992
  }), jsx(WorkspaceOptions, {
8993
+ copyToClipboardLabel: t('workspace-copy-viewpreset-to-clipboard'),
8994
+ handleCopyToClipboard: (isPresetBacked || isActiveWorkspaceView) && isLoggedIn ? onCopyToClipboard : undefined,
8266
8995
  handleDelete: isEnabled ? onDelete : undefined,
8267
8996
  handleEdit: isEnabled ? onEdit : undefined,
8268
- handleEditTitle: canEditPlainView ? handleEditTitle : undefined,
8997
+ handleEditTitle: canEditWorkspaceViewTitle ? handleEditTitle : undefined,
8998
+ handlePasteFromClipboard: isLoggedIn ? onPasteFromClipboard : undefined,
8269
8999
  handleReset: onReset,
8270
9000
  handleSave: isEnabled ? onSave : undefined,
8271
9001
  handleSaveAs: isLoggedIn ? onSaveAs : undefined,
8272
9002
  id: viewPresetOptionId,
9003
+ pasteFromClipboardLabel: t('workspace-paste-viewpreset-from-clipboard'),
8273
9004
  showEditTitleOption: true
8274
9005
  })]
8275
9006
  }), jsx(Box, {
@@ -8281,6 +9012,13 @@ var WorkspaceViewTitleConnectNoMemo = function WorkspaceViewTitleConnectNoMemo(_
8281
9012
  children: jsx(LoadingIndicatorConnect, {
8282
9013
  panelId: panelId
8283
9014
  })
9015
+ }), jsx(PastePresetDialog, {
9016
+ isOpen: isPasteDialogOpen,
9017
+ mode: "viewpreset",
9018
+ onClose: function onClose() {
9019
+ return setIsPasteDialogOpen(false);
9020
+ },
9021
+ onConfirm: onPasteViewPresetConfirm
8284
9022
  })]
8285
9023
  })
8286
9024
  );
@@ -8520,7 +9258,9 @@ var WorkspaceView = function WorkspaceView(_ref) {
8520
9258
  },
8521
9259
  '.mosaic-window-toolbar .mosaic-window-title': {
8522
9260
  color: windowIsActive ? theme.palette.geowebColors.typographyAndIcons.text : theme.palette.geowebColors.typographyAndIcons.inactiveText
8523
- }
9261
+ },
9262
+ containerName: 'workspace-view-container',
9263
+ containerType: 'inline-size'
8524
9264
  };
8525
9265
  },
8526
9266
  children: jsx(WorkspaceTileConnect, {
@@ -8695,7 +9435,7 @@ var WorkspaceMenuButtonConnect = function WorkspaceMenuButtonConnect(_ref) {
8695
9435
  };
8696
9436
 
8697
9437
  var WorkspaceOptionsConnect = function WorkspaceOptionsConnect(_ref) {
8698
- var _currentWorkspacePres;
9438
+ var _workspaceData$userna;
8699
9439
  var title = _ref.title,
8700
9440
  workspaceId = _ref.workspaceId;
8701
9441
  var dispatch = useDispatch();
@@ -8714,17 +9454,14 @@ var WorkspaceOptionsConnect = function WorkspaceOptionsConnect(_ref) {
8714
9454
  var workspaceData = useSelector(function (store) {
8715
9455
  return getWorkspaceData(store);
8716
9456
  });
8717
- var _useWorkspacePresets = useWorkspacePresets(),
8718
- _useWorkspacePresets$ = _useWorkspacePresets.data,
8719
- workspacePresets = _useWorkspacePresets$ === void 0 ? [] : _useWorkspacePresets$;
8720
- var currentWorkspacePreset = workspacePresets.find(function (preset) {
8721
- return preset.id === workspaceId;
8722
- });
8723
- var workspaceCreator = (_currentWorkspacePres = currentWorkspacePreset == null ? void 0 : currentWorkspacePreset.username) != null ? _currentWorkspacePres : '';
9457
+ var workspaceCreator = (_workspaceData$userna = workspaceData == null ? void 0 : workspaceData.username) != null ? _workspaceData$userna : '';
8724
9458
  var viewIds = useSelector(function (store) {
8725
9459
  return getViewIds(store);
8726
9460
  });
8727
- var isNew = !workspaceId;
9461
+ var storeWorkspaceId = useSelector(function (store) {
9462
+ return getWorkspaceId(store);
9463
+ });
9464
+ var isNew = !storeWorkspaceId;
8728
9465
  var isUserPreset = workspaceScope === 'user';
8729
9466
  var isUserPresetCreator = (auth == null ? void 0 : auth.username) === workspaceCreator;
8730
9467
  var setWorkspaceActionDialogOptions = React.useCallback(function (dialogOptions) {
@@ -8849,13 +9586,81 @@ var WorkspaceOptionsConnect = function WorkspaceOptionsConnect(_ref) {
8849
9586
  }
8850
9587
  return isUserPreset && isUserPresetCreator ? onEdit : undefined;
8851
9588
  };
8852
- return jsx(WorkspaceOptions, {
8853
- handleDelete: getOnDelete(),
8854
- handleEdit: handleEdit(),
8855
- handleReset: onReset,
8856
- handleSave: handleSave(),
8857
- handleSaveAs: handleSaveAs(),
8858
- isDisabled: !viewIds.length || !isLoggedIn
9589
+ var _React$useState = React.useState(false),
9590
+ isPasteDialogOpen = _React$useState[0],
9591
+ setIsPasteDialogOpen = _React$useState[1];
9592
+ var onCopyToClipboard = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
9593
+ var preset, expanded, sanitized, json;
9594
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
9595
+ while (1) switch (_context.prev = _context.next) {
9596
+ case 0:
9597
+ _context.prev = 0;
9598
+ _context.next = 3;
9599
+ return getWorkspace(workspaceId, auth);
9600
+ case 3:
9601
+ preset = _context.sent;
9602
+ _context.next = 6;
9603
+ return expandWorkspaceViewPresets(preset, auth);
9604
+ case 6:
9605
+ expanded = _context.sent;
9606
+ sanitized = sanitizeWorkspaceForClipboard(expanded);
9607
+ json = JSON.stringify(sanitized, null, 2);
9608
+ _context.next = 11;
9609
+ return writeToClipboard(json);
9610
+ case 11:
9611
+ dispatch(snackbarActions.openSnackbar({
9612
+ type: snackbarTypes.SnackbarMessageType.VERBATIM_MESSAGE,
9613
+ message: t('workspace-copy-success')
9614
+ }));
9615
+ _context.next = 17;
9616
+ break;
9617
+ case 14:
9618
+ _context.prev = 14;
9619
+ _context.t0 = _context["catch"](0);
9620
+ dispatch(snackbarActions.openSnackbar({
9621
+ type: snackbarTypes.SnackbarMessageType.VERBATIM_MESSAGE,
9622
+ message: t('workspace-error-generic')
9623
+ }));
9624
+ case 17:
9625
+ case "end":
9626
+ return _context.stop();
9627
+ }
9628
+ }, _callee, null, [[0, 14]]);
9629
+ })), [auth, workspaceId, dispatch, t]);
9630
+ var onPasteFromClipboard = React.useCallback(function () {
9631
+ setIsPasteDialogOpen(true);
9632
+ }, []);
9633
+ var onPasteConfirm = React.useCallback(function (jsonString) {
9634
+ var parsed = JSON.parse(jsonString);
9635
+ var sanitized = sanitizeWorkspaceForClipboard(parsed);
9636
+ var workspacePreset = getLoadingWorkspace(sanitized);
9637
+ dispatch(workspaceActions.changePreset({
9638
+ workspacePreset: workspacePreset,
9639
+ markAsChanged: true
9640
+ }));
9641
+ dispatch(snackbarActions.openSnackbar({
9642
+ type: snackbarTypes.SnackbarMessageType.VERBATIM_MESSAGE,
9643
+ message: t('workspace-paste-success')
9644
+ }));
9645
+ }, [dispatch, t]);
9646
+ return jsxs(Fragment, {
9647
+ children: [jsx(WorkspaceOptions, {
9648
+ handleCopyToClipboard: isNew ? undefined : onCopyToClipboard,
9649
+ handleDelete: getOnDelete(),
9650
+ handleEdit: handleEdit(),
9651
+ handlePasteFromClipboard: onPasteFromClipboard,
9652
+ handleReset: onReset,
9653
+ handleSave: handleSave(),
9654
+ handleSaveAs: handleSaveAs(),
9655
+ isDisabled: !viewIds.length || !isLoggedIn
9656
+ }), jsx(PastePresetDialog, {
9657
+ isOpen: isPasteDialogOpen,
9658
+ mode: "workspace",
9659
+ onClose: function onClose() {
9660
+ return setIsPasteDialogOpen(false);
9661
+ },
9662
+ onConfirm: onPasteConfirm
9663
+ })]
8859
9664
  });
8860
9665
  };
8861
9666
 
@@ -8898,6 +9703,7 @@ var emptyWorkspacePreset = {
8898
9703
  "abstract": ''
8899
9704
  };
8900
9705
  var SHORT_DESC_LIMIT$1 = 100;
9706
+ var VIEW_TITLE_LIMIT = 100;
8901
9707
  var WorkspacePresetsForm = function WorkspacePresetsForm(_ref) {
8902
9708
  var _watch;
8903
9709
  var error = _ref.error,
@@ -8956,7 +9762,7 @@ var WorkspacePresetsForm = function WorkspacePresetsForm(_ref) {
8956
9762
  };
8957
9763
  var hasFormInput = action === WorkspacePresetAction.DUPLICATE || action === WorkspacePresetAction.SAVE || action === WorkspacePresetAction.SAVE_AS || action === WorkspacePresetAction.EDIT || action === WorkspacePresetAction.EDIT_TITLE || action === WorkspacePresetAction.SAVE_SYSTEM_PRESET || action === WorkspacePresetAction.SAVE_SYSTEM_PRESET_AS;
8958
9764
  // disable form inputs
8959
- var isDisabled = hasSavedWorkspace || isLoading;
9765
+ var isDisabled = isLoading || hasSavedWorkspace && action !== WorkspacePresetAction.EDIT_TITLE;
8960
9766
  var shouldShowLabelsForm = action === WorkspacePresetAction.SAVE_SYSTEM_PRESET_AS || action === WorkspacePresetAction.SAVE_AS || action === WorkspacePresetAction.EDIT;
8961
9767
  return jsxs(Fragment, {
8962
9768
  children: [!!error && !shouldShowTitleError && jsx(Box, {
@@ -8999,7 +9805,16 @@ var WorkspacePresetsForm = function WorkspacePresetsForm(_ref) {
8999
9805
  label: mosaicNodeId || t('workspace-view-title'),
9000
9806
  name: "views.0.title",
9001
9807
  rules: {
9002
- required: false
9808
+ required: false,
9809
+ maxLength: {
9810
+ value: VIEW_TITLE_LIMIT,
9811
+ message: "Maximum " + VIEW_TITLE_LIMIT + " characters"
9812
+ }
9813
+ },
9814
+ slotProps: {
9815
+ htmlInput: {
9816
+ maxLength: VIEW_TITLE_LIMIT
9817
+ }
9003
9818
  }
9004
9819
  })]
9005
9820
  });