@collabdt/core 0.3.2 → 0.3.3
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/core/components/ui/Comments/CollapsibleCommentItem.js.map +1 -1
- package/dist/core/components/ui/Comments/Comment.js.map +1 -1
- package/dist/core/components/ui/Comments/CommentActionButtons.d.ts +5 -1
- package/dist/core/components/ui/Comments/CommentActionButtons.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/CommentActionButtons.js +37 -9
- package/dist/core/components/ui/Comments/CommentActionButtons.js.map +1 -1
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts +1 -2
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js +66 -94
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js.map +1 -1
- package/dist/core/components/ui/Sensors/Sensor.d.ts +16 -3
- package/dist/core/components/ui/Sensors/Sensor.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/Sensor.js +76 -37
- package/dist/core/components/ui/Sensors/Sensor.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorChart.d.ts +12 -2
- package/dist/core/components/ui/Sensors/SensorChart.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorChart.js +49 -12
- package/dist/core/components/ui/Sensors/SensorChart.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorDetailDialog.d.ts +9 -0
- package/dist/core/components/ui/Sensors/SensorDetailDialog.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/SensorDetailDialog.js +128 -0
- package/dist/core/components/ui/Sensors/SensorDetailDialog.js.map +1 -0
- package/dist/core/components/ui/Sensors/SensorInput.d.ts +6 -1
- package/dist/core/components/ui/Sensors/SensorInput.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorInput.js +94 -8
- package/dist/core/components/ui/Sensors/SensorInput.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.d.ts +3 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.js +4 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.d.ts +1 -3
- package/dist/core/components/ui/Sensors/SensorsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.js +33 -8
- package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
- package/dist/core/components/ui/Sensors/TimeZoneSelect.d.ts +7 -0
- package/dist/core/components/ui/Sensors/TimeZoneSelect.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/TimeZoneSelect.js +56 -0
- package/dist/core/components/ui/Sensors/TimeZoneSelect.js.map +1 -0
- package/dist/core/components/ui/Sensors/sensorData.d.ts +42 -0
- package/dist/core/components/ui/Sensors/sensorData.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/sensorData.js +118 -0
- package/dist/core/components/ui/Sensors/sensorData.js.map +1 -0
- package/dist/core/components/ui/Sensors/sensorRange.d.ts +24 -0
- package/dist/core/components/ui/Sensors/sensorRange.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/sensorRange.js +34 -0
- package/dist/core/components/ui/Sensors/sensorRange.js.map +1 -0
- package/dist/core/components/ui/Sensors/useSensorSeries.d.ts +15 -0
- package/dist/core/components/ui/Sensors/useSensorSeries.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/useSensorSeries.js +63 -0
- package/dist/core/components/ui/Sensors/useSensorSeries.js.map +1 -0
- package/dist/core/components/viewers/Viewer.js +1 -1
- package/dist/core/components/viewers/Viewer.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.d.ts +1 -3
- package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.js +2 -2
- package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/index.js +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts +1 -2
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js +25 -2
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.d.ts +1 -22
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.js +2 -105
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.d.ts +8 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js +15 -3
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.d.ts +2 -23
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.js +2 -24
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.d.ts +33 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.d.ts.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.js +90 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.js.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.d.ts +7 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.js +26 -230
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts +7 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js +39 -11
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.d.ts +1 -2
- package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.js +2 -2
- package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/index.d.ts +1 -2
- package/dist/core/components/viewers/map/src/MapLayers/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/index.js +2 -2
- package/dist/core/components/viewers/map/src/MapLayers/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts +1 -3
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js +74 -39
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/index.js +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.d.ts +1 -3
- package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.js +2 -2
- package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.js.map +1 -1
- package/dist/core/components/viewers/shared/markers/BimMarkerCluster.d.ts +19 -0
- package/dist/core/components/viewers/shared/markers/BimMarkerCluster.d.ts.map +1 -0
- package/dist/core/components/viewers/shared/markers/BimMarkerCluster.js +108 -0
- package/dist/core/components/viewers/shared/markers/BimMarkerCluster.js.map +1 -0
- package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.d.ts +24 -0
- package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.d.ts.map +1 -0
- package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.js +27 -0
- package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.js.map +1 -0
- package/dist/core/components/viewers/shared/markers/types.d.ts +66 -0
- package/dist/core/components/viewers/shared/markers/types.d.ts.map +1 -0
- package/dist/core/components/viewers/shared/markers/types.js +1 -0
- package/dist/core/components/viewers/shared/markers/types.js.map +1 -0
- package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.d.ts +22 -0
- package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.d.ts.map +1 -0
- package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.js +233 -0
- package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.js.map +1 -0
- package/dist/core/hooks/ui/useResizableSidebarWidth.js.map +1 -1
- package/dist/core/i18n/messages/en.json +5 -1
- package/dist/core/i18n/messages/es.json +5 -1
- package/dist/core/i18n/messages/fr.json +5 -1
- package/dist/core/store/AppConfig/context.d.ts.map +1 -1
- package/dist/core/store/AppConfig/context.js +4 -1
- package/dist/core/store/AppConfig/context.js.map +1 -1
- package/dist/core/store/AppConfig/reducer.d.ts +10 -0
- package/dist/core/store/AppConfig/reducer.d.ts.map +1 -1
- package/dist/core/store/AppConfig/reducer.js +10 -0
- package/dist/core/store/AppConfig/reducer.js.map +1 -1
- package/dist/core/store/Menus/context.d.ts.map +1 -1
- package/dist/core/store/Menus/context.js +5 -2
- package/dist/core/store/Menus/context.js.map +1 -1
- package/dist/core/store/Menus/reducer.d.ts +45 -1
- package/dist/core/store/Menus/reducer.d.ts.map +1 -1
- package/dist/core/store/Menus/reducer.js +21 -3
- package/dist/core/store/Menus/reducer.js.map +1 -1
- package/dist/core/utils/timeUtils.d.ts +24 -1
- package/dist/core/utils/timeUtils.d.ts.map +1 -1
- package/dist/core/utils/timeUtils.js +52 -3
- package/dist/core/utils/timeUtils.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../../../src/core/store/Menus/reducer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,eAAe,GAAI,SAAS,GAAG,UAAU,CAAA;AAE1F,wFAAwF;AACxF,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;IACxB,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,UAAU,UAAU;IAClB,aAAa,EAAE,WAAW,CAAA;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,cAAc,CAAA;IAC3B,uBAAuB,EAAE,WAAW,EAAE,CAAA;IACtC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,uFAAuF;IACvF,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,iGAAiG;IACjG,cAAc,EAAE,MAAM,CAAA;IACtB,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAA;IACjD,sBAAsB,EAAE,WAAW,EAAE,CAAA;IACrC,kBAAkB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IAC1D,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IACzD,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../../../src/core/store/Menus/reducer.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@ var __spreadValues = (a, b) => {
|
|
|
18
18
|
};
|
|
19
19
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
20
|
const MenusReducer = (state, action) => {
|
|
21
|
-
var _a, _b, _c, _d;
|
|
21
|
+
var _a, _b, _c, _d, _e, _f;
|
|
22
22
|
switch (action.type) {
|
|
23
23
|
case "SET_VIEWER":
|
|
24
24
|
return __spreadProps(__spreadValues({}, state), {
|
|
@@ -77,6 +77,24 @@ const MenusReducer = (state, action) => {
|
|
|
77
77
|
return __spreadProps(__spreadValues({}, state), {
|
|
78
78
|
currentSensorTypeId: action.payload.currentSensorTypeId
|
|
79
79
|
});
|
|
80
|
+
case "SET_FOCUSED_SENSOR_ID":
|
|
81
|
+
return __spreadProps(__spreadValues({}, state), {
|
|
82
|
+
focusedSensorId: action.payload.sensorId,
|
|
83
|
+
sensorFocusRequestId: state.sensorFocusRequestId + 1
|
|
84
|
+
});
|
|
85
|
+
case "REQUEST_SENSOR_ACTION":
|
|
86
|
+
return __spreadProps(__spreadValues({}, state), {
|
|
87
|
+
pendingSensorAction: {
|
|
88
|
+
sensorId: action.payload.sensorId,
|
|
89
|
+
action: "edit",
|
|
90
|
+
requestId: ((_d = (_c = state.pendingSensorAction) == null ? void 0 : _c.requestId) != null ? _d : 0) + 1
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
case "CLEAR_PENDING_SENSOR_ACTION":
|
|
94
|
+
if (state.pendingSensorAction === null) return state;
|
|
95
|
+
return __spreadProps(__spreadValues({}, state), {
|
|
96
|
+
pendingSensorAction: null
|
|
97
|
+
});
|
|
80
98
|
case "HIDE_ALL_SENSORS_IN_VIEWER":
|
|
81
99
|
const sensorViewerToHide = action.payload.viewer;
|
|
82
100
|
if (!sensorViewerToHide) return state;
|
|
@@ -100,7 +118,7 @@ const MenusReducer = (state, action) => {
|
|
|
100
118
|
case "TOGGLE_SENSOR_TYPE_VISIBILITY":
|
|
101
119
|
const { viewer: toggleViewer, sensorTypeId, force } = action.payload;
|
|
102
120
|
if (!toggleViewer || !sensorTypeId) return state;
|
|
103
|
-
const currentTypesForViewer = ((
|
|
121
|
+
const currentTypesForViewer = ((_e = state.visibleSensorTypes) == null ? void 0 : _e[toggleViewer]) || [];
|
|
104
122
|
const isCurrentlyVisible = currentTypesForViewer.includes(sensorTypeId);
|
|
105
123
|
if (force && isCurrentlyVisible) return state;
|
|
106
124
|
return __spreadProps(__spreadValues({}, state), {
|
|
@@ -111,7 +129,7 @@ const MenusReducer = (state, action) => {
|
|
|
111
129
|
case "TOGGLE_SENSOR_TAG_VISIBILITY":
|
|
112
130
|
const { viewer: toggleTagViewer, sensorTag, force: forceTag } = action.payload;
|
|
113
131
|
if (!toggleTagViewer || !sensorTag) return state;
|
|
114
|
-
const currentTagsForViewer = ((
|
|
132
|
+
const currentTagsForViewer = ((_f = state.visibleSensorTags) == null ? void 0 : _f[toggleTagViewer]) || [];
|
|
115
133
|
const isTagCurrentlyVisible = currentTagsForViewer.includes(sensorTag);
|
|
116
134
|
if (forceTag && isTagCurrentlyVisible) return state;
|
|
117
135
|
return __spreadProps(__spreadValues({}, state), {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/store/Menus/reducer.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport type { ViewerNames } from '../../types/dbTypes'\r\nimport type { ActionMap } from '../ActionMap'\r\n\r\nexport type SidebarTabType = 'file' | 'layers' | 'communication' | 'sensors' | 'settings'\r\n\r\n/** Request from a viewer marker to open a comment's editor/reply box in the sidebar. */\r\nexport type CommentActionRequest = {\r\n commentId: number\r\n action: 'edit' | 'reply'\r\n /** Monotonic id so the same request fires again even if the target is unchanged. */\r\n requestId: number\r\n}\r\n\r\ninterface MenusTypes {\r\n currentViewer: ViewerNames\r\n rowsPerPage: number\r\n selectedTab: SidebarTabType\r\n commentsVisibleInViewer: ViewerNames[]\r\n currentCommentId: number | null\r\n /** Comment double-clicked to zoom/focus. Drives the thick focus ring + camera move. */\r\n focusedCommentId: number | null\r\n /** Monotonic counter bumped on every focus dispatch so re-focusing the same comment re-zooms. */\r\n focusRequestId: number\r\n pendingCommentAction: CommentActionRequest | null\r\n sensorsVisibleInViewer: ViewerNames[]\r\n visibleSensorTypes: Partial<Record<ViewerNames, number[]>>\r\n visibleSensorTags: Partial<Record<ViewerNames, string[]>>\r\n currentSensorId: number | null\r\n currentSensorTypeId: number | null\r\n}\r\n\r\nexport type MenusState = MenusTypes\r\n\r\nexport type MenusPayload = {\r\n ['SET_VIEWER']: Pick<MenusTypes, 'currentViewer'>\r\n ['SET_PAGINATION_ROWS_PER_PAGE']: Pick<MenusTypes, 'rowsPerPage'>\r\n ['SET_SIDEBAR_SELECTED_TAB']: Pick<MenusTypes, 'selectedTab'>\r\n ['SHOW_COMMENTS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['HIDE_COMMENTS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['SET_CURRENT_COMMENT_ID']: {commentId: number | null}\r\n ['SET_FOCUSED_COMMENT_ID']: {commentId: number | null}\r\n ['REQUEST_COMMENT_ACTION']: {commentId: number; action: 'edit' | 'reply'}\r\n ['CLEAR_PENDING_COMMENT_ACTION']: undefined\r\n ['TOGGLE_SENSOR_TYPE_VISIBILITY']: { viewer: ViewerNames; sensorTypeId: number; force?: boolean }\r\n ['TOGGLE_SENSOR_TAG_VISIBILITY']: { viewer: ViewerNames; sensorTag: string; force?: boolean }\r\n ['SHOW_ALL_SENSOR_IN_VIEWER']: {viewer: ViewerNames}\r\n ['HIDE_ALL_SENSORS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['HIDE_ALL_SENSOR_TAGS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['SET_CURRENT_SENSOR_ID']: Pick<MenusTypes, 'currentSensorId'>\r\n ['SET_CURRENT_SENSOR_TYPE_ID']: Pick<MenusTypes, 'currentSensorTypeId'>\r\n}\r\n\r\nexport type MenusActions\r\n = ActionMap<MenusPayload>[keyof ActionMap<MenusPayload>]\r\n\r\nexport const MenusReducer = (state: MenusState, action: MenusActions) => {\r\n switch (action.type) {\r\n case 'SET_VIEWER':\r\n return {\r\n ...state,\r\n currentViewer: action.payload.currentViewer,\r\n }\r\n case 'SET_PAGINATION_ROWS_PER_PAGE':\r\n return {\r\n ...state,\r\n rowsPerPage: action.payload.rowsPerPage,\r\n }\r\n case 'SET_SIDEBAR_SELECTED_TAB':\r\n return {\r\n ...state,\r\n selectedTab: action.payload.selectedTab,\r\n }\r\n case 'SHOW_COMMENTS_IN_VIEWER':\r\n const viewerToShow = action.payload.viewer\r\n if (!viewerToShow) return state\r\n const commentsCurrentlyVisible = state.commentsVisibleInViewer || []\r\n return {\r\n ...state,\r\n commentsVisibleInViewer: commentsCurrentlyVisible.includes(viewerToShow)\r\n ? commentsCurrentlyVisible\r\n : [...commentsCurrentlyVisible, viewerToShow],\r\n }\r\n case 'HIDE_COMMENTS_IN_VIEWER':\r\n const viewerToHide = action.payload.viewer\r\n if (!viewerToHide) return state\r\n return {\r\n ...state,\r\n commentsVisibleInViewer: (state.commentsVisibleInViewer || []).filter(\r\n v => v !== viewerToHide\r\n ),\r\n }\r\n case 'SET_CURRENT_COMMENT_ID':\r\n return {\r\n ...state,\r\n currentCommentId: action.payload.commentId,\r\n }\r\n case 'SET_FOCUSED_COMMENT_ID':\r\n return {\r\n ...state,\r\n focusedCommentId: action.payload.commentId,\r\n focusRequestId: state.focusRequestId + 1,\r\n }\r\n case 'REQUEST_COMMENT_ACTION':\r\n return {\r\n ...state,\r\n pendingCommentAction: {\r\n commentId: action.payload.commentId,\r\n action: action.payload.action,\r\n requestId: (state.pendingCommentAction?.requestId ?? 0) + 1,\r\n },\r\n }\r\n case 'CLEAR_PENDING_COMMENT_ACTION':\r\n if (state.pendingCommentAction === null) return state\r\n return {\r\n ...state,\r\n pendingCommentAction: null,\r\n }\r\n case 'SET_CURRENT_SENSOR_ID':\r\n return {\r\n ...state,\r\n currentSensorId: action.payload.currentSensorId,\r\n }\r\n case 'SET_CURRENT_SENSOR_TYPE_ID':\r\n return {\r\n ...state,\r\n currentSensorTypeId: action.payload.currentSensorTypeId,\r\n }\r\n case 'HIDE_ALL_SENSORS_IN_VIEWER':\r\n const sensorViewerToHide = action.payload.viewer\r\n if (!sensorViewerToHide) return state\r\n return {\r\n ...state,\r\n sensorsVisibleInViewer: (state.sensorsVisibleInViewer || []).filter(\r\n v => v !== sensorViewerToHide\r\n ),\r\n // Also hide all sensor types for this viewer\r\n visibleSensorTypes: {\r\n ...state.visibleSensorTypes,\r\n [sensorViewerToHide]: [],\r\n },\r\n }\r\n case 'HIDE_ALL_SENSOR_TAGS_IN_VIEWER':\r\n const tagViewerToHide = action.payload.viewer\r\n if (!tagViewerToHide) return state\r\n return {\r\n ...state,\r\n visibleSensorTags: {\r\n ...state.visibleSensorTags,\r\n [tagViewerToHide]: [],\r\n },\r\n }\r\n case 'TOGGLE_SENSOR_TYPE_VISIBILITY':\r\n const { viewer: toggleViewer, sensorTypeId, force } = action.payload\r\n if (!toggleViewer || !sensorTypeId) return state\r\n const currentTypesForViewer = state.visibleSensorTypes?.[toggleViewer] || []\r\n const isCurrentlyVisible = currentTypesForViewer.includes(sensorTypeId)\r\n // force=true → only show (idempotent); force=false/undefined → toggle\r\n if (force && isCurrentlyVisible) return state\r\n return {\r\n ...state,\r\n visibleSensorTypes: {\r\n ...state.visibleSensorTypes,\r\n [toggleViewer]: (force || !isCurrentlyVisible)\r\n ? [...currentTypesForViewer, sensorTypeId]\r\n : currentTypesForViewer.filter(t => t !== sensorTypeId),\r\n },\r\n }\r\n case 'TOGGLE_SENSOR_TAG_VISIBILITY':\r\n const { viewer: toggleTagViewer, sensorTag, force: forceTag } = action.payload\r\n if (!toggleTagViewer || !sensorTag) return state\r\n const currentTagsForViewer = state.visibleSensorTags?.[toggleTagViewer] || []\r\n const isTagCurrentlyVisible = currentTagsForViewer.includes(sensorTag)\r\n if (forceTag && isTagCurrentlyVisible) return state\r\n return {\r\n ...state,\r\n visibleSensorTags: {\r\n ...state.visibleSensorTags,\r\n [toggleTagViewer]: (forceTag || !isTagCurrentlyVisible)\r\n ? [...currentTagsForViewer, sensorTag]\r\n : currentTagsForViewer.filter(t => t !== sensorTag),\r\n },\r\n }\r\n\r\n case 'SHOW_ALL_SENSOR_IN_VIEWER':\r\n const showAllViewer = action.payload.viewer\r\n if (!showAllViewer) return state\r\n // This is called when opening the add sensor tool - we don't know all types yet\r\n // So we just ensure the viewer is in sensorsVisibleInViewer\r\n return state\r\n default:\r\n return state\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/store/Menus/reducer.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport type { ViewerNames } from '../../types/dbTypes'\r\nimport type { ActionMap } from '../ActionMap'\r\n\r\nexport type SidebarTabType = 'file' | 'layers' | 'communication' | 'sensors' | 'settings'\r\n\r\n/** Request from a viewer marker to open a comment's editor/reply box in the sidebar. */\r\nexport type CommentActionRequest = {\r\n commentId: number\r\n action: 'edit' | 'reply'\r\n /** Monotonic id so the same request fires again even if the target is unchanged. */\r\n requestId: number\r\n}\r\n\r\n/** Request from a viewer marker to open a sensor's editor in the sidebar. */\r\nexport type SensorActionRequest = {\r\n sensorId: number\r\n action: 'edit'\r\n /** Monotonic id so the same request fires again even if the target is unchanged. */\r\n requestId: number\r\n}\r\n\r\ninterface MenusTypes {\r\n currentViewer: ViewerNames\r\n rowsPerPage: number\r\n selectedTab: SidebarTabType\r\n commentsVisibleInViewer: ViewerNames[]\r\n currentCommentId: number | null\r\n /** Comment double-clicked to zoom/focus. Drives the thick focus ring + camera move. */\r\n focusedCommentId: number | null\r\n /** Monotonic counter bumped on every focus dispatch so re-focusing the same comment re-zooms. */\r\n focusRequestId: number\r\n pendingCommentAction: CommentActionRequest | null\r\n sensorsVisibleInViewer: ViewerNames[]\r\n visibleSensorTypes: Partial<Record<ViewerNames, number[]>>\r\n visibleSensorTags: Partial<Record<ViewerNames, string[]>>\r\n currentSensorId: number | null\r\n currentSensorTypeId: number | null\r\n /** Sensor double-clicked to zoom/focus. Drives the thick focus ring + camera move. */\r\n focusedSensorId: number | null\r\n /** Monotonic counter bumped on every sensor focus dispatch so re-focusing re-zooms. */\r\n sensorFocusRequestId: number\r\n pendingSensorAction: SensorActionRequest | null\r\n}\r\n\r\nexport type MenusState = MenusTypes\r\n\r\nexport type MenusPayload = {\r\n ['SET_VIEWER']: Pick<MenusTypes, 'currentViewer'>\r\n ['SET_PAGINATION_ROWS_PER_PAGE']: Pick<MenusTypes, 'rowsPerPage'>\r\n ['SET_SIDEBAR_SELECTED_TAB']: Pick<MenusTypes, 'selectedTab'>\r\n ['SHOW_COMMENTS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['HIDE_COMMENTS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['SET_CURRENT_COMMENT_ID']: {commentId: number | null}\r\n ['SET_FOCUSED_COMMENT_ID']: {commentId: number | null}\r\n ['REQUEST_COMMENT_ACTION']: {commentId: number; action: 'edit' | 'reply'}\r\n ['CLEAR_PENDING_COMMENT_ACTION']: undefined\r\n ['TOGGLE_SENSOR_TYPE_VISIBILITY']: { viewer: ViewerNames; sensorTypeId: number; force?: boolean }\r\n ['TOGGLE_SENSOR_TAG_VISIBILITY']: { viewer: ViewerNames; sensorTag: string; force?: boolean }\r\n ['SHOW_ALL_SENSOR_IN_VIEWER']: {viewer: ViewerNames}\r\n ['HIDE_ALL_SENSORS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['HIDE_ALL_SENSOR_TAGS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['SET_CURRENT_SENSOR_ID']: Pick<MenusTypes, 'currentSensorId'>\r\n ['SET_CURRENT_SENSOR_TYPE_ID']: Pick<MenusTypes, 'currentSensorTypeId'>\r\n ['SET_FOCUSED_SENSOR_ID']: {sensorId: number | null}\r\n ['REQUEST_SENSOR_ACTION']: {sensorId: number}\r\n ['CLEAR_PENDING_SENSOR_ACTION']: undefined\r\n}\r\n\r\nexport type MenusActions\r\n = ActionMap<MenusPayload>[keyof ActionMap<MenusPayload>]\r\n\r\nexport const MenusReducer = (state: MenusState, action: MenusActions) => {\r\n switch (action.type) {\r\n case 'SET_VIEWER':\r\n return {\r\n ...state,\r\n currentViewer: action.payload.currentViewer,\r\n }\r\n case 'SET_PAGINATION_ROWS_PER_PAGE':\r\n return {\r\n ...state,\r\n rowsPerPage: action.payload.rowsPerPage,\r\n }\r\n case 'SET_SIDEBAR_SELECTED_TAB':\r\n return {\r\n ...state,\r\n selectedTab: action.payload.selectedTab,\r\n }\r\n case 'SHOW_COMMENTS_IN_VIEWER':\r\n const viewerToShow = action.payload.viewer\r\n if (!viewerToShow) return state\r\n const commentsCurrentlyVisible = state.commentsVisibleInViewer || []\r\n return {\r\n ...state,\r\n commentsVisibleInViewer: commentsCurrentlyVisible.includes(viewerToShow)\r\n ? commentsCurrentlyVisible\r\n : [...commentsCurrentlyVisible, viewerToShow],\r\n }\r\n case 'HIDE_COMMENTS_IN_VIEWER':\r\n const viewerToHide = action.payload.viewer\r\n if (!viewerToHide) return state\r\n return {\r\n ...state,\r\n commentsVisibleInViewer: (state.commentsVisibleInViewer || []).filter(\r\n v => v !== viewerToHide\r\n ),\r\n }\r\n case 'SET_CURRENT_COMMENT_ID':\r\n return {\r\n ...state,\r\n currentCommentId: action.payload.commentId,\r\n }\r\n case 'SET_FOCUSED_COMMENT_ID':\r\n return {\r\n ...state,\r\n focusedCommentId: action.payload.commentId,\r\n focusRequestId: state.focusRequestId + 1,\r\n }\r\n case 'REQUEST_COMMENT_ACTION':\r\n return {\r\n ...state,\r\n pendingCommentAction: {\r\n commentId: action.payload.commentId,\r\n action: action.payload.action,\r\n requestId: (state.pendingCommentAction?.requestId ?? 0) + 1,\r\n },\r\n }\r\n case 'CLEAR_PENDING_COMMENT_ACTION':\r\n if (state.pendingCommentAction === null) return state\r\n return {\r\n ...state,\r\n pendingCommentAction: null,\r\n }\r\n case 'SET_CURRENT_SENSOR_ID':\r\n return {\r\n ...state,\r\n currentSensorId: action.payload.currentSensorId,\r\n }\r\n case 'SET_CURRENT_SENSOR_TYPE_ID':\r\n return {\r\n ...state,\r\n currentSensorTypeId: action.payload.currentSensorTypeId,\r\n }\r\n case 'SET_FOCUSED_SENSOR_ID':\r\n return {\r\n ...state,\r\n focusedSensorId: action.payload.sensorId,\r\n sensorFocusRequestId: state.sensorFocusRequestId + 1,\r\n }\r\n case 'REQUEST_SENSOR_ACTION':\r\n return {\r\n ...state,\r\n pendingSensorAction: {\r\n sensorId: action.payload.sensorId,\r\n action: 'edit',\r\n requestId: (state.pendingSensorAction?.requestId ?? 0) + 1,\r\n },\r\n }\r\n case 'CLEAR_PENDING_SENSOR_ACTION':\r\n if (state.pendingSensorAction === null) return state\r\n return {\r\n ...state,\r\n pendingSensorAction: null,\r\n }\r\n case 'HIDE_ALL_SENSORS_IN_VIEWER':\r\n const sensorViewerToHide = action.payload.viewer\r\n if (!sensorViewerToHide) return state\r\n return {\r\n ...state,\r\n sensorsVisibleInViewer: (state.sensorsVisibleInViewer || []).filter(\r\n v => v !== sensorViewerToHide\r\n ),\r\n // Also hide all sensor types for this viewer\r\n visibleSensorTypes: {\r\n ...state.visibleSensorTypes,\r\n [sensorViewerToHide]: [],\r\n },\r\n }\r\n case 'HIDE_ALL_SENSOR_TAGS_IN_VIEWER':\r\n const tagViewerToHide = action.payload.viewer\r\n if (!tagViewerToHide) return state\r\n return {\r\n ...state,\r\n visibleSensorTags: {\r\n ...state.visibleSensorTags,\r\n [tagViewerToHide]: [],\r\n },\r\n }\r\n case 'TOGGLE_SENSOR_TYPE_VISIBILITY':\r\n const { viewer: toggleViewer, sensorTypeId, force } = action.payload\r\n if (!toggleViewer || !sensorTypeId) return state\r\n const currentTypesForViewer = state.visibleSensorTypes?.[toggleViewer] || []\r\n const isCurrentlyVisible = currentTypesForViewer.includes(sensorTypeId)\r\n // force=true → only show (idempotent); force=false/undefined → toggle\r\n if (force && isCurrentlyVisible) return state\r\n return {\r\n ...state,\r\n visibleSensorTypes: {\r\n ...state.visibleSensorTypes,\r\n [toggleViewer]: (force || !isCurrentlyVisible)\r\n ? [...currentTypesForViewer, sensorTypeId]\r\n : currentTypesForViewer.filter(t => t !== sensorTypeId),\r\n },\r\n }\r\n case 'TOGGLE_SENSOR_TAG_VISIBILITY':\r\n const { viewer: toggleTagViewer, sensorTag, force: forceTag } = action.payload\r\n if (!toggleTagViewer || !sensorTag) return state\r\n const currentTagsForViewer = state.visibleSensorTags?.[toggleTagViewer] || []\r\n const isTagCurrentlyVisible = currentTagsForViewer.includes(sensorTag)\r\n if (forceTag && isTagCurrentlyVisible) return state\r\n return {\r\n ...state,\r\n visibleSensorTags: {\r\n ...state.visibleSensorTags,\r\n [toggleTagViewer]: (forceTag || !isTagCurrentlyVisible)\r\n ? [...currentTagsForViewer, sensorTag]\r\n : currentTagsForViewer.filter(t => t !== sensorTag),\r\n },\r\n }\r\n\r\n case 'SHOW_ALL_SENSOR_IN_VIEWER':\r\n const showAllViewer = action.payload.viewer\r\n if (!showAllViewer) return state\r\n // This is called when opening the add sensor tool - we don't know all types yet\r\n // So we just ensure the viewer is in sensorsVisibleInViewer\r\n return state\r\n default:\r\n return state\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA0EO,MAAM,eAAe,CAAC,OAAmB,WAAyB;AA1EzE;AA2EE,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,iCACF,QADE;AAAA,QAEL,eAAe,OAAO,QAAQ;AAAA,MAChC;AAAA,IACF,KAAK;AACH,aAAO,iCACF,QADE;AAAA,QAEL,aAAa,OAAO,QAAQ;AAAA,MAC9B;AAAA,IACF,KAAK;AACH,aAAO,iCACF,QADE;AAAA,QAEL,aAAa,OAAO,QAAQ;AAAA,MAC9B;AAAA,IACF,KAAK;AACH,YAAM,eAAe,OAAO,QAAQ;AACpC,UAAI,CAAC,aAAc,QAAO;AAC1B,YAAM,2BAA2B,MAAM,2BAA2B,CAAC;AACnE,aAAO,iCACJ,QADI;AAAA,QAEP,yBAAyB,yBAAyB,SAAS,YAAY,IACnE,2BACA,CAAC,GAAG,0BAA0B,YAAY;AAAA,MAC9C;AAAA,IACF,KAAK;AACH,YAAM,eAAe,OAAO,QAAQ;AACpC,UAAI,CAAC,aAAc,QAAO;AAC1B,aAAO,iCACJ,QADI;AAAA,QAEP,0BAA0B,MAAM,2BAA2B,CAAC,GAAG;AAAA,UAC7D,OAAK,MAAM;AAAA,QACb;AAAA,MACA;AAAA,IACF,KAAK;AACH,aAAO,iCACF,QADE;AAAA,QAEL,kBAAkB,OAAO,QAAQ;AAAA,MACnC;AAAA,IACF,KAAK;AACH,aAAO,iCACF,QADE;AAAA,QAEL,kBAAkB,OAAO,QAAQ;AAAA,QACjC,gBAAgB,MAAM,iBAAiB;AAAA,MACzC;AAAA,IACF,KAAK;AACH,aAAO,iCACF,QADE;AAAA,QAEL,sBAAsB;AAAA,UACpB,WAAW,OAAO,QAAQ;AAAA,UAC1B,QAAQ,OAAO,QAAQ;AAAA,UACvB,aAAY,iBAAM,yBAAN,mBAA4B,cAA5B,YAAyC,KAAK;AAAA,QAC5D;AAAA,MACF;AAAA,IACF,KAAK;AACH,UAAI,MAAM,yBAAyB,KAAM,QAAO;AAChD,aAAO,iCACF,QADE;AAAA,QAEL,sBAAsB;AAAA,MACxB;AAAA,IACF,KAAK;AACH,aAAO,iCACF,QADE;AAAA,QAEL,iBAAiB,OAAO,QAAQ;AAAA,MAClC;AAAA,IACF,KAAK;AACH,aAAO,iCACF,QADE;AAAA,QAEL,qBAAqB,OAAO,QAAQ;AAAA,MACtC;AAAA,IACF,KAAK;AACH,aAAO,iCACF,QADE;AAAA,QAEL,iBAAiB,OAAO,QAAQ;AAAA,QAChC,sBAAsB,MAAM,uBAAuB;AAAA,MACrD;AAAA,IACF,KAAK;AACH,aAAO,iCACF,QADE;AAAA,QAEL,qBAAqB;AAAA,UACnB,UAAU,OAAO,QAAQ;AAAA,UACzB,QAAQ;AAAA,UACR,aAAY,iBAAM,wBAAN,mBAA2B,cAA3B,YAAwC,KAAK;AAAA,QAC3D;AAAA,MACF;AAAA,IACF,KAAK;AACH,UAAI,MAAM,wBAAwB,KAAM,QAAO;AAC/C,aAAO,iCACF,QADE;AAAA,QAEL,qBAAqB;AAAA,MACvB;AAAA,IACF,KAAK;AACH,YAAM,qBAAqB,OAAO,QAAQ;AAC1C,UAAI,CAAC,mBAAoB,QAAO;AAChC,aAAO,iCACF,QADE;AAAA,QAEL,yBAAyB,MAAM,0BAA0B,CAAC,GAAG;AAAA,UAC3D,OAAK,MAAM;AAAA,QACb;AAAA;AAAA,QAEA,oBAAoB,iCACf,MAAM,qBADS;AAAA,UAElB,CAAC,kBAAkB,GAAG,CAAC;AAAA,QACzB;AAAA,MACF;AAAA,IACF,KAAK;AACH,YAAM,kBAAkB,OAAO,QAAQ;AACvC,UAAI,CAAC,gBAAiB,QAAO;AAC7B,aAAO,iCACF,QADE;AAAA,QAEL,mBAAmB,iCACd,MAAM,oBADQ;AAAA,UAEjB,CAAC,eAAe,GAAG,CAAC;AAAA,QACtB;AAAA,MACF;AAAA,IACF,KAAK;AACH,YAAM,EAAE,QAAQ,cAAc,cAAc,MAAM,IAAI,OAAO;AAC7D,UAAI,CAAC,gBAAgB,CAAC,aAAc,QAAO;AAC3C,YAAM,0BAAwB,WAAM,uBAAN,mBAA2B,kBAAiB,CAAC;AAC3E,YAAM,qBAAqB,sBAAsB,SAAS,YAAY;AAEtE,UAAI,SAAS,mBAAoB,QAAO;AACxC,aAAO,iCACF,QADE;AAAA,QAEL,oBAAoB,iCACf,MAAM,qBADS;AAAA,UAElB,CAAC,YAAY,GAAI,SAAS,CAAC,qBACvB,CAAC,GAAG,uBAAuB,YAAY,IACvC,sBAAsB,OAAO,OAAK,MAAM,YAAY;AAAA,QAC1D;AAAA,MACF;AAAA,IACF,KAAK;AACH,YAAM,EAAE,QAAQ,iBAAiB,WAAW,OAAO,SAAS,IAAI,OAAO;AACvE,UAAI,CAAC,mBAAmB,CAAC,UAAW,QAAO;AAC3C,YAAM,yBAAuB,WAAM,sBAAN,mBAA0B,qBAAoB,CAAC;AAC5E,YAAM,wBAAwB,qBAAqB,SAAS,SAAS;AACrE,UAAI,YAAY,sBAAuB,QAAO;AAC9C,aAAO,iCACF,QADE;AAAA,QAEL,mBAAmB,iCACd,MAAM,oBADQ;AAAA,UAEjB,CAAC,eAAe,GAAI,YAAY,CAAC,wBAC7B,CAAC,GAAG,sBAAsB,SAAS,IACnC,qBAAqB,OAAO,OAAK,MAAM,SAAS;AAAA,QACtD;AAAA,MACF;AAAA,IAEF,KAAK;AACH,YAAM,gBAAgB,OAAO,QAAQ;AACrC,UAAI,CAAC,cAAe,QAAO;AAG3B,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;","names":[]}
|
|
@@ -11,8 +11,12 @@ export declare function timeAgo(then: Date): string;
|
|
|
11
11
|
* Format a timestamp for display
|
|
12
12
|
* - If today: shows relative time (e.g., "5 min")
|
|
13
13
|
* - If not today: shows formatted date (e.g., "Jan 15, 2026")
|
|
14
|
+
*
|
|
15
|
+
* The `timeZone` arg only affects the absolute-date rendering; the today/relative
|
|
16
|
+
* boundary is computed in the host local day (a known cosmetic limitation near
|
|
17
|
+
* midnight across zones).
|
|
14
18
|
*/
|
|
15
|
-
export declare function formatTimestamp(input: string | Date): string;
|
|
19
|
+
export declare function formatTimestamp(input: string | Date, timeZone?: string): string;
|
|
16
20
|
/**
|
|
17
21
|
* Format milliseconds to human-readable duration
|
|
18
22
|
* Examples: "500 ms", "1 sec", "30 sec", "5 min", "1 hr", "2 days"
|
|
@@ -35,4 +39,23 @@ export declare const frequencyUnits: readonly [{
|
|
|
35
39
|
readonly value: 3600000;
|
|
36
40
|
readonly label: "Hours";
|
|
37
41
|
}];
|
|
42
|
+
/** Browser IANA zone, e.g. "America/Toronto". Falls back to "UTC" if unavailable. */
|
|
43
|
+
export declare function detectTimeZone(): string;
|
|
44
|
+
/**
|
|
45
|
+
* Longitude -> nearest whole-hour offset -> an Etc/GMT±N id. Note POSIX sign inversion:
|
|
46
|
+
* a positive (east) offset is Etc/GMT-N. This is a rough approximation: no DST, no
|
|
47
|
+
* political borders. 0 -> "UTC".
|
|
48
|
+
*/
|
|
49
|
+
export declare function offsetZoneFromLongitude(longitude: number): string;
|
|
50
|
+
/**
|
|
51
|
+
* Default display zone. Prefers the browser's IANA zone: it is DST-correct and, for a user
|
|
52
|
+
* in the sensor's region, already the right local zone. Only when detection is unavailable
|
|
53
|
+
* (returns "UTC") does it fall back to a longitude-derived fixed offset, trying each
|
|
54
|
+
* candidate longitude in order. Callers pass candidates in priority order: BIM sensors sit
|
|
55
|
+
* in a building (building longitude first), map sensors carry their own coordinates (sensor
|
|
56
|
+
* longitude first).
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveDefaultTimeZone(longitudeCandidates: Array<number | null | undefined>): string;
|
|
59
|
+
/** Format an epoch in a specific zone. Handles Etc/GMT±N and true IANA zones alike. */
|
|
60
|
+
export declare function formatInZone(epochMs: number, timeZone: string, opts?: Intl.DateTimeFormatOptions): string;
|
|
38
61
|
//# sourceMappingURL=timeUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeUtils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/timeUtils.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAMnD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAuB1C;AAED
|
|
1
|
+
{"version":3,"file":"timeUtils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/timeUtils.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAMnD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAuB1C;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAa/E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAcjD;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;EAKjB,CAAA;AAEV,qFAAqF;AACrF,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,mBAAmB,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,CAOpG;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,IAAI,CAAC,qBAAqB,GAChC,MAAM,CAMR"}
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __spreadValues = (a, b) => {
|
|
7
|
+
for (var prop in b || (b = {}))
|
|
8
|
+
if (__hasOwnProp.call(b, prop))
|
|
9
|
+
__defNormalProp(a, prop, b[prop]);
|
|
10
|
+
if (__getOwnPropSymbols)
|
|
11
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
+
if (__propIsEnum.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
}
|
|
15
|
+
return a;
|
|
16
|
+
};
|
|
1
17
|
function isSameDay(a, b) {
|
|
2
18
|
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
3
19
|
}
|
|
@@ -18,16 +34,16 @@ function timeAgo(then) {
|
|
|
18
34
|
const diffYears = Math.floor(diffDays / 365);
|
|
19
35
|
return `${diffYears}y`;
|
|
20
36
|
}
|
|
21
|
-
function formatTimestamp(input) {
|
|
37
|
+
function formatTimestamp(input, timeZone) {
|
|
22
38
|
const then = typeof input === "string" ? new Date(input) : input;
|
|
23
39
|
const now = /* @__PURE__ */ new Date();
|
|
24
40
|
if (Number.isNaN(then.getTime())) return "";
|
|
25
41
|
if (isSameDay(now, then)) return timeAgo(then);
|
|
26
|
-
return then.toLocaleDateString(void 0, {
|
|
42
|
+
return then.toLocaleDateString(void 0, __spreadValues({
|
|
27
43
|
year: "numeric",
|
|
28
44
|
month: "short",
|
|
29
45
|
day: "2-digit"
|
|
30
|
-
});
|
|
46
|
+
}, timeZone ? { timeZone } : {}));
|
|
31
47
|
}
|
|
32
48
|
function formatDuration(ms) {
|
|
33
49
|
if (ms < 1e3) return `${ms} ms`;
|
|
@@ -46,11 +62,44 @@ const frequencyUnits = [
|
|
|
46
62
|
{ value: 6e4, label: "Minutes" },
|
|
47
63
|
{ value: 36e5, label: "Hours" }
|
|
48
64
|
];
|
|
65
|
+
function detectTimeZone() {
|
|
66
|
+
try {
|
|
67
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
68
|
+
} catch (e) {
|
|
69
|
+
return "UTC";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function offsetZoneFromLongitude(longitude) {
|
|
73
|
+
if (!Number.isFinite(longitude)) return "UTC";
|
|
74
|
+
let h = Math.round(longitude / 15);
|
|
75
|
+
h = Math.max(-12, Math.min(12, h));
|
|
76
|
+
if (h === 0) return "UTC";
|
|
77
|
+
return `Etc/GMT${h > 0 ? "-" : "+"}${Math.abs(h)}`;
|
|
78
|
+
}
|
|
79
|
+
function resolveDefaultTimeZone(longitudeCandidates) {
|
|
80
|
+
const detected = detectTimeZone();
|
|
81
|
+
if (detected && detected !== "UTC") return detected;
|
|
82
|
+
for (const lng of longitudeCandidates) {
|
|
83
|
+
if (typeof lng === "number" && Number.isFinite(lng)) return offsetZoneFromLongitude(lng);
|
|
84
|
+
}
|
|
85
|
+
return detected || "UTC";
|
|
86
|
+
}
|
|
87
|
+
function formatInZone(epochMs, timeZone, opts) {
|
|
88
|
+
try {
|
|
89
|
+
return new Intl.DateTimeFormat(void 0, __spreadValues({ timeZone }, opts)).format(epochMs);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
return new Intl.DateTimeFormat(void 0, opts).format(epochMs);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
49
94
|
export {
|
|
95
|
+
detectTimeZone,
|
|
50
96
|
formatDuration,
|
|
97
|
+
formatInZone,
|
|
51
98
|
formatTimestamp,
|
|
52
99
|
frequencyUnits,
|
|
53
100
|
isSameDay,
|
|
101
|
+
offsetZoneFromLongitude,
|
|
102
|
+
resolveDefaultTimeZone,
|
|
54
103
|
timeAgo
|
|
55
104
|
};
|
|
56
105
|
//# sourceMappingURL=timeUtils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/utils/timeUtils.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n/**\r\n * Check if two dates are on the same day (ignoring time)\r\n */\r\nexport function isSameDay(a: Date, b: Date): boolean {\r\n return (\r\n a.getFullYear() === b.getFullYear()\r\n && a.getMonth() === b.getMonth()\r\n && a.getDate() === b.getDate()\r\n )\r\n}\r\n\r\n/**\r\n * Calculate time elapsed since a given date and return a human-readable string\r\n * Examples: \"5s\", \"10 min\", \"3h\", \"2d\", \"1w\", \"3mo\", \"2y\"\r\n */\r\nexport function timeAgo(then: Date): string {\r\n const now = new Date()\r\n const diffSeconds = Math.floor((now.getTime() - then.getTime()) / 1000)\r\n\r\n if (diffSeconds < 60) return `${diffSeconds}s`\r\n\r\n const diffMinutes = Math.floor(diffSeconds / 60)\r\n if (diffMinutes < 60) return `${diffMinutes} min`\r\n\r\n const diffHours = Math.floor(diffMinutes / 60)\r\n if (diffHours < 24) return `${diffHours}h`\r\n\r\n const diffDays = Math.floor(diffHours / 24)\r\n if (diffDays < 7) return `${diffDays}d`\r\n\r\n const diffWeeks = Math.floor(diffDays / 7)\r\n if (diffWeeks < 4) return `${diffWeeks}w`\r\n\r\n const diffMonths = Math.floor(diffDays / 30)\r\n if (diffMonths < 12) return `${diffMonths}mo`\r\n\r\n const diffYears = Math.floor(diffDays / 365)\r\n return `${diffYears}y`\r\n}\r\n\r\n/**\r\n * Format a timestamp for display\r\n * - If today: shows relative time (e.g., \"5 min\")\r\n * - If not today: shows formatted date (e.g., \"Jan 15, 2026\")\r\n */\r\nexport function formatTimestamp(input: string | Date): string {\r\n const then = typeof input === 'string' ? new Date(input) : input\r\n const now = new Date()\r\n\r\n if (Number.isNaN(then.getTime())) return ''\r\n if (isSameDay(now, then)) return timeAgo(then)\r\n\r\n return then.toLocaleDateString(undefined, {\r\n year: 'numeric',\r\n month: 'short',\r\n day: '2-digit',\r\n })\r\n}\r\n\r\n/**\r\n * Format milliseconds to human-readable duration\r\n * Examples: \"500 ms\", \"1 sec\", \"30 sec\", \"5 min\", \"1 hr\", \"2 days\"\r\n */\r\nexport function formatDuration(ms: number): string {\r\n if (ms < 1000) return `${ms} ms`\r\n\r\n const seconds = ms / 1000\r\n if (seconds < 60) return seconds === 1 ? '1 sec' : `${seconds} sec`\r\n\r\n const minutes = seconds / 60\r\n if (minutes < 60) return minutes === 1 ? '1 min' : `${Math.floor(minutes)} min`\r\n\r\n const hours = minutes / 60\r\n if (hours < 24) return hours === 1 ? '1 hr' : `${Math.floor(hours)} hr`\r\n\r\n const days = hours / 24\r\n return days === 1 ? '1 day' : `${Math.floor(days)} days`\r\n}\r\n\r\n/**\r\n * Time frequency units for duration inputs\r\n * Value is the multiplier to convert to milliseconds\r\n */\r\nexport const frequencyUnits = [\r\n { value: 1, label: 'Milliseconds' },\r\n { value: 1000, label: 'Seconds' },\r\n { value: 60000, label: 'Minutes' },\r\n { value: 3600000, label: 'Hours' },\r\n] as const\r\n"],"mappings":"AAMO,SAAS,UAAU,GAAS,GAAkB;AACnD,SACE,EAAE,YAAY,MAAM,EAAE,YAAY,KAC/B,EAAE,SAAS,MAAM,EAAE,SAAS,KAC5B,EAAE,QAAQ,MAAM,EAAE,QAAQ;AAEjC;AAMO,SAAS,QAAQ,MAAoB;AAC1C,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,cAAc,KAAK,OAAO,IAAI,QAAQ,IAAI,KAAK,QAAQ,KAAK,GAAI;AAEtE,MAAI,cAAc,GAAI,QAAO,GAAG,WAAW;AAE3C,QAAM,cAAc,KAAK,MAAM,cAAc,EAAE;AAC/C,MAAI,cAAc,GAAI,QAAO,GAAG,WAAW;AAE3C,QAAM,YAAY,KAAK,MAAM,cAAc,EAAE;AAC7C,MAAI,YAAY,GAAI,QAAO,GAAG,SAAS;AAEvC,QAAM,WAAW,KAAK,MAAM,YAAY,EAAE;AAC1C,MAAI,WAAW,EAAG,QAAO,GAAG,QAAQ;AAEpC,QAAM,YAAY,KAAK,MAAM,WAAW,CAAC;AACzC,MAAI,YAAY,EAAG,QAAO,GAAG,SAAS;AAEtC,QAAM,aAAa,KAAK,MAAM,WAAW,EAAE;AAC3C,MAAI,aAAa,GAAI,QAAO,GAAG,UAAU;AAEzC,QAAM,YAAY,KAAK,MAAM,WAAW,GAAG;AAC3C,SAAO,GAAG,SAAS;AACrB;
|
|
1
|
+
{"version":3,"sources":["../../../src/core/utils/timeUtils.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n/**\r\n * Check if two dates are on the same day (ignoring time)\r\n */\r\nexport function isSameDay(a: Date, b: Date): boolean {\r\n return (\r\n a.getFullYear() === b.getFullYear()\r\n && a.getMonth() === b.getMonth()\r\n && a.getDate() === b.getDate()\r\n )\r\n}\r\n\r\n/**\r\n * Calculate time elapsed since a given date and return a human-readable string\r\n * Examples: \"5s\", \"10 min\", \"3h\", \"2d\", \"1w\", \"3mo\", \"2y\"\r\n */\r\nexport function timeAgo(then: Date): string {\r\n const now = new Date()\r\n const diffSeconds = Math.floor((now.getTime() - then.getTime()) / 1000)\r\n\r\n if (diffSeconds < 60) return `${diffSeconds}s`\r\n\r\n const diffMinutes = Math.floor(diffSeconds / 60)\r\n if (diffMinutes < 60) return `${diffMinutes} min`\r\n\r\n const diffHours = Math.floor(diffMinutes / 60)\r\n if (diffHours < 24) return `${diffHours}h`\r\n\r\n const diffDays = Math.floor(diffHours / 24)\r\n if (diffDays < 7) return `${diffDays}d`\r\n\r\n const diffWeeks = Math.floor(diffDays / 7)\r\n if (diffWeeks < 4) return `${diffWeeks}w`\r\n\r\n const diffMonths = Math.floor(diffDays / 30)\r\n if (diffMonths < 12) return `${diffMonths}mo`\r\n\r\n const diffYears = Math.floor(diffDays / 365)\r\n return `${diffYears}y`\r\n}\r\n\r\n/**\r\n * Format a timestamp for display\r\n * - If today: shows relative time (e.g., \"5 min\")\r\n * - If not today: shows formatted date (e.g., \"Jan 15, 2026\")\r\n *\r\n * The `timeZone` arg only affects the absolute-date rendering; the today/relative\r\n * boundary is computed in the host local day (a known cosmetic limitation near\r\n * midnight across zones).\r\n */\r\nexport function formatTimestamp(input: string | Date, timeZone?: string): string {\r\n const then = typeof input === 'string' ? new Date(input) : input\r\n const now = new Date()\r\n\r\n if (Number.isNaN(then.getTime())) return ''\r\n if (isSameDay(now, then)) return timeAgo(then)\r\n\r\n return then.toLocaleDateString(undefined, {\r\n year: 'numeric',\r\n month: 'short',\r\n day: '2-digit',\r\n ...(timeZone ? { timeZone } : {}),\r\n })\r\n}\r\n\r\n/**\r\n * Format milliseconds to human-readable duration\r\n * Examples: \"500 ms\", \"1 sec\", \"30 sec\", \"5 min\", \"1 hr\", \"2 days\"\r\n */\r\nexport function formatDuration(ms: number): string {\r\n if (ms < 1000) return `${ms} ms`\r\n\r\n const seconds = ms / 1000\r\n if (seconds < 60) return seconds === 1 ? '1 sec' : `${seconds} sec`\r\n\r\n const minutes = seconds / 60\r\n if (minutes < 60) return minutes === 1 ? '1 min' : `${Math.floor(minutes)} min`\r\n\r\n const hours = minutes / 60\r\n if (hours < 24) return hours === 1 ? '1 hr' : `${Math.floor(hours)} hr`\r\n\r\n const days = hours / 24\r\n return days === 1 ? '1 day' : `${Math.floor(days)} days`\r\n}\r\n\r\n/**\r\n * Time frequency units for duration inputs\r\n * Value is the multiplier to convert to milliseconds\r\n */\r\nexport const frequencyUnits = [\r\n { value: 1, label: 'Milliseconds' },\r\n { value: 1000, label: 'Seconds' },\r\n { value: 60000, label: 'Minutes' },\r\n { value: 3600000, label: 'Hours' },\r\n] as const\r\n\r\n/** Browser IANA zone, e.g. \"America/Toronto\". Falls back to \"UTC\" if unavailable. */\r\nexport function detectTimeZone(): string {\r\n try {\r\n return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'\r\n } catch {\r\n return 'UTC'\r\n }\r\n}\r\n\r\n/**\r\n * Longitude -> nearest whole-hour offset -> an Etc/GMT±N id. Note POSIX sign inversion:\r\n * a positive (east) offset is Etc/GMT-N. This is a rough approximation: no DST, no\r\n * political borders. 0 -> \"UTC\".\r\n */\r\nexport function offsetZoneFromLongitude(longitude: number): string {\r\n if (!Number.isFinite(longitude)) return 'UTC'\r\n let h = Math.round(longitude / 15)\r\n h = Math.max(-12, Math.min(12, h))\r\n if (h === 0) return 'UTC'\r\n return `Etc/GMT${h > 0 ? '-' : '+'}${Math.abs(h)}`\r\n}\r\n\r\n/**\r\n * Default display zone. Prefers the browser's IANA zone: it is DST-correct and, for a user\r\n * in the sensor's region, already the right local zone. Only when detection is unavailable\r\n * (returns \"UTC\") does it fall back to a longitude-derived fixed offset, trying each\r\n * candidate longitude in order. Callers pass candidates in priority order: BIM sensors sit\r\n * in a building (building longitude first), map sensors carry their own coordinates (sensor\r\n * longitude first).\r\n */\r\nexport function resolveDefaultTimeZone(longitudeCandidates: Array<number | null | undefined>): string {\r\n const detected = detectTimeZone()\r\n if (detected && detected !== 'UTC') return detected\r\n for (const lng of longitudeCandidates) {\r\n if (typeof lng === 'number' && Number.isFinite(lng)) return offsetZoneFromLongitude(lng)\r\n }\r\n return detected || 'UTC'\r\n}\r\n\r\n/** Format an epoch in a specific zone. Handles Etc/GMT±N and true IANA zones alike. */\r\nexport function formatInZone(\r\n epochMs: number,\r\n timeZone: string,\r\n opts?: Intl.DateTimeFormatOptions,\r\n): string {\r\n try {\r\n return new Intl.DateTimeFormat(undefined, { timeZone, ...opts }).format(epochMs)\r\n } catch {\r\n return new Intl.DateTimeFormat(undefined, opts).format(epochMs)\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|