@opengeoweb/warnings 19.6.1-nightly-20260917 → 20.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/dist/index.esm.js +489 -36
- package/dist/src/lib/components/DrawingToolForm/DrawingToolForm.d.ts +1 -0
- package/dist/src/lib/components/DrawingToolForm/DrawingToolFormConnect.d.ts +1 -0
- package/dist/src/lib/components/DrawingToolForm/DrawingToolFormContents.d.ts +1 -0
- package/dist/src/lib/components/DrawingToolForm/maskUtils.d.ts +15 -0
- package/dist/src/lib/components/DrawingToolForm/useMaskPreviewLayer.d.ts +3 -1
- package/dist/src/lib/store/warningsDrawings/types.d.ts +5 -0
- package/package.json +12 -12
package/dist/index.esm.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useDispatch, useSelector, useStore, shallowEqual } from 'react-redux';
|
|
3
3
|
import { uiTypes, uiActions, getSingularDrawtoolDrawLayerId, drawingToolSelectors, layerSelectors, uiSelectors, layerActions, drawingToolActions, layerUtils, mapListener, layersListener, drawingToolListener, syncGroupsListener, openlayersListener, syncGroupsReducer, drawingToolReducer, uiReducer, layerReducer, mapReducer, useSetupDialog, PUBLIC_WARNING_DRAW_TOOL_ID, genericSelectors, useUpdateFeatureSyncLayers, genericActions, selectorMemoizationOptions, useRegisterFeatureSyncSource, syncGroupsSelector } from '@opengeoweb/store';
|
|
4
4
|
import { Polygons, Edit, Delete, ExitDomain, ChevronDown, DrawPolygon, Remove, Options, Waterspouts, Snow, FreezingRain, CoastalEvent, TemperatureLow, TemperatureHigh, Rain, Lightning, Fog, Wind, Thunderstorm, SevereMountainWaves, VulcanicEruption, Haze, FreezingPrecipitation, ModerateAircraftIcing, SevereAircraftIcing, ModerateTurbulence, SevereTurbulence, SandStorm, RadioactiveMaterials, DrawMask, Visibility, Add, breakpoints, DragHandle, Info, ArrowUpCompact, ArrowDownCompact, CalendarToday, Expire, Cube, AlertBadge, ArrowDropDownDown, Extend24h, Copy, Update, Cancel, Success, VisibilityOff, ChevronUp, Close, Clock } from '@opengeoweb/theme';
|
|
5
|
-
import { WEBMAP_REACT_NAMESPACE, defaultPolygon, emptyGeoJSON, MapControlButton, isGeoJSONGeometryEmpty, rewindGeometry, removeTransientFeatureProperties, defaultSmoothLine, defaultLineString, defaultFreehandLine, defaultOval, defaultCircle, defaultRotatableBox, defaultSquare, defaultLocation, defaultPoint, defaultSplit, defaultDelete, getDrawModeIdFromSelectionType, getIcon, getGeoJSONPropertyValue, DRAWMODE, currentlySupportedDrawModes, defaultLayers, viewUtils, OpenLayersMapView, MapControls, OpenLayersZoomControl, OpenLayersLayer, OpenLayersFeatureLayer, genericOpenLayersFeatureStyle, DEFAULT_GEOJSON_STYLE_FILL_OPACITY, FEATURE_DRAW_FILL_COLOR, FEATURE_DRAW_SECONDARY_FILL_COLOR, FEATURE_DRAW_STROKE_COLOR } from '@opengeoweb/webmap-react';
|
|
5
|
+
import { WEBMAP_REACT_NAMESPACE, defaultPolygon, emptyGeoJSON, MapControlButton, isGeoJSONGeometryEmpty, rewindGeometry, removeTransientFeatureProperties, defaultSmoothLine, defaultLineString, defaultFreehandLine, defaultOval, defaultCircle, defaultRotatableBox, defaultSquare, defaultLocation, defaultPoint, defaultSplit, defaultDelete, getDrawModeIdFromSelectionType, getIcon, getGeoJSONPropertyValue, FEATURE_DRAW_SECONDARY_STROKE_COLOR, DRAWMODE, currentlySupportedDrawModes, defaultLayers, viewUtils, OpenLayersMapView, MapControls, OpenLayersZoomControl, OpenLayersLayer, OpenLayersFeatureLayer, genericOpenLayersFeatureStyle, DEFAULT_GEOJSON_STYLE_FILL_OPACITY, FEATURE_DRAW_FILL_COLOR, FEATURE_DRAW_SECONDARY_FILL_COLOR, FEATURE_DRAW_STROKE_COLOR } from '@opengeoweb/webmap-react';
|
|
6
6
|
import { SHARED_NAMESPACE, useConfirmationDialog, dateUtils, sessionStorageProvider, ToggleMenu, calculateStartSize, ToolContainerDraggable, AlertBanner, ConfirmationDialog, CustomIconButton, usePrevious, usePreventBrowserClose, CustomTooltip, Avatar, getInitials, SwitchButton, Filter, CustomToggleButton, FilterChip, TooltipSelect, LastUpdateTime, DateTimePicker, StatusTag, FilterOption, getAxiosErrorMessage, CustomDialog, ConfirmationButtons, ErrorBoundary } from '@opengeoweb/shared';
|
|
7
7
|
import { createEntityAdapter, createSlice, createSelector, createListenerMiddleware, combineReducers, configureStore } from '@reduxjs/toolkit';
|
|
8
8
|
import { t } from 'i18next';
|
|
@@ -18,12 +18,12 @@ import { List, useListRef } from 'react-window';
|
|
|
18
18
|
import { useQueryClient, useMutation, queryOptions, QueryClient, useQuery } from '@tanstack/react-query';
|
|
19
19
|
import { getHeaders, handleResponse, AirmetPhenomena, SigmetPhenomena, useAuthQuery, useAuthenticationContext, optimisticUpdate, ProductStatus, LevelUnits } from '@opengeoweb/api';
|
|
20
20
|
import { snackbarListener, snackbarReducer, snackbarActions, snackbarTypes } from '@opengeoweb/snackbar';
|
|
21
|
-
import { isEqual, cloneDeep, clamp, concat, groupBy, pick } from 'lodash';
|
|
21
|
+
import { isEqual, cloneDeep, clamp, omit, concat, groupBy, pick } from 'lodash';
|
|
22
22
|
import { useFormContext, useFieldArray, useForm, FormProvider, useWatch } from 'react-hook-form';
|
|
23
|
-
import {
|
|
23
|
+
import { bbox, intersect, featureCollection, union, bboxClip, polygonToLine, lineSplit, along, length, booleanPointInPolygon, area } from '@turf/turf';
|
|
24
|
+
import { intersects, buffer, getWidth, getHeight, isEmpty, createEmpty, extend } from 'ol/extent';
|
|
24
25
|
import GeoJSON from 'ol/format/GeoJSON';
|
|
25
26
|
import { ReactSortable } from 'react-sortablejs';
|
|
26
|
-
import { intersect, area } from '@turf/turf';
|
|
27
27
|
import Box$1 from '@mui/material/Box';
|
|
28
28
|
import Tooltip$1 from '@mui/material/Tooltip';
|
|
29
29
|
import { useTheme as useTheme$1 } from '@mui/material/styles';
|
|
@@ -418,6 +418,9 @@ var en = {
|
|
|
418
418
|
"drawing-tool-form-masks-clear": "Clear",
|
|
419
419
|
"drawing-tool-form-masks-tooltip": "Select a mask to clip your drawing",
|
|
420
420
|
"drawing-tool-form-masks-empty": "No masks available. Please contact your administrator.",
|
|
421
|
+
"drawing-tool-form-mask-no-overlap": "The drawing does not overlap with the selected mask",
|
|
422
|
+
"drawing-tool-form-mask-clip-error": "The drawing could not be clipped with the selected mask",
|
|
423
|
+
"drawing-tool-form-mask-saved": "Saved mask",
|
|
421
424
|
"warning-event-button-add-drawing": "Add a drawing to this event, then choose individual objects for each warning",
|
|
422
425
|
"warning-event-button-assign-object": "Assign an object from the chosen drawing to this warning",
|
|
423
426
|
"warning-event-objects-menu-title": "Objects",
|
|
@@ -767,6 +770,9 @@ var nl = {
|
|
|
767
770
|
"drawing-tool-form-masks-clear": "Wissen",
|
|
768
771
|
"drawing-tool-form-masks-tooltip": "Selecteer een masker om je tekening bij te snijden",
|
|
769
772
|
"drawing-tool-form-masks-empty": "Geen maskers beschikbaar. Neem contact op met je beheerder.",
|
|
773
|
+
"drawing-tool-form-mask-no-overlap": "De tekening overlapt niet met het geselecteerde masker",
|
|
774
|
+
"drawing-tool-form-mask-clip-error": "De tekening kon niet worden bijgesneden met het geselecteerde masker",
|
|
775
|
+
"drawing-tool-form-mask-saved": "Opgeslagen masker",
|
|
770
776
|
"warning-event-button-add-drawing": "Voeg een tekening toe aan dit event. Wijs daarna individuele objecten toe aan elke waarschuwing",
|
|
771
777
|
"warning-event-button-assign-object": "Wijs een object uit de gekozen tekening toe aan deze waarschuwing",
|
|
772
778
|
"warning-event-objects-menu-title": "Objecten",
|
|
@@ -1068,6 +1074,9 @@ var fi = {
|
|
|
1068
1074
|
"drawing-tool-form-masks-clear": "ei käännetty",
|
|
1069
1075
|
"drawing-tool-form-masks-tooltip": "ei käännetty",
|
|
1070
1076
|
"drawing-tool-form-masks-empty": "ei käännetty",
|
|
1077
|
+
"drawing-tool-form-mask-no-overlap": "ei käännetty",
|
|
1078
|
+
"drawing-tool-form-mask-clip-error": "ei käännetty",
|
|
1079
|
+
"drawing-tool-form-mask-saved": "ei käännetty",
|
|
1071
1080
|
"warning-event-button-add-drawing": "ei käännetty",
|
|
1072
1081
|
"warning-event-button-assign-object": "ei käännetty",
|
|
1073
1082
|
"warning-event-objects-menu-title": "ei käännetty",
|
|
@@ -1367,6 +1376,9 @@ var no = {
|
|
|
1367
1376
|
"drawing-tool-form-masks-clear": "ikke oversatt",
|
|
1368
1377
|
"drawing-tool-form-masks-tooltip": "ikke oversatt",
|
|
1369
1378
|
"drawing-tool-form-masks-empty": "ikke oversatt",
|
|
1379
|
+
"drawing-tool-form-mask-no-overlap": "ikke oversatt",
|
|
1380
|
+
"drawing-tool-form-mask-clip-error": "ikke oversatt",
|
|
1381
|
+
"drawing-tool-form-mask-saved": "ikke oversatt",
|
|
1370
1382
|
"warning-event-button-add-drawing": "ikke oversatt",
|
|
1371
1383
|
"warning-event-button-assign-object": "ikke oversatt",
|
|
1372
1384
|
"warning-event-objects-menu-title": "Objekter",
|
|
@@ -1595,6 +1607,20 @@ function _regeneratorDefine(e, r, n, t) {
|
|
|
1595
1607
|
}) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2));
|
|
1596
1608
|
}, _regeneratorDefine(e, r, n, t);
|
|
1597
1609
|
}
|
|
1610
|
+
function _toPrimitive(t, r) {
|
|
1611
|
+
if ("object" != typeof t || !t) return t;
|
|
1612
|
+
var e = t[Symbol.toPrimitive];
|
|
1613
|
+
if (void 0 !== e) {
|
|
1614
|
+
var i = e.call(t, r);
|
|
1615
|
+
if ("object" != typeof i) return i;
|
|
1616
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
1617
|
+
}
|
|
1618
|
+
return (String )(t);
|
|
1619
|
+
}
|
|
1620
|
+
function _toPropertyKey(t) {
|
|
1621
|
+
var i = _toPrimitive(t, "string");
|
|
1622
|
+
return "symbol" == typeof i ? i : i + "";
|
|
1623
|
+
}
|
|
1598
1624
|
function _unsupportedIterableToArray(r, a) {
|
|
1599
1625
|
if (r) {
|
|
1600
1626
|
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
@@ -5724,6 +5750,7 @@ var AreaDrawingManagerConnect = function AreaDrawingManagerConnect(_ref2) {
|
|
|
5724
5750
|
setSelectedDrawingId(drawingId);
|
|
5725
5751
|
};
|
|
5726
5752
|
useEffect(function () {
|
|
5753
|
+
var _drawingDetails$trans, _drawingDetails$trans2;
|
|
5727
5754
|
if (!selectedDrawingId || !drawingDetails || (drawingDetails == null ? void 0 : drawingDetails.id) !== selectedDrawingId || isFetchingDetails) {
|
|
5728
5755
|
return;
|
|
5729
5756
|
}
|
|
@@ -5732,7 +5759,7 @@ var AreaDrawingManagerConnect = function AreaDrawingManagerConnect(_ref2) {
|
|
|
5732
5759
|
id: selectedDrawingId,
|
|
5733
5760
|
drawingInstanceId: drawingDialogType
|
|
5734
5761
|
}));
|
|
5735
|
-
openDrawDialog(drawingDetails.geoJSON);
|
|
5762
|
+
openDrawDialog((_drawingDetails$trans = (_drawingDetails$trans2 = drawingDetails.transformation) == null ? void 0 : _drawingDetails$trans2.original) != null ? _drawingDetails$trans : drawingDetails.geoJSON);
|
|
5736
5763
|
setSelectedDrawingId(undefined);
|
|
5737
5764
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
5738
5765
|
}, [selectedDrawingId, drawingDetails, dispatch, isFetchingDetails]);
|
|
@@ -6320,6 +6347,7 @@ var DrawingToolFormContentsNoMemo = function DrawingToolFormContentsNoMemo(_ref)
|
|
|
6320
6347
|
geoJSONProperties = _ref.geoJSONProperties,
|
|
6321
6348
|
masks = _ref.masks,
|
|
6322
6349
|
isLoadingMasks = _ref.isLoadingMasks,
|
|
6350
|
+
maskError = _ref.maskError,
|
|
6323
6351
|
selectedMaskId = _ref.selectedMaskId,
|
|
6324
6352
|
onSelectMask = _ref.onSelectMask,
|
|
6325
6353
|
onHoverMask = _ref.onHoverMask;
|
|
@@ -6437,19 +6465,28 @@ var DrawingToolFormContentsNoMemo = function DrawingToolFormContentsNoMemo(_ref)
|
|
|
6437
6465
|
}
|
|
6438
6466
|
}
|
|
6439
6467
|
})]
|
|
6440
|
-
}),
|
|
6468
|
+
}), jsxs(Grid, {
|
|
6441
6469
|
container: true,
|
|
6442
6470
|
sx: {
|
|
6443
6471
|
marginBottom: 1
|
|
6444
6472
|
},
|
|
6445
|
-
children: jsx(DrawingToolFormMasks, {
|
|
6473
|
+
children: [jsx(DrawingToolFormMasks, {
|
|
6446
6474
|
isDisabled: isLoading,
|
|
6447
6475
|
isLoadingMasks: isLoadingMasks,
|
|
6448
6476
|
masks: masks,
|
|
6449
6477
|
onHoverMask: onHoverMask,
|
|
6450
6478
|
onSelectMask: onSelectMask,
|
|
6451
6479
|
selectedMaskId: selectedMaskId
|
|
6452
|
-
})
|
|
6480
|
+
}), maskError ? jsx(FormHelperText, {
|
|
6481
|
+
"data-testid": "drawingToolForm-masks-error",
|
|
6482
|
+
error: true,
|
|
6483
|
+
sx: {
|
|
6484
|
+
marginLeft: 0,
|
|
6485
|
+
width: '100%'
|
|
6486
|
+
},
|
|
6487
|
+
variant: "filled",
|
|
6488
|
+
children: t(maskError)
|
|
6489
|
+
}) : null]
|
|
6453
6490
|
}), jsx(Grid, {
|
|
6454
6491
|
container: true,
|
|
6455
6492
|
size: "grow",
|
|
@@ -6598,7 +6635,7 @@ var DrawingToolFormContentsNoMemo = function DrawingToolFormContentsNoMemo(_ref)
|
|
|
6598
6635
|
},
|
|
6599
6636
|
children: jsx(Button, {
|
|
6600
6637
|
"data-testid": "saveDrawingFormButton",
|
|
6601
|
-
disabled: isLoading || hasErrors,
|
|
6638
|
+
disabled: isLoading || hasErrors || !!maskError,
|
|
6602
6639
|
onClick: onSubmit,
|
|
6603
6640
|
sx: {
|
|
6604
6641
|
width: '100%',
|
|
@@ -6696,6 +6733,7 @@ var DrawingToolForm = function DrawingToolForm(_ref) {
|
|
|
6696
6733
|
masks = _ref$masks === void 0 ? emptyMasks$1 : _ref$masks,
|
|
6697
6734
|
_ref$isLoadingMasks = _ref.isLoadingMasks,
|
|
6698
6735
|
isLoadingMasks = _ref$isLoadingMasks === void 0 ? false : _ref$isLoadingMasks,
|
|
6736
|
+
maskError = _ref.maskError,
|
|
6699
6737
|
selectedMaskId = _ref.selectedMaskId,
|
|
6700
6738
|
_ref$onSelectMask = _ref.onSelectMask,
|
|
6701
6739
|
onSelectMask = _ref$onSelectMask === void 0 ? noopSelectMask : _ref$onSelectMask,
|
|
@@ -6830,6 +6868,7 @@ var DrawingToolForm = function DrawingToolForm(_ref) {
|
|
|
6830
6868
|
isInEditMode: isInEditMode,
|
|
6831
6869
|
isLoading: isLoading,
|
|
6832
6870
|
isLoadingMasks: isLoadingMasks,
|
|
6871
|
+
maskError: maskError,
|
|
6833
6872
|
masks: masks,
|
|
6834
6873
|
onBlurName: onBlurName,
|
|
6835
6874
|
onBlurObjectName: onBlurObjectName,
|
|
@@ -6865,6 +6904,265 @@ var Wrapper = function Wrapper(props) {
|
|
|
6865
6904
|
});
|
|
6866
6905
|
};
|
|
6867
6906
|
|
|
6907
|
+
var CLIPPED_RESULT_FILL_OPACITY = 0.4;
|
|
6908
|
+
var MASKED_FILL_OPACITY_KEY = 'maskedFillOpacity';
|
|
6909
|
+
var getDrawnFeatureIndexes = function getDrawnFeatureIndexes(geoJSON) {
|
|
6910
|
+
return geoJSON.features.reduce(function (indexes, feature, index) {
|
|
6911
|
+
return isGeoJSONGeometryEmpty(feature) ? indexes : [].concat(indexes, [index]);
|
|
6912
|
+
}, []);
|
|
6913
|
+
};
|
|
6914
|
+
var getFeatureIndexesToHideFill = function getFeatureIndexesToHideFill(geoJSON) {
|
|
6915
|
+
return getDrawnFeatureIndexes(geoJSON).filter(function (index) {
|
|
6916
|
+
var _geoJSON$features$ind;
|
|
6917
|
+
return ((_geoJSON$features$ind = geoJSON.features[index].properties) == null ? void 0 : _geoJSON$features$ind['fill-opacity']) !== 0;
|
|
6918
|
+
});
|
|
6919
|
+
};
|
|
6920
|
+
var getFeatureIndexesToRestoreFill = function getFeatureIndexesToRestoreFill(geoJSON) {
|
|
6921
|
+
return geoJSON.features.reduce(function (indexes, feature, index) {
|
|
6922
|
+
var _feature$properties;
|
|
6923
|
+
return ((_feature$properties = feature.properties) == null ? void 0 : _feature$properties[MASKED_FILL_OPACITY_KEY]) !== undefined ? [].concat(indexes, [index]) : indexes;
|
|
6924
|
+
}, []);
|
|
6925
|
+
};
|
|
6926
|
+
var restoreMaskedFillProperties = function restoreMaskedFillProperties(properties) {
|
|
6927
|
+
if ((properties == null ? void 0 : properties[MASKED_FILL_OPACITY_KEY]) === undefined) {
|
|
6928
|
+
return properties;
|
|
6929
|
+
}
|
|
6930
|
+
var fillOpacity = properties[MASKED_FILL_OPACITY_KEY],
|
|
6931
|
+
restProperties = _objectWithoutPropertiesLoose(properties, [MASKED_FILL_OPACITY_KEY].map(_toPropertyKey));
|
|
6932
|
+
return fillOpacity === null ? omit(restProperties, 'fill-opacity') : Object.assign({}, restProperties, {
|
|
6933
|
+
'fill-opacity': fillOpacity
|
|
6934
|
+
});
|
|
6935
|
+
};
|
|
6936
|
+
var restoreMaskedFill = function restoreMaskedFill(geoJSON) {
|
|
6937
|
+
return Object.assign({}, geoJSON, {
|
|
6938
|
+
features: geoJSON.features.map(function (feature) {
|
|
6939
|
+
return Object.assign({}, feature, {
|
|
6940
|
+
properties: restoreMaskedFillProperties(feature.properties)
|
|
6941
|
+
});
|
|
6942
|
+
})
|
|
6943
|
+
});
|
|
6944
|
+
};
|
|
6945
|
+
var maskPolygonCache = new WeakMap();
|
|
6946
|
+
var maskPartsCache = new WeakMap();
|
|
6947
|
+
var clippedGeometryCache = new WeakMap();
|
|
6948
|
+
var isPolygonFeature = function isPolygonFeature(feature) {
|
|
6949
|
+
var _feature$geometry, _feature$geometry2;
|
|
6950
|
+
return ((_feature$geometry = feature.geometry) == null ? void 0 : _feature$geometry.type) === 'Polygon' || ((_feature$geometry2 = feature.geometry) == null ? void 0 : _feature$geometry2.type) === 'MultiPolygon';
|
|
6951
|
+
};
|
|
6952
|
+
var getMaskPolygon = function getMaskPolygon(mask) {
|
|
6953
|
+
var _polygons$;
|
|
6954
|
+
var cachedMaskPolygon = maskPolygonCache.get(mask);
|
|
6955
|
+
if (cachedMaskPolygon !== undefined) {
|
|
6956
|
+
return cachedMaskPolygon;
|
|
6957
|
+
}
|
|
6958
|
+
var polygons = mask.features.filter(isPolygonFeature);
|
|
6959
|
+
var maskPolygon = polygons.length > 1 ? union(featureCollection(polygons)) : (_polygons$ = polygons[0]) != null ? _polygons$ : null;
|
|
6960
|
+
maskPolygonCache.set(mask, maskPolygon);
|
|
6961
|
+
return maskPolygon;
|
|
6962
|
+
};
|
|
6963
|
+
var getMaskParts = function getMaskParts(mask) {
|
|
6964
|
+
var cachedMaskParts = maskPartsCache.get(mask);
|
|
6965
|
+
if (cachedMaskParts) {
|
|
6966
|
+
return cachedMaskParts;
|
|
6967
|
+
}
|
|
6968
|
+
var maskParts = mask.features.filter(isPolygonFeature).map(function (polygon) {
|
|
6969
|
+
return {
|
|
6970
|
+
polygon: polygon,
|
|
6971
|
+
bbox: bbox(polygon)
|
|
6972
|
+
};
|
|
6973
|
+
});
|
|
6974
|
+
maskPartsCache.set(mask, maskParts);
|
|
6975
|
+
return maskParts;
|
|
6976
|
+
};
|
|
6977
|
+
var padBBox = function padBBox(geometryBBox) {
|
|
6978
|
+
return buffer(geometryBBox, Math.max(getWidth(geometryBBox), getHeight(geometryBBox)) * 0.01 + 1e-6);
|
|
6979
|
+
};
|
|
6980
|
+
var removeEmptyRings = function removeEmptyRings(polygon) {
|
|
6981
|
+
var isRing = function isRing(ring) {
|
|
6982
|
+
return ring.length > 3;
|
|
6983
|
+
};
|
|
6984
|
+
if (polygon.geometry.type === 'Polygon') {
|
|
6985
|
+
return Object.assign({}, polygon, {
|
|
6986
|
+
geometry: Object.assign({}, polygon.geometry, {
|
|
6987
|
+
coordinates: polygon.geometry.coordinates.filter(isRing)
|
|
6988
|
+
})
|
|
6989
|
+
});
|
|
6990
|
+
}
|
|
6991
|
+
return Object.assign({}, polygon, {
|
|
6992
|
+
geometry: Object.assign({}, polygon.geometry, {
|
|
6993
|
+
coordinates: polygon.geometry.coordinates.map(function (rings) {
|
|
6994
|
+
return rings.filter(isRing);
|
|
6995
|
+
}).filter(function (rings) {
|
|
6996
|
+
return rings.length > 0;
|
|
6997
|
+
})
|
|
6998
|
+
})
|
|
6999
|
+
});
|
|
7000
|
+
};
|
|
7001
|
+
var getMaskPolygonInBBox = function getMaskPolygonInBBox(maskPolygon, maskBBox, geometryBBox) {
|
|
7002
|
+
if (!intersects(maskBBox, geometryBBox)) {
|
|
7003
|
+
return null;
|
|
7004
|
+
}
|
|
7005
|
+
var clippedMask = removeEmptyRings(bboxClip(maskPolygon, padBBox(geometryBBox)));
|
|
7006
|
+
return clippedMask.geometry.coordinates.length ? clippedMask : null;
|
|
7007
|
+
};
|
|
7008
|
+
var isPointInMask = function isPointInMask(position, maskPolygon) {
|
|
7009
|
+
return booleanPointInPolygon(position, maskPolygon);
|
|
7010
|
+
};
|
|
7011
|
+
var clipLine = function clipLine(coordinates, maskPolygon, splitterPolygon) {
|
|
7012
|
+
var line = {
|
|
7013
|
+
type: 'Feature',
|
|
7014
|
+
properties: {},
|
|
7015
|
+
geometry: {
|
|
7016
|
+
type: 'LineString',
|
|
7017
|
+
coordinates: coordinates
|
|
7018
|
+
}
|
|
7019
|
+
};
|
|
7020
|
+
var outline = polygonToLine(splitterPolygon);
|
|
7021
|
+
var outlines = outline.type === 'FeatureCollection' ? outline.features : [outline];
|
|
7022
|
+
var segments = outlines.reduce(function (currentSegments, splitter) {
|
|
7023
|
+
return currentSegments.flatMap(function (segment) {
|
|
7024
|
+
var split = lineSplit(segment, splitter);
|
|
7025
|
+
return split.features.length ? split.features : [segment];
|
|
7026
|
+
});
|
|
7027
|
+
}, [line]);
|
|
7028
|
+
return segments.filter(function (segment) {
|
|
7029
|
+
var midpoint = along(segment, length(segment) / 2);
|
|
7030
|
+
return isPointInMask(midpoint.geometry.coordinates, maskPolygon);
|
|
7031
|
+
}).map(function (segment) {
|
|
7032
|
+
return segment.geometry.coordinates;
|
|
7033
|
+
});
|
|
7034
|
+
};
|
|
7035
|
+
var isPointInAnyMaskPart = function isPointInAnyMaskPart(position, mask) {
|
|
7036
|
+
return getMaskParts(mask).some(function (part) {
|
|
7037
|
+
return isPointInMask(position, part.polygon);
|
|
7038
|
+
});
|
|
7039
|
+
};
|
|
7040
|
+
var clipGeometry = function clipGeometry(geometry, mask) {
|
|
7041
|
+
switch (geometry.type) {
|
|
7042
|
+
case 'Polygon':
|
|
7043
|
+
case 'MultiPolygon':
|
|
7044
|
+
{
|
|
7045
|
+
var _union$geometry, _union;
|
|
7046
|
+
var geometryBBox = bbox(geometry);
|
|
7047
|
+
var feature = {
|
|
7048
|
+
type: 'Feature',
|
|
7049
|
+
properties: {},
|
|
7050
|
+
geometry: geometry
|
|
7051
|
+
};
|
|
7052
|
+
var clippedParts = getMaskParts(mask).reduce(function (result, part) {
|
|
7053
|
+
var maskInBBox = getMaskPolygonInBBox(part.polygon, part.bbox, geometryBBox);
|
|
7054
|
+
var clippedPart = maskInBBox && intersect(featureCollection([feature, maskInBBox]));
|
|
7055
|
+
return clippedPart ? [].concat(result, [clippedPart]) : result;
|
|
7056
|
+
}, []);
|
|
7057
|
+
if (clippedParts.length <= 1) {
|
|
7058
|
+
var _clippedParts$0$geome, _clippedParts$;
|
|
7059
|
+
return (_clippedParts$0$geome = (_clippedParts$ = clippedParts[0]) == null ? void 0 : _clippedParts$.geometry) != null ? _clippedParts$0$geome : null;
|
|
7060
|
+
}
|
|
7061
|
+
return (_union$geometry = (_union = union(featureCollection(clippedParts))) == null ? void 0 : _union.geometry) != null ? _union$geometry : null;
|
|
7062
|
+
}
|
|
7063
|
+
case 'LineString':
|
|
7064
|
+
case 'MultiLineString':
|
|
7065
|
+
{
|
|
7066
|
+
var maskPolygon = getMaskPolygon(mask);
|
|
7067
|
+
var maskInBBox = maskPolygon && getMaskPolygonInBBox(maskPolygon, bbox(maskPolygon), bbox(geometry));
|
|
7068
|
+
if (!maskPolygon || !maskInBBox) {
|
|
7069
|
+
return null;
|
|
7070
|
+
}
|
|
7071
|
+
var lines = geometry.type === 'LineString' ? [geometry.coordinates] : geometry.coordinates;
|
|
7072
|
+
var clipped = lines.flatMap(function (line) {
|
|
7073
|
+
return clipLine(line, maskPolygon, maskInBBox);
|
|
7074
|
+
});
|
|
7075
|
+
if (clipped.length === 0) {
|
|
7076
|
+
return null;
|
|
7077
|
+
}
|
|
7078
|
+
return clipped.length === 1 ? {
|
|
7079
|
+
type: 'LineString',
|
|
7080
|
+
coordinates: clipped[0]
|
|
7081
|
+
} : {
|
|
7082
|
+
type: 'MultiLineString',
|
|
7083
|
+
coordinates: clipped
|
|
7084
|
+
};
|
|
7085
|
+
}
|
|
7086
|
+
case 'Point':
|
|
7087
|
+
return isPointInAnyMaskPart(geometry.coordinates, mask) ? geometry : null;
|
|
7088
|
+
case 'MultiPoint':
|
|
7089
|
+
{
|
|
7090
|
+
var points = geometry.coordinates.filter(function (point) {
|
|
7091
|
+
return isPointInAnyMaskPart(point, mask);
|
|
7092
|
+
});
|
|
7093
|
+
return points.length ? {
|
|
7094
|
+
type: 'MultiPoint',
|
|
7095
|
+
coordinates: points
|
|
7096
|
+
} : null;
|
|
7097
|
+
}
|
|
7098
|
+
default:
|
|
7099
|
+
return geometry;
|
|
7100
|
+
}
|
|
7101
|
+
};
|
|
7102
|
+
var getClippedGeometry = function getClippedGeometry(geometry, mask) {
|
|
7103
|
+
var _clippedGeometryCache;
|
|
7104
|
+
var cachedByMask = (_clippedGeometryCache = clippedGeometryCache.get(geometry)) != null ? _clippedGeometryCache : new WeakMap();
|
|
7105
|
+
if (cachedByMask.has(mask)) {
|
|
7106
|
+
return cachedByMask.get(mask);
|
|
7107
|
+
}
|
|
7108
|
+
var clippedGeometry = clipGeometry(geometry, mask);
|
|
7109
|
+
cachedByMask.set(mask, clippedGeometry);
|
|
7110
|
+
clippedGeometryCache.set(geometry, cachedByMask);
|
|
7111
|
+
return clippedGeometry;
|
|
7112
|
+
};
|
|
7113
|
+
var clipGeoJSONWithMask = function clipGeoJSONWithMask(geoJSON, mask) {
|
|
7114
|
+
if (getMaskParts(mask).length === 0) {
|
|
7115
|
+
return Object.assign({}, geoJSON, {
|
|
7116
|
+
features: []
|
|
7117
|
+
});
|
|
7118
|
+
}
|
|
7119
|
+
var features = geoJSON.features.reduce(function (result, feature) {
|
|
7120
|
+
if (!feature.geometry || isGeoJSONGeometryEmpty(feature)) {
|
|
7121
|
+
return result;
|
|
7122
|
+
}
|
|
7123
|
+
var geometry = getClippedGeometry(feature.geometry, mask);
|
|
7124
|
+
return geometry ? [].concat(result, [Object.assign({}, feature, {
|
|
7125
|
+
geometry: geometry
|
|
7126
|
+
})]) : result;
|
|
7127
|
+
}, []);
|
|
7128
|
+
return Object.assign({}, geoJSON, {
|
|
7129
|
+
features: features
|
|
7130
|
+
});
|
|
7131
|
+
};
|
|
7132
|
+
var findMaskForTransformation = function findMaskForTransformation(masks, transformation) {
|
|
7133
|
+
if (!transformation) {
|
|
7134
|
+
return undefined;
|
|
7135
|
+
}
|
|
7136
|
+
var getGeometries = function getGeometries(geoJSON) {
|
|
7137
|
+
return geoJSON.features.map(function (feature) {
|
|
7138
|
+
return feature.geometry;
|
|
7139
|
+
});
|
|
7140
|
+
};
|
|
7141
|
+
var transformationGeometries = getGeometries(transformation.mask);
|
|
7142
|
+
return masks.find(function (mask) {
|
|
7143
|
+
return isEqual(getGeometries(mask.geoJSON), transformationGeometries);
|
|
7144
|
+
});
|
|
7145
|
+
};
|
|
7146
|
+
var buildClippedHighlightGeoJSON = function buildClippedHighlightGeoJSON(clipped) {
|
|
7147
|
+
return Object.assign({}, clipped, {
|
|
7148
|
+
features: clipped.features.map(function (feature, index) {
|
|
7149
|
+
var _feature$id;
|
|
7150
|
+
return Object.assign({}, feature, {
|
|
7151
|
+
id: "mask-result-" + ((_feature$id = feature.id) != null ? _feature$id : index),
|
|
7152
|
+
properties: Object.assign({}, feature.properties, {
|
|
7153
|
+
isReadonly: true,
|
|
7154
|
+
mapFeatureClass: 'default',
|
|
7155
|
+
isSelected: false,
|
|
7156
|
+
fill: '#186DFF',
|
|
7157
|
+
'fill-opacity': CLIPPED_RESULT_FILL_OPACITY,
|
|
7158
|
+
'stroke-width': 0,
|
|
7159
|
+
'stroke-opacity': 0
|
|
7160
|
+
})
|
|
7161
|
+
});
|
|
7162
|
+
})
|
|
7163
|
+
});
|
|
7164
|
+
};
|
|
7165
|
+
|
|
6868
7166
|
/* *
|
|
6869
7167
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6870
7168
|
* you may not use this file except in compliance with the License.
|
|
@@ -6882,10 +7180,13 @@ var Wrapper = function Wrapper(props) {
|
|
|
6882
7180
|
* Copyright 2026 - Finnish Meteorological Institute (FMI)
|
|
6883
7181
|
* Copyright 2026 - The Norwegian Meteorological Institute (MET Norway)
|
|
6884
7182
|
* */
|
|
6885
|
-
var MASK_PREVIEW_FILL_OPACITY = 0
|
|
7183
|
+
var MASK_PREVIEW_FILL_OPACITY = 0;
|
|
6886
7184
|
var getMaskPreviewLayerId = function getMaskPreviewLayerId(mapId) {
|
|
6887
7185
|
return "drawing-mask-preview-" + mapId;
|
|
6888
7186
|
};
|
|
7187
|
+
var getClippedResultLayerId = function getClippedResultLayerId(mapId) {
|
|
7188
|
+
return "drawing-mask-result-" + mapId;
|
|
7189
|
+
};
|
|
6889
7190
|
var buildMaskPreviewGeoJSON = function buildMaskPreviewGeoJSON(mask) {
|
|
6890
7191
|
return Object.assign({}, mask.geoJSON, {
|
|
6891
7192
|
features: mask.geoJSON.features.map(function (feature, index) {
|
|
@@ -6896,21 +7197,19 @@ var buildMaskPreviewGeoJSON = function buildMaskPreviewGeoJSON(mask) {
|
|
|
6896
7197
|
isReadonly: true,
|
|
6897
7198
|
mapFeatureClass: 'default',
|
|
6898
7199
|
isSelected: false,
|
|
6899
|
-
|
|
7200
|
+
// TODO https://gitlab.com/opengeoweb/opengeoweb/-/work_items/7413: remove this property and make the hover effect based on selectionType
|
|
7201
|
+
selectionType: 'fir',
|
|
7202
|
+
fill: FEATURE_DRAW_SECONDARY_STROKE_COLOR,
|
|
6900
7203
|
'fill-opacity': MASK_PREVIEW_FILL_OPACITY,
|
|
6901
|
-
stroke:
|
|
6902
|
-
|
|
7204
|
+
'stroke-width': 3,
|
|
7205
|
+
stroke: '#F59E0B'
|
|
6903
7206
|
})
|
|
6904
7207
|
});
|
|
6905
7208
|
})
|
|
6906
7209
|
});
|
|
6907
7210
|
};
|
|
6908
|
-
var
|
|
7211
|
+
var useReadonlyFeatureLayer = function useReadonlyFeatureLayer(mapId, layerId, geojson) {
|
|
6909
7212
|
var dispatch = useDispatch();
|
|
6910
|
-
var layerId = getMaskPreviewLayerId(mapId);
|
|
6911
|
-
var geojson = React.useMemo(function () {
|
|
6912
|
-
return mask ? buildMaskPreviewGeoJSON(mask) : emptyGeoJSON;
|
|
6913
|
-
}, [mask]);
|
|
6914
7213
|
React.useEffect(function () {
|
|
6915
7214
|
if (!mapId) {
|
|
6916
7215
|
return undefined;
|
|
@@ -6943,6 +7242,18 @@ var useMaskPreviewLayer = function useMaskPreviewLayer(mapId, mask) {
|
|
|
6943
7242
|
}
|
|
6944
7243
|
}, [dispatch, geojson, layerId, mapId]);
|
|
6945
7244
|
};
|
|
7245
|
+
var useMaskPreviewLayer = function useMaskPreviewLayer(mapId, mask) {
|
|
7246
|
+
var geojson = React.useMemo(function () {
|
|
7247
|
+
return mask ? buildMaskPreviewGeoJSON(mask) : emptyGeoJSON;
|
|
7248
|
+
}, [mask]);
|
|
7249
|
+
useReadonlyFeatureLayer(mapId, getMaskPreviewLayerId(mapId), geojson);
|
|
7250
|
+
};
|
|
7251
|
+
var useClippedResultLayer = function useClippedResultLayer(mapId, clippedGeoJSON) {
|
|
7252
|
+
var geojson = React.useMemo(function () {
|
|
7253
|
+
return clippedGeoJSON ? buildClippedHighlightGeoJSON(clippedGeoJSON) : emptyGeoJSON;
|
|
7254
|
+
}, [clippedGeoJSON]);
|
|
7255
|
+
useReadonlyFeatureLayer(mapId, getClippedResultLayerId(mapId), geojson);
|
|
7256
|
+
};
|
|
6946
7257
|
|
|
6947
7258
|
/* *
|
|
6948
7259
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -7018,27 +7329,129 @@ var useSelectDrawFeature = function useSelectDrawFeature(layerId) {
|
|
|
7018
7329
|
};
|
|
7019
7330
|
|
|
7020
7331
|
var emptyMasks = [];
|
|
7021
|
-
var
|
|
7332
|
+
var SAVED_MASK_ID = 'saved-mask';
|
|
7333
|
+
var useRestoreSavedMask = function useRestoreSavedMask(drawingId, masks, isLoadingMasks, onRestoreMask) {
|
|
7334
|
+
var _useWarningsTranslati = useWarningsTranslation(),
|
|
7335
|
+
t = _useWarningsTranslati.t;
|
|
7336
|
+
var _useDrawingDetails = useDrawingDetails(drawingId),
|
|
7337
|
+
drawingDetails = _useDrawingDetails.data;
|
|
7338
|
+
var restoredDrawingIdRef = React.useRef(undefined);
|
|
7339
|
+
var _React$useState = React.useState(),
|
|
7340
|
+
unmatchedSavedMask = _React$useState[0],
|
|
7341
|
+
setUnmatchedSavedMask = _React$useState[1];
|
|
7342
|
+
React.useEffect(function () {
|
|
7343
|
+
if (!drawingId || restoredDrawingIdRef.current === drawingId || (drawingDetails == null ? void 0 : drawingDetails.id) !== drawingId || isLoadingMasks) {
|
|
7344
|
+
return;
|
|
7345
|
+
}
|
|
7346
|
+
restoredDrawingIdRef.current = drawingId;
|
|
7347
|
+
var savedMask = findMaskForTransformation(masks, drawingDetails.transformation);
|
|
7348
|
+
if (savedMask) {
|
|
7349
|
+
onRestoreMask(savedMask.id);
|
|
7350
|
+
return;
|
|
7351
|
+
}
|
|
7352
|
+
if (drawingDetails.transformation) {
|
|
7353
|
+
setUnmatchedSavedMask({
|
|
7354
|
+
id: SAVED_MASK_ID,
|
|
7355
|
+
objectName: t('drawing-tool-form-mask-saved'),
|
|
7356
|
+
geoJSON: drawingDetails.transformation.mask,
|
|
7357
|
+
lastUpdatedTime: drawingDetails.lastUpdatedTime,
|
|
7358
|
+
scope: 'user'
|
|
7359
|
+
});
|
|
7360
|
+
onRestoreMask(SAVED_MASK_ID);
|
|
7361
|
+
}
|
|
7362
|
+
}, [drawingDetails, drawingId, isLoadingMasks, masks, onRestoreMask, t]);
|
|
7363
|
+
return unmatchedSavedMask;
|
|
7364
|
+
};
|
|
7365
|
+
var useClippedGeoJSON = function useClippedGeoJSON(mapId, geoJSON, mask) {
|
|
7366
|
+
var result = React.useMemo(function () {
|
|
7367
|
+
if (!mask || !geoJSON) {
|
|
7368
|
+
return {};
|
|
7369
|
+
}
|
|
7370
|
+
try {
|
|
7371
|
+
return {
|
|
7372
|
+
clippedGeoJSON: clipGeoJSONWithMask(geoJSON, mask.geoJSON)
|
|
7373
|
+
};
|
|
7374
|
+
} catch (_unused) {
|
|
7375
|
+
return {
|
|
7376
|
+
hasClipError: true
|
|
7377
|
+
};
|
|
7378
|
+
}
|
|
7379
|
+
}, [geoJSON, mask]);
|
|
7380
|
+
useClippedResultLayer(mapId, result.clippedGeoJSON);
|
|
7381
|
+
return result;
|
|
7382
|
+
};
|
|
7383
|
+
var getMaskError = function getMaskError(_ref, geoJSON) {
|
|
7384
|
+
var clippedGeoJSON = _ref.clippedGeoJSON,
|
|
7385
|
+
hasClipError = _ref.hasClipError;
|
|
7386
|
+
if (hasClipError) {
|
|
7387
|
+
return 'drawing-tool-form-mask-clip-error';
|
|
7388
|
+
}
|
|
7389
|
+
var hasDrawnFeatures = !!geoJSON && getDrawnFeatureIndexes(geoJSON).length > 0;
|
|
7390
|
+
return clippedGeoJSON && hasDrawnFeatures && !clippedGeoJSON.features.length ? 'drawing-tool-form-mask-no-overlap' : undefined;
|
|
7391
|
+
};
|
|
7392
|
+
var useHideFillOutsideMask = function useHideFillOutsideMask(layerId, geoJSON, isMaskSelected) {
|
|
7393
|
+
var dispatch = useDispatch();
|
|
7394
|
+
React.useEffect(function () {
|
|
7395
|
+
if (!layerId || !geoJSON) {
|
|
7396
|
+
return;
|
|
7397
|
+
}
|
|
7398
|
+
if (isMaskSelected) {
|
|
7399
|
+
getFeatureIndexesToHideFill(geoJSON).forEach(function (targetFeatureIndex) {
|
|
7400
|
+
var _geoJSON$features$tar, _geoJSON$features$tar2, _properties;
|
|
7401
|
+
dispatch(layerActions.updateFeatureProperties({
|
|
7402
|
+
layerId: layerId,
|
|
7403
|
+
properties: (_properties = {
|
|
7404
|
+
'fill-opacity': 0
|
|
7405
|
+
}, _properties[MASKED_FILL_OPACITY_KEY] = (_geoJSON$features$tar = (_geoJSON$features$tar2 = geoJSON.features[targetFeatureIndex].properties) == null ? void 0 : _geoJSON$features$tar2['fill-opacity']) != null ? _geoJSON$features$tar : null, _properties),
|
|
7406
|
+
targetFeatureIndex: targetFeatureIndex,
|
|
7407
|
+
origin: 'DrawingToolFormConnect'
|
|
7408
|
+
}));
|
|
7409
|
+
});
|
|
7410
|
+
return;
|
|
7411
|
+
}
|
|
7412
|
+
getFeatureIndexesToRestoreFill(geoJSON).forEach(function (targetFeatureIndex) {
|
|
7413
|
+
var _geoJSON$features$tar3, _geoJSON$features$tar4, _properties2;
|
|
7414
|
+
dispatch(layerActions.updateFeatureProperties({
|
|
7415
|
+
layerId: layerId,
|
|
7416
|
+
properties: (_properties2 = {
|
|
7417
|
+
'fill-opacity': (_geoJSON$features$tar3 = (_geoJSON$features$tar4 = geoJSON.features[targetFeatureIndex].properties) == null ? void 0 : _geoJSON$features$tar4[MASKED_FILL_OPACITY_KEY]) != null ? _geoJSON$features$tar3 : undefined
|
|
7418
|
+
}, _properties2[MASKED_FILL_OPACITY_KEY] = undefined, _properties2),
|
|
7419
|
+
targetFeatureIndex: targetFeatureIndex,
|
|
7420
|
+
origin: 'DrawingToolFormConnect'
|
|
7421
|
+
}));
|
|
7422
|
+
});
|
|
7423
|
+
}, [dispatch, geoJSON, isMaskSelected, layerId]);
|
|
7424
|
+
};
|
|
7425
|
+
var useDrawingToolMasks = function useDrawingToolMasks(drawingId, geoJSON) {
|
|
7426
|
+
var _masks$find;
|
|
7022
7427
|
var dispatch = useDispatch();
|
|
7023
7428
|
var _useDrawings = useDrawings({
|
|
7024
7429
|
keywords: 'mask'
|
|
7025
7430
|
}),
|
|
7026
7431
|
_useDrawings$data = _useDrawings.data,
|
|
7027
|
-
|
|
7432
|
+
fetchedMasks = _useDrawings$data === void 0 ? emptyMasks : _useDrawings$data,
|
|
7028
7433
|
isLoading = _useDrawings.isLoading;
|
|
7029
|
-
var _React$useState = React.useState(),
|
|
7030
|
-
selectedMaskId = _React$useState[0],
|
|
7031
|
-
setSelectedMaskId = _React$useState[1];
|
|
7032
7434
|
var _React$useState2 = React.useState(),
|
|
7033
|
-
|
|
7034
|
-
|
|
7435
|
+
selectedMaskId = _React$useState2[0],
|
|
7436
|
+
setSelectedMaskId = _React$useState2[1];
|
|
7437
|
+
var _React$useState3 = React.useState(),
|
|
7438
|
+
hoveredMaskId = _React$useState3[0],
|
|
7439
|
+
setHoveredMaskId = _React$useState3[1];
|
|
7035
7440
|
var mapId = useSelector(function (store) {
|
|
7036
7441
|
return uiSelectors.getDialogMapId(store, drawingDialogType);
|
|
7037
7442
|
});
|
|
7038
|
-
var
|
|
7039
|
-
|
|
7443
|
+
var unmatchedSavedMask = useRestoreSavedMask(drawingId, fetchedMasks, isLoading, setSelectedMaskId);
|
|
7444
|
+
var masks = React.useMemo(function () {
|
|
7445
|
+
return unmatchedSavedMask ? [].concat(fetchedMasks, [unmatchedSavedMask]) : fetchedMasks;
|
|
7446
|
+
}, [fetchedMasks, unmatchedSavedMask]);
|
|
7447
|
+
var selectedMask = masks.find(function (mask) {
|
|
7448
|
+
return mask.id === selectedMaskId;
|
|
7040
7449
|
});
|
|
7450
|
+
var previewMask = (_masks$find = masks.find(function (mask) {
|
|
7451
|
+
return mask.id === hoveredMaskId;
|
|
7452
|
+
})) != null ? _masks$find : selectedMask;
|
|
7041
7453
|
useMaskPreviewLayer(mapId, previewMask);
|
|
7454
|
+
var clipResult = useClippedGeoJSON(mapId, geoJSON, selectedMask);
|
|
7042
7455
|
var onSelectMask = React.useCallback(function (maskId) {
|
|
7043
7456
|
setSelectedMaskId(maskId);
|
|
7044
7457
|
dispatch(warningsDrawingsActions.setFormDirty({
|
|
@@ -7049,12 +7462,15 @@ var useDrawingToolMasks = function useDrawingToolMasks() {
|
|
|
7049
7462
|
return {
|
|
7050
7463
|
masks: masks,
|
|
7051
7464
|
isLoading: isLoading,
|
|
7465
|
+
selectedMask: selectedMask,
|
|
7052
7466
|
selectedMaskId: selectedMaskId,
|
|
7467
|
+
maskError: getMaskError(clipResult, geoJSON),
|
|
7053
7468
|
onSelectMask: onSelectMask,
|
|
7054
7469
|
onHoverMask: setHoveredMaskId
|
|
7055
7470
|
};
|
|
7056
7471
|
};
|
|
7057
7472
|
var DrawingToolFormConnect = function DrawingToolFormConnect() {
|
|
7473
|
+
var _drawing$id;
|
|
7058
7474
|
var dispatch = useDispatch();
|
|
7059
7475
|
var _useMutateSaveOrUpdat = useMutateSaveOrUpdateDrawing(),
|
|
7060
7476
|
saveOrUpdateDrawing = _useMutateSaveOrUpdat.mutate,
|
|
@@ -7081,29 +7497,65 @@ var DrawingToolFormConnect = function DrawingToolFormConnect() {
|
|
|
7081
7497
|
return getWarningFormDirty(store, drawingDialogType);
|
|
7082
7498
|
});
|
|
7083
7499
|
usePreventBrowserClose(isFormDirty || isLayerInEditMode);
|
|
7084
|
-
var _useDrawingToolMasks = useDrawingToolMasks(),
|
|
7500
|
+
var _useDrawingToolMasks = useDrawingToolMasks((_drawing$id = drawing == null ? void 0 : drawing.id) != null ? _drawing$id : '', layerFeatureGeoJSON),
|
|
7085
7501
|
masks = _useDrawingToolMasks.masks,
|
|
7086
7502
|
isLoadingMasks = _useDrawingToolMasks.isLoading,
|
|
7503
|
+
selectedMask = _useDrawingToolMasks.selectedMask,
|
|
7087
7504
|
selectedMaskId = _useDrawingToolMasks.selectedMaskId,
|
|
7505
|
+
maskError = _useDrawingToolMasks.maskError,
|
|
7088
7506
|
onSelectMask = _useDrawingToolMasks.onSelectMask,
|
|
7089
7507
|
onHoverMask = _useDrawingToolMasks.onHoverMask;
|
|
7508
|
+
useHideFillOutsideMask(drawTool == null ? void 0 : drawTool.geoJSONLayerId, layerFeatureGeoJSON, !!selectedMask);
|
|
7509
|
+
var formGeoJSONRef = React.useRef(undefined);
|
|
7510
|
+
var formGeoJSON = React.useMemo(function () {
|
|
7511
|
+
var restoredGeoJSON = layerFeatureGeoJSON && restoreMaskedFill(layerFeatureGeoJSON);
|
|
7512
|
+
if (!isEqual(formGeoJSONRef.current, restoredGeoJSON)) {
|
|
7513
|
+
formGeoJSONRef.current = restoredGeoJSON;
|
|
7514
|
+
}
|
|
7515
|
+
return formGeoJSONRef.current;
|
|
7516
|
+
}, [layerFeatureGeoJSON]);
|
|
7517
|
+
var geoJSONProperties = React.useMemo(function () {
|
|
7518
|
+
return restoreMaskedFillProperties(featureLayerGeoJSONProperties);
|
|
7519
|
+
}, [featureLayerGeoJSONProperties]);
|
|
7090
7520
|
var onSubmitForm = React.useCallback(function (formValues) {
|
|
7521
|
+
var original = formValues.geoJSON;
|
|
7091
7522
|
saveOrUpdateDrawing({
|
|
7092
7523
|
id: drawing == null ? void 0 : drawing.id,
|
|
7093
|
-
data: {
|
|
7094
|
-
geoJSON:
|
|
7524
|
+
data: Object.assign({
|
|
7525
|
+
geoJSON: selectedMask ? clipGeoJSONWithMask(original, selectedMask.geoJSON) : original,
|
|
7095
7526
|
objectName: formValues.objectName,
|
|
7096
7527
|
scope: 'user'
|
|
7097
|
-
}
|
|
7528
|
+
}, selectedMask && {
|
|
7529
|
+
transformation: {
|
|
7530
|
+
mask: selectedMask.geoJSON,
|
|
7531
|
+
original: original
|
|
7532
|
+
}
|
|
7533
|
+
})
|
|
7098
7534
|
});
|
|
7099
|
-
}, [drawing == null ? void 0 : drawing.id, saveOrUpdateDrawing]);
|
|
7535
|
+
}, [drawing == null ? void 0 : drawing.id, saveOrUpdateDrawing, selectedMask]);
|
|
7100
7536
|
var onChangeGeoJSONProperties = React.useCallback(function (properties) {
|
|
7537
|
+
var layerId = drawTool == null ? void 0 : drawTool.geoJSONLayerId;
|
|
7101
7538
|
dispatch(layerActions.updateFeatureProperties({
|
|
7102
|
-
layerId:
|
|
7539
|
+
layerId: layerId,
|
|
7103
7540
|
properties: properties,
|
|
7104
7541
|
origin: 'DrawingToolFormConnect'
|
|
7105
7542
|
}));
|
|
7106
|
-
|
|
7543
|
+
var fillOpacity = properties == null ? void 0 : properties['fill-opacity'];
|
|
7544
|
+
if (!selectedMask || typeof fillOpacity !== 'number') {
|
|
7545
|
+
return;
|
|
7546
|
+
}
|
|
7547
|
+
getDrawnFeatureIndexes(layerFeatureGeoJSON != null ? layerFeatureGeoJSON : emptyGeoJSON).forEach(function (targetFeatureIndex) {
|
|
7548
|
+
var _properties3;
|
|
7549
|
+
dispatch(layerActions.updateFeatureProperties({
|
|
7550
|
+
layerId: layerId,
|
|
7551
|
+
properties: (_properties3 = {
|
|
7552
|
+
'fill-opacity': 0
|
|
7553
|
+
}, _properties3[MASKED_FILL_OPACITY_KEY] = fillOpacity, _properties3),
|
|
7554
|
+
targetFeatureIndex: targetFeatureIndex,
|
|
7555
|
+
origin: 'DrawingToolFormConnect'
|
|
7556
|
+
}));
|
|
7557
|
+
});
|
|
7558
|
+
}, [dispatch, drawTool == null ? void 0 : drawTool.geoJSONLayerId, layerFeatureGeoJSON, selectedMask]);
|
|
7107
7559
|
var onChangeObjectName = React.useCallback(function (featureId, objectName) {
|
|
7108
7560
|
var _layerFeatureGeoJSON$;
|
|
7109
7561
|
var featureIndex = ((_layerFeatureGeoJSON$ = layerFeatureGeoJSON == null ? void 0 : layerFeatureGeoJSON.features) != null ? _layerFeatureGeoJSON$ : []).findIndex(function (feature) {
|
|
@@ -7167,12 +7619,13 @@ var DrawingToolFormConnect = function DrawingToolFormConnect() {
|
|
|
7167
7619
|
dialogError: error == null ? void 0 : error.message,
|
|
7168
7620
|
drawModes: drawTool == null ? void 0 : drawTool.drawModes,
|
|
7169
7621
|
drawingName: drawing == null ? void 0 : drawing.objectName,
|
|
7170
|
-
geoJSON:
|
|
7171
|
-
geoJSONProperties:
|
|
7622
|
+
geoJSON: formGeoJSON,
|
|
7623
|
+
geoJSONProperties: geoJSONProperties,
|
|
7172
7624
|
id: drawing == null ? void 0 : drawing.id,
|
|
7173
7625
|
isInEditMode: isLayerInEditMode,
|
|
7174
7626
|
isLoading: isPending,
|
|
7175
7627
|
isLoadingMasks: isLoadingMasks,
|
|
7628
|
+
maskError: maskError,
|
|
7176
7629
|
masks: masks,
|
|
7177
7630
|
onChangeDrawMode: onChangeDrawMode,
|
|
7178
7631
|
onChangeName: onChangeName,
|
|
@@ -26,6 +26,7 @@ export interface DrawingToolFormComponentProps {
|
|
|
26
26
|
geoJSON: FeatureCollection<Geometry, GeoJsonProperties> | undefined;
|
|
27
27
|
masks?: DrawingListItem[];
|
|
28
28
|
isLoadingMasks?: boolean;
|
|
29
|
+
maskError?: string;
|
|
29
30
|
selectedMaskId?: string;
|
|
30
31
|
onSelectMask?: (maskId?: string) => void;
|
|
31
32
|
onHoverMask?: (maskId?: string) => void;
|
|
@@ -37,6 +37,7 @@ export interface DrawingToolFormContentsProps {
|
|
|
37
37
|
geoJSONProperties?: GeoJSON.GeoJsonProperties;
|
|
38
38
|
masks: DrawingListItem[];
|
|
39
39
|
isLoadingMasks: boolean;
|
|
40
|
+
maskError?: string;
|
|
40
41
|
selectedMaskId?: string;
|
|
41
42
|
onSelectMask: (maskId?: string) => void;
|
|
42
43
|
onHoverMask: (maskId?: string) => void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Feature, FeatureCollection, MultiPolygon, Polygon } from 'geojson';
|
|
2
|
+
import type { DrawingListItem, DrawingTransformation } from '../../store/warningsDrawings/types';
|
|
3
|
+
type MaskPolygon = Feature<Polygon | MultiPolygon>;
|
|
4
|
+
export declare const CLIPPED_RESULT_FILL_OPACITY = 0.4;
|
|
5
|
+
export declare const MASKED_FILL_OPACITY_KEY = "maskedFillOpacity";
|
|
6
|
+
export declare const getDrawnFeatureIndexes: (geoJSON: FeatureCollection) => number[];
|
|
7
|
+
export declare const getFeatureIndexesToHideFill: (geoJSON: FeatureCollection) => number[];
|
|
8
|
+
export declare const getFeatureIndexesToRestoreFill: (geoJSON: FeatureCollection) => number[];
|
|
9
|
+
export declare const restoreMaskedFillProperties: (properties: GeoJSON.GeoJsonProperties) => GeoJSON.GeoJsonProperties;
|
|
10
|
+
export declare const restoreMaskedFill: (geoJSON: FeatureCollection) => FeatureCollection;
|
|
11
|
+
export declare const getMaskPolygon: (mask: FeatureCollection) => MaskPolygon | null;
|
|
12
|
+
export declare const clipGeoJSONWithMask: (geoJSON: FeatureCollection, mask: FeatureCollection) => FeatureCollection;
|
|
13
|
+
export declare const findMaskForTransformation: (masks: DrawingListItem[], transformation?: DrawingTransformation) => DrawingListItem | undefined;
|
|
14
|
+
export declare const buildClippedHighlightGeoJSON: (clipped: FeatureCollection) => FeatureCollection;
|
|
15
|
+
export {};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { DrawingListItem } from '../../store/warningsDrawings/types';
|
|
2
|
-
export declare const MASK_PREVIEW_FILL_OPACITY = 0
|
|
2
|
+
export declare const MASK_PREVIEW_FILL_OPACITY = 0;
|
|
3
3
|
export declare const getMaskPreviewLayerId: (mapId: string) => string;
|
|
4
|
+
export declare const getClippedResultLayerId: (mapId: string) => string;
|
|
4
5
|
export declare const buildMaskPreviewGeoJSON: (mask: DrawingListItem) => GeoJSON.FeatureCollection;
|
|
5
6
|
export declare const useMaskPreviewLayer: (mapId: string, mask?: DrawingListItem) => void;
|
|
7
|
+
export declare const useClippedResultLayer: (mapId: string, clippedGeoJSON?: GeoJSON.FeatureCollection) => void;
|
|
@@ -12,10 +12,15 @@ export interface BaseDrawingListItem {
|
|
|
12
12
|
objectName: string;
|
|
13
13
|
lastUpdatedTime: string;
|
|
14
14
|
}
|
|
15
|
+
export interface DrawingTransformation {
|
|
16
|
+
mask: GeoJSON.FeatureCollection;
|
|
17
|
+
original: GeoJSON.FeatureCollection;
|
|
18
|
+
}
|
|
15
19
|
export interface DrawingListItem extends BaseDrawingListItem {
|
|
16
20
|
scope: DrawingScope;
|
|
17
21
|
geoJSON: GeoJSON.FeatureCollection;
|
|
18
22
|
keywords?: string;
|
|
23
|
+
transformation?: DrawingTransformation;
|
|
19
24
|
}
|
|
20
25
|
export interface AreaListItem extends BaseDrawingListItem {
|
|
21
26
|
scope: DrawingScope;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeoweb/warnings",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "20.0.0",
|
|
4
4
|
"description": "GeoWeb warinings library for the opengeoweb project",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -20,24 +20,24 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@opengeoweb/api": "
|
|
24
|
-
"@opengeoweb/shared": "
|
|
25
|
-
"@opengeoweb/store": "
|
|
26
|
-
"@opengeoweb/webmap-react": "
|
|
23
|
+
"@opengeoweb/api": "20.0.0",
|
|
24
|
+
"@opengeoweb/shared": "20.0.0",
|
|
25
|
+
"@opengeoweb/store": "20.0.0",
|
|
26
|
+
"@opengeoweb/webmap-react": "20.0.0",
|
|
27
27
|
"@tanstack/react-query": "^5.85.5",
|
|
28
28
|
"react-redux": "^9.2.0",
|
|
29
|
-
"@opengeoweb/theme": "
|
|
30
|
-
"@opengeoweb/form-fields": "
|
|
29
|
+
"@opengeoweb/theme": "20.0.0",
|
|
30
|
+
"@opengeoweb/form-fields": "20.0.0",
|
|
31
31
|
"react-hook-form": "^7.50.1",
|
|
32
32
|
"lodash": "^4.18.1",
|
|
33
33
|
"@reduxjs/toolkit": "^2.6.1",
|
|
34
|
-
"@opengeoweb/snackbar": "
|
|
34
|
+
"@opengeoweb/snackbar": "20.0.0",
|
|
35
35
|
"react-window": "^2.2.6",
|
|
36
36
|
"axios": "^1.18.0",
|
|
37
|
-
"@opengeoweb/core": "
|
|
38
|
-
"@opengeoweb/webmap": "
|
|
39
|
-
"@opengeoweb/authentication": "
|
|
40
|
-
"@opengeoweb/sigmet-airmet": "
|
|
37
|
+
"@opengeoweb/core": "20.0.0",
|
|
38
|
+
"@opengeoweb/webmap": "20.0.0",
|
|
39
|
+
"@opengeoweb/authentication": "20.0.0",
|
|
40
|
+
"@opengeoweb/sigmet-airmet": "20.0.0",
|
|
41
41
|
"react-i18next": "^15.1.1",
|
|
42
42
|
"i18next": "^25.0.1",
|
|
43
43
|
"@mui/material": "^9.0.1",
|