@dexteel/mesf-core 7.5.2 → 7.7.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/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +21 -0
- package/GEMINI.md +92 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +823 -44
- package/dist/index.esm.js.map +1 -1
- package/dist/pages/sp-executor/SPExecutorPage.d.ts +2 -0
- package/dist/pages/sp-executor/components/DynamicParameterForm.d.ts +9 -0
- package/dist/pages/sp-executor/components/PinGate.d.ts +6 -0
- package/dist/pages/sp-executor/components/ResultsList.d.ts +9 -0
- package/dist/pages/sp-executor/components/SPAutocomplete.d.ts +11 -0
- package/dist/pages/sp-executor/index.d.ts +2 -0
- package/dist/pages/sp-executor/models/SPExecutorModels.d.ts +37 -0
- package/dist/pages/sp-executor/repositories/SPExecutorRepository.d.ts +3 -0
- package/dist/pages/trendings-v2/components/chart/components/modals/BitSelectorModal.d.ts +11 -0
- package/dist/pages/trendings-v2/components/chart/models/TrendingModelsV2.d.ts +6 -0
- package/package.json +6 -5
package/dist/index.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HubConnectionBuilder, LogLevel } from '@microsoft/signalr';
|
|
2
2
|
export * from '@microsoft/signalr';
|
|
3
3
|
export { LicenseManager } from 'ag-grid-enterprise';
|
|
4
|
-
import { styled, DialogTitle as DialogTitle$1, DialogContent as DialogContent$1, DialogActions as DialogActions$1, Grid2, Button, Box, MenuItem, ListItemIcon, createTheme, TextField, Alert as Alert$2, useTheme, InputAdornment, Popover, MenuList, ListItemText, alpha, Dialog as Dialog$1, Paper, List, ListItem, Chip, SvgIcon, Typography as Typography$1, Checkbox, IconButton as IconButton$1, CircularProgress, FormControl, FormHelperText, FormControlLabel, Snackbar, DialogContentText, Badge, InputLabel, Select, Input, Divider, Card, CardContent, CardActions, Collapse, Tooltip, CssBaseline, AppBar, Toolbar, Container, Menu, Switch, Hidden, Drawer,
|
|
4
|
+
import { styled, DialogTitle as DialogTitle$1, DialogContent as DialogContent$1, DialogActions as DialogActions$1, Grid2, Button, Box, MenuItem, ListItemIcon, createTheme, TextField, Alert as Alert$2, useTheme, InputAdornment, Popover, MenuList, ListItemText, alpha, Dialog as Dialog$1, Paper, List, ListItem, Chip, SvgIcon, Typography as Typography$1, Checkbox, IconButton as IconButton$1, CircularProgress, FormControl, FormHelperText, FormControlLabel, Snackbar, DialogContentText, Badge, InputLabel, Select, Input, Divider, Card, CardContent, CardActions, Collapse, Tooltip, CssBaseline, AppBar, Toolbar, Container, Menu, Switch, Hidden, Drawer, Grid, Accordion, AccordionSummary, AccordionDetails, Tabs, Tab, Autocomplete as Autocomplete$1, useMediaQuery, ListSubheader, ListItemButton, TableContainer, Table, TableHead, TableRow, TableCell, TableBody, debounce, StyledEngineProvider, ThemeProvider, ListItemSecondaryAction } from '@mui/material';
|
|
5
5
|
import { useMutation, useQuery, useQueryClient, QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
6
6
|
import * as React from 'react';
|
|
7
7
|
import React__default, { createContext, useContext, useRef, useState, useEffect, useCallback, useMemo, Component, lazy, Suspense } from 'react';
|
|
@@ -25,7 +25,7 @@ import DeleteIcon from '@mui/icons-material/Delete';
|
|
|
25
25
|
import EditIcon from '@mui/icons-material/Edit';
|
|
26
26
|
import FindInPageIcon from '@mui/icons-material/FindInPage';
|
|
27
27
|
import PlaylistAddIcon from '@mui/icons-material/PlaylistAdd';
|
|
28
|
-
import { ArrowRight, ArrowBackRounded, ArrowForwardRounded, SkipNext, ChevronLeft, ChevronRight, Cloud, Square as Square$1, Timeline, Send, Menu as Menu$1, People, Storage, Group, Assignment, Chat, ViewList, Build, Settings as Settings$2, FastRewind, FastForward, ZoomIn, Restore, Lock, Create, Delete, Folder, InsertChart, Search, PlaylistAdd, DragIndicator, Save, AttachFile, CloudUpload, GetApp } from '@mui/icons-material';
|
|
28
|
+
import { ArrowRight, ArrowBackRounded, ArrowForwardRounded, SkipNext, ChevronLeft, ChevronRight, Cloud, Square as Square$1, Timeline, Send, Menu as Menu$1, People, Storage, Group, Assignment, Chat, ViewList, Build, Settings as Settings$2, Code as Code$1, FastRewind, FastForward, ZoomIn, Restore, Lock, Create, Delete, Folder, InsertChart, Search, PlaylistAdd, DragIndicator, Save, AttachFile, CloudUpload, GetApp } from '@mui/icons-material';
|
|
29
29
|
import FormatListBulletedSharpIcon from '@mui/icons-material/FormatListBulletedSharp';
|
|
30
30
|
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
|
|
31
31
|
import CloseIcon from '@mui/icons-material/Close';
|
|
@@ -55,7 +55,11 @@ import { DndProvider } from 'react-dnd';
|
|
|
55
55
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
56
56
|
import MenuIcon from '@mui/icons-material/Menu';
|
|
57
57
|
import ShowChartIcon from '@mui/icons-material/ShowChart';
|
|
58
|
+
import { DateTimePicker as DateTimePicker$1 } from '@mui/x-date-pickers/DateTimePicker';
|
|
59
|
+
import ClearAllIcon from '@mui/icons-material/ClearAll';
|
|
60
|
+
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|
58
61
|
import axios from 'axios';
|
|
62
|
+
import { Group as Group$1, Panel, Separator } from 'react-resizable-panels';
|
|
59
63
|
import { LocalizationProvider as LocalizationProvider$1 } from '@mui/x-date-pickers/LocalizationProvider';
|
|
60
64
|
import InsertChartIcon from '@mui/icons-material/InsertChart';
|
|
61
65
|
import ReactECharts from 'echarts-for-react';
|
|
@@ -3856,13 +3860,13 @@ var INITIAL_VALUES$2 = {
|
|
|
3856
3860
|
};
|
|
3857
3861
|
|
|
3858
3862
|
var CreateProfile = function (_a) {
|
|
3859
|
-
var _b;
|
|
3863
|
+
var _b, _c;
|
|
3860
3864
|
var show = _a.show, onHide = _a.onHide, suffixTitle = _a.suffixTitle;
|
|
3861
|
-
var
|
|
3862
|
-
var
|
|
3863
|
-
var
|
|
3864
|
-
var
|
|
3865
|
-
var
|
|
3865
|
+
var _d = useState(false), openSnackbar = _d[0], setOpenSnackbar = _d[1];
|
|
3866
|
+
var _e = useState(""), message = _e[0], setMessage = _e[1];
|
|
3867
|
+
var _f = useState(false), isSubmitLoading = _f[0], setIsSubmitLoading = _f[1];
|
|
3868
|
+
var _g = useState(""), error = _g[0], setError = _g[1];
|
|
3869
|
+
var _h = useForm({ defaultValues: INITIAL_VALUES$2 }), register = _h.register, handleSubmit = _h.handleSubmit, reset = _h.reset, errors = _h.formState.errors;
|
|
3866
3870
|
var createProfile = useMutation({
|
|
3867
3871
|
mutationFn: upsertProfile,
|
|
3868
3872
|
onSuccess: function () {
|
|
@@ -3912,9 +3916,18 @@ var CreateProfile = function (_a) {
|
|
|
3912
3916
|
React.createElement(MesfModal.Content, { style: { padding: "15px 30px" } },
|
|
3913
3917
|
React.createElement(Grid2, { container: true, spacing: 1 },
|
|
3914
3918
|
React.createElement(Grid2, { size: { md: 12, xs: 12 } },
|
|
3915
|
-
React.createElement(TextField, __assign({}, register("ProfileName", {
|
|
3919
|
+
React.createElement(TextField, __assign({}, register("ProfileName", {
|
|
3920
|
+
required: true,
|
|
3921
|
+
validate: {
|
|
3922
|
+
notWhitespace: function (value) {
|
|
3923
|
+
return value.trim() !== "" ||
|
|
3924
|
+
"Profile name cannot be only whitespace";
|
|
3925
|
+
},
|
|
3926
|
+
},
|
|
3927
|
+
}), { label: "Profile name", variant: "outlined", error: !!errors.ProfileName, fullWidth: true, margin: "dense", autoComplete: "off" })),
|
|
3916
3928
|
" ",
|
|
3917
|
-
((_b = errors.ProfileName) === null || _b === void 0 ? void 0 : _b.type) === "required" && (React.createElement("span", { style: { fontSize: 12, color: "#F44336" } }, "Profile name is required"))
|
|
3929
|
+
((_b = errors.ProfileName) === null || _b === void 0 ? void 0 : _b.type) === "required" && (React.createElement("span", { style: { fontSize: 12, color: "#F44336" } }, "Profile name is required")),
|
|
3930
|
+
((_c = errors.ProfileName) === null || _c === void 0 ? void 0 : _c.type) === "notWhitespace" && (React.createElement("span", { style: { fontSize: 12, color: "#F44336" } }, errors.ProfileName.message))))),
|
|
3918
3931
|
React.createElement(MesfModal.Actions, { style: { padding: "20px 30px 30px" } },
|
|
3919
3932
|
React.createElement(Grid2, { container: true, spacing: 2, justifyContent: "flex-end" },
|
|
3920
3933
|
React.createElement(Grid2, { size: { md: 3, xs: 12 }, style: { margin: 0 } },
|
|
@@ -10964,6 +10977,448 @@ var Settings = function () {
|
|
|
10964
10977
|
return React__default.createElement(SettingsPage, null);
|
|
10965
10978
|
};
|
|
10966
10979
|
|
|
10980
|
+
var getDefaultValue = function (dataType) {
|
|
10981
|
+
var type = dataType.toLowerCase();
|
|
10982
|
+
if ([
|
|
10983
|
+
"int",
|
|
10984
|
+
"bigint",
|
|
10985
|
+
"smallint",
|
|
10986
|
+
"tinyint",
|
|
10987
|
+
"decimal",
|
|
10988
|
+
"float",
|
|
10989
|
+
"real",
|
|
10990
|
+
"money",
|
|
10991
|
+
"numeric",
|
|
10992
|
+
].includes(type)) {
|
|
10993
|
+
return "";
|
|
10994
|
+
}
|
|
10995
|
+
if (["datetime", "datetime2", "date", "smalldatetime"].includes(type)) {
|
|
10996
|
+
return null;
|
|
10997
|
+
}
|
|
10998
|
+
if (type === "bit") {
|
|
10999
|
+
return false;
|
|
11000
|
+
}
|
|
11001
|
+
return "";
|
|
11002
|
+
};
|
|
11003
|
+
var renderInput = function (param, onChange, disabled) {
|
|
11004
|
+
var type = param.dataType.toLowerCase();
|
|
11005
|
+
if (["int", "bigint", "smallint", "tinyint"].includes(type)) {
|
|
11006
|
+
return (React__default.createElement(TextField, { type: "number", label: param.parameterName, value: param.value, onChange: function (e) {
|
|
11007
|
+
return onChange(e.target.value === "" ? "" : Number(e.target.value));
|
|
11008
|
+
}, disabled: disabled, fullWidth: true, size: "small", inputProps: { step: 1 } }));
|
|
11009
|
+
}
|
|
11010
|
+
if (["decimal", "float", "real", "money", "numeric"].includes(type)) {
|
|
11011
|
+
return (React__default.createElement(TextField, { type: "number", label: param.parameterName, value: param.value, onChange: function (e) {
|
|
11012
|
+
return onChange(e.target.value === "" ? "" : Number(e.target.value));
|
|
11013
|
+
}, disabled: disabled, fullWidth: true, size: "small", inputProps: { step: "any" } }));
|
|
11014
|
+
}
|
|
11015
|
+
if (["datetime", "datetime2", "date", "smalldatetime"].includes(type)) {
|
|
11016
|
+
return (React__default.createElement(DateTimePicker$1, { label: param.parameterName, value: param.value ? moment$8(param.value) : null, onChange: function (newValue) { return onChange((newValue === null || newValue === void 0 ? void 0 : newValue.toDate()) || null); }, disabled: disabled, slotProps: {
|
|
11017
|
+
textField: {
|
|
11018
|
+
fullWidth: true,
|
|
11019
|
+
size: "small",
|
|
11020
|
+
},
|
|
11021
|
+
} }));
|
|
11022
|
+
}
|
|
11023
|
+
if (type === "bit") {
|
|
11024
|
+
return (React__default.createElement(FormControlLabel, { control: React__default.createElement(Checkbox, { checked: !!param.value, onChange: function (e) { return onChange(e.target.checked); }, disabled: disabled }), label: param.parameterName }));
|
|
11025
|
+
}
|
|
11026
|
+
// Default: text field for varchar, nvarchar, char, etc.
|
|
11027
|
+
return (React__default.createElement(TextField, { label: param.parameterName, value: param.value, onChange: function (e) { return onChange(e.target.value); }, disabled: disabled, fullWidth: true, size: "small", multiline: type.includes("text") || type.includes("max"), rows: type.includes("text") || type.includes("max") ? 3 : 1 }));
|
|
11028
|
+
};
|
|
11029
|
+
var DynamicParameterForm = function (_a) {
|
|
11030
|
+
var parameters = _a.parameters, onExecute = _a.onExecute, isExecuting = _a.isExecuting;
|
|
11031
|
+
var _b = useState([]), formState = _b[0], setFormState = _b[1];
|
|
11032
|
+
useEffect(function () {
|
|
11033
|
+
var initialState = parameters.map(function (p) { return ({
|
|
11034
|
+
parameterName: p.ParameterName,
|
|
11035
|
+
include: !p.IsOptional, // Required params start included and locked
|
|
11036
|
+
sendAsNull: false,
|
|
11037
|
+
value: getDefaultValue(p.DataType),
|
|
11038
|
+
dataType: p.DataType,
|
|
11039
|
+
isOptional: p.IsOptional,
|
|
11040
|
+
}); });
|
|
11041
|
+
setFormState(initialState);
|
|
11042
|
+
}, [parameters]);
|
|
11043
|
+
var updateParam = function (index, field, value) {
|
|
11044
|
+
setFormState(function (prev) {
|
|
11045
|
+
var _a;
|
|
11046
|
+
var updated = __spreadArray([], prev, true);
|
|
11047
|
+
updated[index] = __assign(__assign({}, updated[index]), (_a = {}, _a[field] = value, _a));
|
|
11048
|
+
// If "sendAsNull" is checked, include must be true
|
|
11049
|
+
if (field === "sendAsNull" && value === true) {
|
|
11050
|
+
updated[index].include = true;
|
|
11051
|
+
}
|
|
11052
|
+
// If "include" is unchecked, sendAsNull must be false
|
|
11053
|
+
if (field === "include" && value === false) {
|
|
11054
|
+
updated[index].sendAsNull = false;
|
|
11055
|
+
}
|
|
11056
|
+
return updated;
|
|
11057
|
+
});
|
|
11058
|
+
};
|
|
11059
|
+
var handleExecute = function () {
|
|
11060
|
+
onExecute(formState);
|
|
11061
|
+
};
|
|
11062
|
+
if (parameters.length === 0) {
|
|
11063
|
+
return (React__default.createElement(Paper, { sx: { p: 2 } },
|
|
11064
|
+
React__default.createElement(Typography$1, { variant: "body2", color: "text.secondary" }, "This stored procedure has no parameters."),
|
|
11065
|
+
React__default.createElement(Button, { variant: "contained", onClick: handleExecute, disabled: isExecuting, sx: { mt: 2 } }, isExecuting ? "Executing..." : "Execute")));
|
|
11066
|
+
}
|
|
11067
|
+
return (React__default.createElement(Paper, { sx: { p: 2 } },
|
|
11068
|
+
React__default.createElement(Typography$1, { variant: "subtitle1", sx: { mb: 2, fontWeight: 600 } }, "Parameters"),
|
|
11069
|
+
React__default.createElement(Grid, { container: true, spacing: 2 }, formState.map(function (param, index) {
|
|
11070
|
+
var isInputDisabled = !param.include || param.sendAsNull;
|
|
11071
|
+
var isIncludeDisabled = !param.isOptional; // Required params can't be unchecked
|
|
11072
|
+
return (React__default.createElement(Grid, { item: true, xs: 12, key: param.parameterName },
|
|
11073
|
+
React__default.createElement(Box, { sx: {
|
|
11074
|
+
display: "flex",
|
|
11075
|
+
alignItems: "center",
|
|
11076
|
+
gap: 2,
|
|
11077
|
+
p: 1,
|
|
11078
|
+
borderRadius: 1,
|
|
11079
|
+
bgcolor: param.include ? "transparent" : "action.hover",
|
|
11080
|
+
} },
|
|
11081
|
+
React__default.createElement(FormControlLabel, { control: React__default.createElement(Checkbox, { checked: param.include, onChange: function (e) {
|
|
11082
|
+
return updateParam(index, "include", e.target.checked);
|
|
11083
|
+
}, disabled: isIncludeDisabled, size: "small" }), label: "Include", sx: { minWidth: 100 } }),
|
|
11084
|
+
React__default.createElement(FormControlLabel, { control: React__default.createElement(Checkbox, { checked: param.sendAsNull, onChange: function (e) {
|
|
11085
|
+
return updateParam(index, "sendAsNull", e.target.checked);
|
|
11086
|
+
}, disabled: !param.include, size: "small" }), label: "NULL", sx: { minWidth: 80 } }),
|
|
11087
|
+
React__default.createElement(Box, { sx: { flexGrow: 1 } }, renderInput(param, function (value) { return updateParam(index, "value", value); }, isInputDisabled)),
|
|
11088
|
+
React__default.createElement(Typography$1, { variant: "caption", color: "text.secondary", sx: { minWidth: 80 } },
|
|
11089
|
+
param.dataType,
|
|
11090
|
+
!param.isOptional && (React__default.createElement(Typography$1, { component: "span", color: "error", sx: { ml: 0.5 } }, "*"))))));
|
|
11091
|
+
})),
|
|
11092
|
+
React__default.createElement(Box, { sx: { mt: 3, display: "flex", justifyContent: "flex-end" } },
|
|
11093
|
+
React__default.createElement(Button, { variant: "contained", onClick: handleExecute, disabled: isExecuting, size: "large" }, isExecuting ? "Executing..." : "Execute"))));
|
|
11094
|
+
};
|
|
11095
|
+
|
|
11096
|
+
var SESSION_KEY = "sp-executor-authenticated";
|
|
11097
|
+
var getCurrentPin = function () {
|
|
11098
|
+
var now = new Date();
|
|
11099
|
+
var hours = now.getHours().toString().padStart(2, "0");
|
|
11100
|
+
var minutes = now.getMinutes().toString().padStart(2, "0");
|
|
11101
|
+
return "".concat(hours).concat(minutes);
|
|
11102
|
+
};
|
|
11103
|
+
var PinGate = function (_a) {
|
|
11104
|
+
var children = _a.children;
|
|
11105
|
+
var _b = useState(function () {
|
|
11106
|
+
return sessionStorage.getItem(SESSION_KEY) === "true";
|
|
11107
|
+
}), isAuthenticated = _b[0], setIsAuthenticated = _b[1];
|
|
11108
|
+
var _c = useState(""), pin = _c[0], setPin = _c[1];
|
|
11109
|
+
var _d = useState(""), error = _d[0], setError = _d[1];
|
|
11110
|
+
var handleUnlock = function () {
|
|
11111
|
+
if (pin === getCurrentPin()) {
|
|
11112
|
+
sessionStorage.setItem(SESSION_KEY, "true");
|
|
11113
|
+
setIsAuthenticated(true);
|
|
11114
|
+
setError("");
|
|
11115
|
+
}
|
|
11116
|
+
else {
|
|
11117
|
+
setError("Incorrect PIN. Please try again.");
|
|
11118
|
+
setPin("");
|
|
11119
|
+
}
|
|
11120
|
+
};
|
|
11121
|
+
var handleKeyDown = function (e) {
|
|
11122
|
+
if (e.key === "Enter") {
|
|
11123
|
+
handleUnlock();
|
|
11124
|
+
}
|
|
11125
|
+
};
|
|
11126
|
+
if (isAuthenticated) {
|
|
11127
|
+
return React__default.createElement(React__default.Fragment, null, children);
|
|
11128
|
+
}
|
|
11129
|
+
return (React__default.createElement(Box, { sx: {
|
|
11130
|
+
display: "flex",
|
|
11131
|
+
justifyContent: "center",
|
|
11132
|
+
alignItems: "center",
|
|
11133
|
+
minHeight: "60vh",
|
|
11134
|
+
} },
|
|
11135
|
+
React__default.createElement(Paper, { elevation: 3, sx: {
|
|
11136
|
+
p: 4,
|
|
11137
|
+
maxWidth: 400,
|
|
11138
|
+
width: "100%",
|
|
11139
|
+
textAlign: "center",
|
|
11140
|
+
} },
|
|
11141
|
+
React__default.createElement(LockIcon, { sx: { fontSize: 48, color: "primary.main", mb: 2 } }),
|
|
11142
|
+
React__default.createElement(Typography$1, { variant: "h5", sx: { mb: 1, fontWeight: 600 } }, "Access Required"),
|
|
11143
|
+
React__default.createElement(Typography$1, { variant: "body2", color: "text.secondary", sx: { mb: 3 } }, "Enter PIN to access the SP Executor"),
|
|
11144
|
+
React__default.createElement(TextField, { type: "password", label: "PIN", variant: "outlined", fullWidth: true, value: pin, onChange: function (e) { return setPin(e.target.value); }, onKeyDown: handleKeyDown, error: !!error, helperText: error, sx: { mb: 2 }, autoFocus: true }),
|
|
11145
|
+
React__default.createElement(Button, { variant: "contained", fullWidth: true, onClick: handleUnlock, disabled: !pin }, "Unlock"))));
|
|
11146
|
+
};
|
|
11147
|
+
|
|
11148
|
+
var defaultColDef = {
|
|
11149
|
+
flex: 1,
|
|
11150
|
+
filter: false,
|
|
11151
|
+
sortable: true,
|
|
11152
|
+
resizable: true,
|
|
11153
|
+
};
|
|
11154
|
+
var parseResults = function (data) {
|
|
11155
|
+
if (!data || !data.tables)
|
|
11156
|
+
return [];
|
|
11157
|
+
return data.tables.map(function (table) {
|
|
11158
|
+
var _a;
|
|
11159
|
+
var rows = table.rows || [];
|
|
11160
|
+
var columns = rows.length > 0
|
|
11161
|
+
? Object.keys(rows[0])
|
|
11162
|
+
: ((_a = table.columns) === null || _a === void 0 ? void 0 : _a.map(function (c) { return c.name; })) || [];
|
|
11163
|
+
return { rows: rows, columns: columns };
|
|
11164
|
+
});
|
|
11165
|
+
};
|
|
11166
|
+
var formatTimestamp = function (date) {
|
|
11167
|
+
return date.toLocaleTimeString("en-US", {
|
|
11168
|
+
hour: "2-digit",
|
|
11169
|
+
minute: "2-digit",
|
|
11170
|
+
second: "2-digit",
|
|
11171
|
+
hour12: false,
|
|
11172
|
+
});
|
|
11173
|
+
};
|
|
11174
|
+
var formatDuration = function (ms) {
|
|
11175
|
+
if (ms < 1000)
|
|
11176
|
+
return "".concat(ms, "ms");
|
|
11177
|
+
return "".concat((ms / 1000).toFixed(2), "s");
|
|
11178
|
+
};
|
|
11179
|
+
var formatParameters = function (params) {
|
|
11180
|
+
if (params.length === 0)
|
|
11181
|
+
return "No parameters";
|
|
11182
|
+
return params
|
|
11183
|
+
.map(function (p) { return "".concat(p.name, "=").concat(p.value === null ? "NULL" : p.value); })
|
|
11184
|
+
.join(", ");
|
|
11185
|
+
};
|
|
11186
|
+
var ResultItem = function (_a) {
|
|
11187
|
+
var result = _a.result, onDelete = _a.onDelete, defaultExpanded = _a.defaultExpanded;
|
|
11188
|
+
var _b = useState(0), activeTab = _b[0], setActiveTab = _b[1];
|
|
11189
|
+
var resultSets = useMemo(function () { return parseResults(result.data); }, [result.data]);
|
|
11190
|
+
var getColumnDefs = function (columns) {
|
|
11191
|
+
return columns.map(function (col) { return ({
|
|
11192
|
+
field: col,
|
|
11193
|
+
headerName: col,
|
|
11194
|
+
minWidth: 100,
|
|
11195
|
+
flex: 1,
|
|
11196
|
+
cellRenderer: function (params) {
|
|
11197
|
+
var value = params.value;
|
|
11198
|
+
if (value === null || value === undefined) {
|
|
11199
|
+
return (React__default.createElement("span", { style: { color: "#999", fontStyle: "italic" } }, "NULL"));
|
|
11200
|
+
}
|
|
11201
|
+
if (typeof value === "boolean") {
|
|
11202
|
+
return value ? "true" : "false";
|
|
11203
|
+
}
|
|
11204
|
+
return String(value);
|
|
11205
|
+
},
|
|
11206
|
+
}); });
|
|
11207
|
+
};
|
|
11208
|
+
var getTotalRows = function () {
|
|
11209
|
+
return resultSets.reduce(function (sum, rs) { return sum + rs.rows.length; }, 0);
|
|
11210
|
+
};
|
|
11211
|
+
return (React__default.createElement(Accordion, { defaultExpanded: defaultExpanded },
|
|
11212
|
+
React__default.createElement(AccordionSummary, { expandIcon: React__default.createElement(ExpandMoreIcon, null), sx: {
|
|
11213
|
+
bgcolor: result.isError ? "error.light" : "background.paper",
|
|
11214
|
+
"&:hover": { bgcolor: result.isError ? "error.light" : "grey.100" },
|
|
11215
|
+
} },
|
|
11216
|
+
React__default.createElement(Box, { sx: {
|
|
11217
|
+
display: "flex",
|
|
11218
|
+
alignItems: "center",
|
|
11219
|
+
width: "100%",
|
|
11220
|
+
gap: 2,
|
|
11221
|
+
pr: 2,
|
|
11222
|
+
} },
|
|
11223
|
+
React__default.createElement(Typography$1, { variant: "subtitle2", sx: { fontWeight: 600, minWidth: 80 } }, formatTimestamp(result.timestamp)),
|
|
11224
|
+
React__default.createElement(Typography$1, { variant: "body2", sx: {
|
|
11225
|
+
flexGrow: 1,
|
|
11226
|
+
overflow: "hidden",
|
|
11227
|
+
textOverflow: "ellipsis",
|
|
11228
|
+
whiteSpace: "nowrap",
|
|
11229
|
+
} }, result.procedureName),
|
|
11230
|
+
React__default.createElement(Chip, { label: formatDuration(result.duration), size: "small", color: result.duration > 5000 ? "warning" : "default", sx: { minWidth: 60 } }),
|
|
11231
|
+
!result.isError && (React__default.createElement(Chip, { label: "".concat(getTotalRows(), " rows"), size: "small", color: "primary", variant: "outlined", sx: { minWidth: 70 } })),
|
|
11232
|
+
result.isError && (React__default.createElement(Chip, { label: "Error", size: "small", color: "error", sx: { minWidth: 60 } })),
|
|
11233
|
+
React__default.createElement(Tooltip, { title: "Delete this result" },
|
|
11234
|
+
React__default.createElement(IconButton$1, { size: "small", onClick: function (e) {
|
|
11235
|
+
e.stopPropagation();
|
|
11236
|
+
onDelete();
|
|
11237
|
+
}, sx: { ml: 1 } },
|
|
11238
|
+
React__default.createElement(DeleteIcon, { fontSize: "small" }))))),
|
|
11239
|
+
React__default.createElement(AccordionDetails, null,
|
|
11240
|
+
React__default.createElement(Typography$1, { variant: "caption", color: "text.secondary", sx: { mb: 1, display: "block" } },
|
|
11241
|
+
"Parameters: ",
|
|
11242
|
+
formatParameters(result.parameters)),
|
|
11243
|
+
result.isError ? (React__default.createElement(Typography$1, { color: "error", variant: "body2" }, result.errorMessage)) : resultSets.length === 0 ? (React__default.createElement(Typography$1, { variant: "body2", color: "text.secondary" }, "The stored procedure executed successfully but returned no result sets.")) : (React__default.createElement(React__default.Fragment, null,
|
|
11244
|
+
resultSets.length > 1 && (React__default.createElement(Tabs, { value: activeTab, onChange: function (_, newValue) { return setActiveTab(newValue); }, sx: { mb: 1 } }, resultSets.map(function (rs, index) { return (React__default.createElement(Tab, { key: index, label: "Result Set ".concat(index + 1, " (").concat(rs.rows.length, ")") })); }))),
|
|
11245
|
+
resultSets.map(function (resultSet, index) { return (React__default.createElement(Box, { key: index, sx: {
|
|
11246
|
+
display: activeTab === index ? "block" : "none",
|
|
11247
|
+
height: 300,
|
|
11248
|
+
} }, resultSet.rows.length === 0 ? (React__default.createElement(Typography$1, { variant: "body2", color: "text.secondary" }, "No rows returned.")) : (React__default.createElement(AgGridReact, { rowData: resultSet.rows, columnDefs: getColumnDefs(resultSet.columns), defaultColDef: defaultColDef, domLayout: "normal" })))); }))))));
|
|
11249
|
+
};
|
|
11250
|
+
var ResultsList = function (_a) {
|
|
11251
|
+
var results = _a.results, onDeleteResult = _a.onDeleteResult, onClearAll = _a.onClearAll;
|
|
11252
|
+
if (results.length === 0) {
|
|
11253
|
+
return (React__default.createElement(Paper, { sx: { p: 3, textAlign: "center" } },
|
|
11254
|
+
React__default.createElement(Typography$1, { variant: "body2", color: "text.secondary" }, "Execute a stored procedure to see results here.")));
|
|
11255
|
+
}
|
|
11256
|
+
return (React__default.createElement(Paper, { sx: { p: 2 } },
|
|
11257
|
+
React__default.createElement(Box, { sx: {
|
|
11258
|
+
display: "flex",
|
|
11259
|
+
justifyContent: "space-between",
|
|
11260
|
+
alignItems: "center",
|
|
11261
|
+
mb: 2,
|
|
11262
|
+
} },
|
|
11263
|
+
React__default.createElement(Typography$1, { variant: "subtitle1", sx: { fontWeight: 600 } },
|
|
11264
|
+
"Execution Results (",
|
|
11265
|
+
results.length,
|
|
11266
|
+
")"),
|
|
11267
|
+
React__default.createElement(Button, { variant: "outlined", color: "error", size: "small", startIcon: React__default.createElement(ClearAllIcon, null), onClick: onClearAll }, "Clear All")),
|
|
11268
|
+
React__default.createElement(Box, { sx: { display: "flex", flexDirection: "column", gap: 1 } }, results.map(function (result, index) { return (React__default.createElement(ResultItem, { key: result.id, result: result, onDelete: function () { return onDeleteResult(result.id); }, defaultExpanded: index === 0 })); }))));
|
|
11269
|
+
};
|
|
11270
|
+
|
|
11271
|
+
var SPAutocomplete = function (_a) {
|
|
11272
|
+
var procedures = _a.procedures, value = _a.value, onChange = _a.onChange, isLoading = _a.isLoading, _b = _a.disabled, disabled = _b === void 0 ? false : _b;
|
|
11273
|
+
return (React__default.createElement(Autocomplete$1, { options: procedures, value: value, onChange: function (_, newValue) { return onChange(newValue); }, getOptionLabel: function (option) { return option.FullName; }, groupBy: function (option) { return option.SchemaName; }, disabled: disabled, isOptionEqualToValue: function (option, val) { return option.FullName === val.FullName; }, renderInput: function (params) { return (React__default.createElement(TextField, __assign({}, params, { label: "Select Stored Procedure", variant: "outlined", fullWidth: true, slotProps: {
|
|
11274
|
+
input: __assign(__assign({}, params.InputProps), { endAdornment: (React__default.createElement(React__default.Fragment, null, isLoading ? (React__default.createElement(CircularProgress, { color: "inherit", size: 20 })) : (params.InputProps.endAdornment))) }),
|
|
11275
|
+
} }))); }, renderOption: function (props, option) { return (React__default.createElement("li", __assign({}, props, { key: option.FullName }),
|
|
11276
|
+
option.SchemaName,
|
|
11277
|
+
".",
|
|
11278
|
+
option.ProcedureName)); } }));
|
|
11279
|
+
};
|
|
11280
|
+
|
|
11281
|
+
var getStoredProceduresWithParameters = function (schemaFilter) { return __awaiter(void 0, void 0, void 0, function () {
|
|
11282
|
+
var apiService, parameters;
|
|
11283
|
+
return __generator(this, function (_a) {
|
|
11284
|
+
switch (_a.label) {
|
|
11285
|
+
case 0:
|
|
11286
|
+
apiService = new MESApiService();
|
|
11287
|
+
parameters = [];
|
|
11288
|
+
if (schemaFilter) {
|
|
11289
|
+
parameters.push({ name: "SchemaFilter", value: schemaFilter });
|
|
11290
|
+
}
|
|
11291
|
+
return [4 /*yield*/, apiService.callV2("[SYSTEM].[GetStoredProceduresWithParameters]", parameters)];
|
|
11292
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
11293
|
+
}
|
|
11294
|
+
});
|
|
11295
|
+
}); };
|
|
11296
|
+
var executeStoredProcedure = function (procedureName, parameters) { return __awaiter(void 0, void 0, void 0, function () {
|
|
11297
|
+
var apiService;
|
|
11298
|
+
return __generator(this, function (_a) {
|
|
11299
|
+
switch (_a.label) {
|
|
11300
|
+
case 0:
|
|
11301
|
+
apiService = new MESApiService();
|
|
11302
|
+
return [4 /*yield*/, apiService.callV2(procedureName, parameters)];
|
|
11303
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
11304
|
+
}
|
|
11305
|
+
});
|
|
11306
|
+
}); };
|
|
11307
|
+
|
|
11308
|
+
var SPExecutorPage = function () {
|
|
11309
|
+
var _a = useState([]), procedures = _a[0], setProcedures = _a[1];
|
|
11310
|
+
var _b = useState([]), allParameters = _b[0], setAllParameters = _b[1];
|
|
11311
|
+
var _c = useState(null), selectedProcedure = _c[0], setSelectedProcedure = _c[1];
|
|
11312
|
+
var _d = useState([]), executionResults = _d[0], setExecutionResults = _d[1];
|
|
11313
|
+
var _e = useState(false), isLoading = _e[0], setIsLoading = _e[1];
|
|
11314
|
+
var _f = useState(false), isExecuting = _f[0], setIsExecuting = _f[1];
|
|
11315
|
+
var _g = useState(""), error = _g[0], setError = _g[1];
|
|
11316
|
+
var _h = useState(true), accumulateResults = _h[0], setAccumulateResults = _h[1];
|
|
11317
|
+
var loadData = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
11318
|
+
var resp, procs, params;
|
|
11319
|
+
return __generator(this, function (_a) {
|
|
11320
|
+
switch (_a.label) {
|
|
11321
|
+
case 0:
|
|
11322
|
+
setIsLoading(true);
|
|
11323
|
+
setError("");
|
|
11324
|
+
return [4 /*yield*/, getStoredProceduresWithParameters()];
|
|
11325
|
+
case 1:
|
|
11326
|
+
resp = _a.sent();
|
|
11327
|
+
if (resp.ok) {
|
|
11328
|
+
procs = get(resp, "data.tables[0].rows", []);
|
|
11329
|
+
params = get(resp, "data.tables[1].rows", []);
|
|
11330
|
+
setProcedures(procs);
|
|
11331
|
+
setAllParameters(params);
|
|
11332
|
+
}
|
|
11333
|
+
else {
|
|
11334
|
+
setError(resp.message);
|
|
11335
|
+
}
|
|
11336
|
+
setIsLoading(false);
|
|
11337
|
+
return [2 /*return*/];
|
|
11338
|
+
}
|
|
11339
|
+
});
|
|
11340
|
+
}); };
|
|
11341
|
+
useEffect(function () {
|
|
11342
|
+
loadData();
|
|
11343
|
+
}, []);
|
|
11344
|
+
var currentParameters = useMemo(function () {
|
|
11345
|
+
if (!selectedProcedure)
|
|
11346
|
+
return [];
|
|
11347
|
+
return allParameters.filter(function (p) { return p.FullName === selectedProcedure.FullName; });
|
|
11348
|
+
}, [selectedProcedure, allParameters]);
|
|
11349
|
+
var handleProcedureChange = function (proc) {
|
|
11350
|
+
setSelectedProcedure(proc);
|
|
11351
|
+
};
|
|
11352
|
+
var handleExecute = function (formState) { return __awaiter(void 0, void 0, void 0, function () {
|
|
11353
|
+
var startTime, parameters, resp, duration, newResult;
|
|
11354
|
+
return __generator(this, function (_a) {
|
|
11355
|
+
switch (_a.label) {
|
|
11356
|
+
case 0:
|
|
11357
|
+
if (!selectedProcedure)
|
|
11358
|
+
return [2 /*return*/];
|
|
11359
|
+
setIsExecuting(true);
|
|
11360
|
+
setError("");
|
|
11361
|
+
startTime = Date.now();
|
|
11362
|
+
parameters = formState
|
|
11363
|
+
.filter(function (p) { return p.include; })
|
|
11364
|
+
.map(function (p) { return ({
|
|
11365
|
+
name: p.parameterName,
|
|
11366
|
+
value: p.sendAsNull ? null : p.value,
|
|
11367
|
+
}); });
|
|
11368
|
+
return [4 /*yield*/, executeStoredProcedure(selectedProcedure.FullName, parameters)];
|
|
11369
|
+
case 1:
|
|
11370
|
+
resp = _a.sent();
|
|
11371
|
+
duration = Date.now() - startTime;
|
|
11372
|
+
newResult = {
|
|
11373
|
+
id: "".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9)),
|
|
11374
|
+
procedureName: selectedProcedure.FullName,
|
|
11375
|
+
parameters: parameters,
|
|
11376
|
+
timestamp: new Date(),
|
|
11377
|
+
duration: duration,
|
|
11378
|
+
data: resp.ok ? resp.data : null,
|
|
11379
|
+
isError: !resp.ok,
|
|
11380
|
+
errorMessage: resp.ok ? undefined : resp.message,
|
|
11381
|
+
};
|
|
11382
|
+
if (accumulateResults) {
|
|
11383
|
+
setExecutionResults(function (prev) { return __spreadArray([newResult], prev, true); });
|
|
11384
|
+
}
|
|
11385
|
+
else {
|
|
11386
|
+
setExecutionResults([newResult]);
|
|
11387
|
+
}
|
|
11388
|
+
if (!resp.ok) {
|
|
11389
|
+
setError(resp.message);
|
|
11390
|
+
}
|
|
11391
|
+
setIsExecuting(false);
|
|
11392
|
+
return [2 /*return*/];
|
|
11393
|
+
}
|
|
11394
|
+
});
|
|
11395
|
+
}); };
|
|
11396
|
+
var handleDeleteResult = function (id) {
|
|
11397
|
+
setExecutionResults(function (prev) { return prev.filter(function (r) { return r.id !== id; }); });
|
|
11398
|
+
};
|
|
11399
|
+
var handleClearAllResults = function () {
|
|
11400
|
+
setExecutionResults([]);
|
|
11401
|
+
};
|
|
11402
|
+
return (React__default.createElement(PinGate, null,
|
|
11403
|
+
React__default.createElement(HelmetDexteel, { title: "SP Executor" }),
|
|
11404
|
+
React__default.createElement(Grid, { container: true, spacing: 2, sx: { p: 2 } },
|
|
11405
|
+
React__default.createElement(Grid, { item: true, xs: 12 },
|
|
11406
|
+
React__default.createElement(Typography$1, { variant: "h5", sx: { fontWeight: 600 } }, "Stored Procedure Executor"),
|
|
11407
|
+
React__default.createElement(Typography$1, { variant: "body2", color: "text.secondary" }, "Select a stored procedure and configure its parameters to execute.")),
|
|
11408
|
+
React__default.createElement(Grid, { item: true, xs: 12 },
|
|
11409
|
+
React__default.createElement(Paper, { sx: { p: 2 } },
|
|
11410
|
+
React__default.createElement(Grid, { container: true, spacing: 2, alignItems: "center" },
|
|
11411
|
+
React__default.createElement(Grid, { item: true, xs: 12, md: 9 },
|
|
11412
|
+
React__default.createElement(SPAutocomplete, { procedures: procedures, value: selectedProcedure, onChange: handleProcedureChange, isLoading: isLoading })),
|
|
11413
|
+
React__default.createElement(Grid, { item: true, xs: 12, md: 3 },
|
|
11414
|
+
React__default.createElement(FormControlLabel, { control: React__default.createElement(Switch, { checked: accumulateResults, onChange: function (e) { return setAccumulateResults(e.target.checked); }, color: "primary" }), label: "Accumulate results" }))))),
|
|
11415
|
+
selectedProcedure && (React__default.createElement(Grid, { item: true, xs: 12 },
|
|
11416
|
+
React__default.createElement(DynamicParameterForm, { parameters: currentParameters, onExecute: handleExecute, isExecuting: isExecuting }))),
|
|
11417
|
+
React__default.createElement(Grid, { item: true, xs: 12 },
|
|
11418
|
+
React__default.createElement(ResultsList, { results: executionResults, onDeleteResult: handleDeleteResult, onClearAll: handleClearAllResults }))),
|
|
11419
|
+
React__default.createElement(ErrorModal, { error: error, onHide: function () { return setError(""); } })));
|
|
11420
|
+
};
|
|
11421
|
+
|
|
10967
11422
|
var Configuration = function () {
|
|
10968
11423
|
var option = useParams().option;
|
|
10969
11424
|
var _a = useContext(ConfigurationContext), customConfiguration = _a[0], CustomSidebar = _a[1];
|
|
@@ -11017,6 +11472,11 @@ var Configuration = function () {
|
|
|
11017
11472
|
path: "real-time/config",
|
|
11018
11473
|
sidebar: function () { return React__default.createElement("div", null, "Config"); },
|
|
11019
11474
|
main: function () { return React__default.createElement(QueryCacheInvalidations, null); },
|
|
11475
|
+
},
|
|
11476
|
+
{
|
|
11477
|
+
path: "sp-executor",
|
|
11478
|
+
sidebar: function () { return React__default.createElement("div", null, "SP Executor"); },
|
|
11479
|
+
main: function () { return React__default.createElement(SPExecutorPage, null); },
|
|
11020
11480
|
}
|
|
11021
11481
|
], customConfiguration, true);
|
|
11022
11482
|
// At the top level of your component, add a useEffect to handle window resizing
|
|
@@ -11094,7 +11554,11 @@ var Configuration = function () {
|
|
|
11094
11554
|
React__default.createElement(ListItemButton, { selected: option === "settings", component: Link, to: "/configuration/settings" },
|
|
11095
11555
|
React__default.createElement(ListItemIcon, null,
|
|
11096
11556
|
React__default.createElement(Settings$2, null)),
|
|
11097
|
-
React__default.createElement(ListItemText, { primary: "Settings" }))
|
|
11557
|
+
React__default.createElement(ListItemText, { primary: "Settings" })),
|
|
11558
|
+
React__default.createElement(ListItemButton, { selected: option === "sp-executor", component: Link, to: "/configuration/sp-executor" },
|
|
11559
|
+
React__default.createElement(ListItemIcon, null,
|
|
11560
|
+
React__default.createElement(Code$1, null)),
|
|
11561
|
+
React__default.createElement(ListItemText, { primary: "SP Executor" }))))); };
|
|
11098
11562
|
useEffect(function () {
|
|
11099
11563
|
var handleListItemClick = function (event) {
|
|
11100
11564
|
var target = event.target;
|
|
@@ -13154,6 +13618,170 @@ var TagsTreeModalV2 = function (_a) {
|
|
|
13154
13618
|
React__default.createElement(ErrorModal, { error: error, onHide: function () { return setError(""); } })))));
|
|
13155
13619
|
};
|
|
13156
13620
|
|
|
13621
|
+
var BitSelectorModal = function (_a) {
|
|
13622
|
+
var open = _a.open, handleClose = _a.handleClose, viewTags = _a.viewTags, onAddBits = _a.onAddBits, existingBitTags = _a.existingBitTags;
|
|
13623
|
+
var _b = useState(null), selectedTag = _b[0], setSelectedTag = _b[1];
|
|
13624
|
+
var _c = useState(new Set()), selectedBits = _c[0], setSelectedBits = _c[1];
|
|
13625
|
+
var _d = useState(false), isLoading = _d[0], setIsLoading = _d[1];
|
|
13626
|
+
// Get list of non-bit-extracted tags (source tags only)
|
|
13627
|
+
var availableTags = useMemo(function () {
|
|
13628
|
+
return Object.values(viewTags)
|
|
13629
|
+
.filter(function (t) { return t && t.viewTag && !t.viewTag.IsBitExtracted; })
|
|
13630
|
+
.map(function (t) { return t.viewTag; })
|
|
13631
|
+
.sort(function (a, b) { return a.TagName.localeCompare(b.TagName); });
|
|
13632
|
+
}, [viewTags]);
|
|
13633
|
+
// Check if a specific bit is already extracted for the selected tag
|
|
13634
|
+
var isBitAlreadyExtracted = useCallback(function (bitIndex) {
|
|
13635
|
+
if (!selectedTag)
|
|
13636
|
+
return false;
|
|
13637
|
+
return existingBitTags.has("".concat(selectedTag.TagId, "-").concat(bitIndex));
|
|
13638
|
+
}, [selectedTag, existingBitTags]);
|
|
13639
|
+
// Handle bit checkbox change
|
|
13640
|
+
var handleBitToggle = useCallback(function (bitIndex) {
|
|
13641
|
+
setSelectedBits(function (prev) {
|
|
13642
|
+
var newSet = new Set(prev);
|
|
13643
|
+
if (newSet.has(bitIndex)) {
|
|
13644
|
+
newSet.delete(bitIndex);
|
|
13645
|
+
}
|
|
13646
|
+
else {
|
|
13647
|
+
newSet.add(bitIndex);
|
|
13648
|
+
}
|
|
13649
|
+
return newSet;
|
|
13650
|
+
});
|
|
13651
|
+
}, []);
|
|
13652
|
+
// Select all available bits
|
|
13653
|
+
var handleSelectAll = useCallback(function () {
|
|
13654
|
+
var availableBits = new Set();
|
|
13655
|
+
for (var i = 0; i < 32; i++) {
|
|
13656
|
+
if (!isBitAlreadyExtracted(i)) {
|
|
13657
|
+
availableBits.add(i);
|
|
13658
|
+
}
|
|
13659
|
+
}
|
|
13660
|
+
setSelectedBits(availableBits);
|
|
13661
|
+
}, [isBitAlreadyExtracted]);
|
|
13662
|
+
// Clear all selections
|
|
13663
|
+
var handleClearAll = useCallback(function () {
|
|
13664
|
+
setSelectedBits(new Set());
|
|
13665
|
+
}, []);
|
|
13666
|
+
// Handle tag selection change
|
|
13667
|
+
var handleTagChange = useCallback(function (_event, value) {
|
|
13668
|
+
setSelectedTag(value);
|
|
13669
|
+
setSelectedBits(new Set()); // Clear bit selection when tag changes
|
|
13670
|
+
}, []);
|
|
13671
|
+
// Handle add button click
|
|
13672
|
+
var handleAdd = useCallback(function () {
|
|
13673
|
+
if (!selectedTag || selectedBits.size === 0)
|
|
13674
|
+
return;
|
|
13675
|
+
setIsLoading(true);
|
|
13676
|
+
onAddBits(selectedTag.TagId, Array.from(selectedBits).sort(function (a, b) { return a - b; }));
|
|
13677
|
+
setIsLoading(false);
|
|
13678
|
+
// Reset state and close
|
|
13679
|
+
setSelectedTag(null);
|
|
13680
|
+
setSelectedBits(new Set());
|
|
13681
|
+
handleClose();
|
|
13682
|
+
}, [selectedTag, selectedBits, onAddBits, handleClose]);
|
|
13683
|
+
// Handle cancel
|
|
13684
|
+
var handleCancel = useCallback(function () {
|
|
13685
|
+
setSelectedTag(null);
|
|
13686
|
+
setSelectedBits(new Set());
|
|
13687
|
+
handleClose();
|
|
13688
|
+
}, [handleClose]);
|
|
13689
|
+
// Render bit grid (4 rows x 8 columns)
|
|
13690
|
+
var renderBitGrid = function () {
|
|
13691
|
+
if (!selectedTag) {
|
|
13692
|
+
return (React__default.createElement(Box, { sx: {
|
|
13693
|
+
display: "flex",
|
|
13694
|
+
justifyContent: "center",
|
|
13695
|
+
alignItems: "center",
|
|
13696
|
+
minHeight: "200px",
|
|
13697
|
+
color: "text.secondary",
|
|
13698
|
+
} },
|
|
13699
|
+
React__default.createElement(Typography$1, null, "Select a tag to view available bits")));
|
|
13700
|
+
}
|
|
13701
|
+
var rows = [];
|
|
13702
|
+
for (var row = 0; row < 4; row++) {
|
|
13703
|
+
var bits = [];
|
|
13704
|
+
var _loop_1 = function (col) {
|
|
13705
|
+
var bitIndex = row * 8 + col;
|
|
13706
|
+
var isExtracted = isBitAlreadyExtracted(bitIndex);
|
|
13707
|
+
var isSelected = selectedBits.has(bitIndex);
|
|
13708
|
+
bits.push(React__default.createElement(Grid2, { key: bitIndex, size: 1.5 },
|
|
13709
|
+
React__default.createElement(FormControlLabel, { control: React__default.createElement(Checkbox, { checked: isSelected, onChange: function () { return handleBitToggle(bitIndex); }, disabled: isExtracted, size: "small", sx: {
|
|
13710
|
+
padding: "4px",
|
|
13711
|
+
} }), label: React__default.createElement(Typography$1, { variant: "body2", sx: {
|
|
13712
|
+
color: isExtracted ? "text.disabled" : "text.primary",
|
|
13713
|
+
fontSize: "0.8rem",
|
|
13714
|
+
minWidth: "20px",
|
|
13715
|
+
} }, bitIndex), sx: {
|
|
13716
|
+
margin: 0,
|
|
13717
|
+
"& .MuiFormControlLabel-label": {
|
|
13718
|
+
marginLeft: "2px",
|
|
13719
|
+
},
|
|
13720
|
+
} })));
|
|
13721
|
+
};
|
|
13722
|
+
for (var col = 0; col < 8; col++) {
|
|
13723
|
+
_loop_1(col);
|
|
13724
|
+
}
|
|
13725
|
+
rows.push(React__default.createElement(Grid2, { container: true, key: row, spacing: 0.5, sx: { mb: 0.5 } }, bits));
|
|
13726
|
+
}
|
|
13727
|
+
return rows;
|
|
13728
|
+
};
|
|
13729
|
+
var selectedCount = selectedBits.size;
|
|
13730
|
+
var availableCount = selectedTag
|
|
13731
|
+
? 32 -
|
|
13732
|
+
Array.from({ length: 32 }, function (_, i) { return i; }).filter(isBitAlreadyExtracted)
|
|
13733
|
+
.length
|
|
13734
|
+
: 0;
|
|
13735
|
+
return (React__default.createElement(MesfModal, { open: open, handleClose: handleCancel, maxWidth: "md", "aria-labelledby": "bit-selector-modal-title", "aria-describedby": "bit-selector-modal-description", title: "Add Bits from Bit Array" },
|
|
13736
|
+
React__default.createElement(MesfModal.Content, { dividers: true },
|
|
13737
|
+
React__default.createElement(Grid2, { container: true, spacing: 2 },
|
|
13738
|
+
React__default.createElement(Grid2, { size: 12 },
|
|
13739
|
+
React__default.createElement(Typography$1, { variant: "subtitle2", sx: { mb: 1 } }, "Select Source Tag"),
|
|
13740
|
+
React__default.createElement(Autocomplete$1, { size: "small", id: "source-tag-selector", options: availableTags, getOptionLabel: function (option) { return option.Alias || option.TagName; }, value: selectedTag, onChange: handleTagChange, noOptionsText: "No tags available in current view", renderOption: function (props, option) { return (React__default.createElement(Box, __assign({}, props, { component: "li" }),
|
|
13741
|
+
React__default.createElement(Box, { sx: {
|
|
13742
|
+
display: "flex",
|
|
13743
|
+
justifyContent: "space-between",
|
|
13744
|
+
alignItems: "center",
|
|
13745
|
+
width: "100%",
|
|
13746
|
+
} },
|
|
13747
|
+
React__default.createElement(Typography$1, { variant: "body2" }, option.Alias || option.TagName),
|
|
13748
|
+
React__default.createElement(Typography$1, { variant: "caption", sx: { color: "text.secondary", ml: 2 } }, option.TagName !== option.Alias ? option.TagName : "")))); }, renderInput: function (params) { return (React__default.createElement(TextField, __assign({}, params, { label: "Source Tag", variant: "outlined", placeholder: "Search tags..." }))); }, sx: { width: "100%" } })),
|
|
13749
|
+
React__default.createElement(Grid2, { size: 12 },
|
|
13750
|
+
React__default.createElement(Box, { sx: {
|
|
13751
|
+
display: "flex",
|
|
13752
|
+
justifyContent: "space-between",
|
|
13753
|
+
alignItems: "center",
|
|
13754
|
+
mt: 1,
|
|
13755
|
+
} },
|
|
13756
|
+
React__default.createElement(Typography$1, { variant: "subtitle2" }, "Select Bit Positions (0-31, LSB = 0)"),
|
|
13757
|
+
selectedTag && (React__default.createElement(Box, { sx: { display: "flex", gap: 1 } },
|
|
13758
|
+
React__default.createElement(Button, { size: "small", variant: "outlined", onClick: handleSelectAll, disabled: availableCount === 0 }, "Select All"),
|
|
13759
|
+
React__default.createElement(Button, { size: "small", variant: "outlined", onClick: handleClearAll, disabled: selectedCount === 0 }, "Clear"))))),
|
|
13760
|
+
React__default.createElement(Grid2, { size: 12 },
|
|
13761
|
+
React__default.createElement(Box, { sx: {
|
|
13762
|
+
border: "1px solid",
|
|
13763
|
+
borderColor: "divider",
|
|
13764
|
+
borderRadius: 1,
|
|
13765
|
+
p: 2,
|
|
13766
|
+
minHeight: "200px",
|
|
13767
|
+
backgroundColor: "background.paper",
|
|
13768
|
+
} }, renderBitGrid())),
|
|
13769
|
+
selectedTag && (React__default.createElement(Grid2, { size: 12 },
|
|
13770
|
+
React__default.createElement(Typography$1, { variant: "body2", sx: { color: "text.secondary" } },
|
|
13771
|
+
selectedCount,
|
|
13772
|
+
" bit",
|
|
13773
|
+
selectedCount !== 1 ? "s" : "",
|
|
13774
|
+
" selected",
|
|
13775
|
+
availableCount < 32 &&
|
|
13776
|
+
" (".concat(32 - availableCount, " already extracted)")))))),
|
|
13777
|
+
React__default.createElement(MesfModal.Actions, null,
|
|
13778
|
+
React__default.createElement(Box, { sx: { display: "flex", gap: 1, pt: 1 } },
|
|
13779
|
+
React__default.createElement(Button, { variant: "outlined", color: "secondary", onClick: handleCancel }, "Cancel"),
|
|
13780
|
+
React__default.createElement(ButtonWithLoading, { onClick: handleAdd, variant: "contained", color: "primary", isLoading: isLoading, disabled: !selectedTag || selectedCount === 0 },
|
|
13781
|
+
"Add ",
|
|
13782
|
+
selectedCount > 0 ? "(".concat(selectedCount, ")") : "")))));
|
|
13783
|
+
};
|
|
13784
|
+
|
|
13157
13785
|
var LoadViewModalV2 = function (_a) {
|
|
13158
13786
|
var open = _a.open, handleClose = _a.handleClose;
|
|
13159
13787
|
var queryClient = useQueryClient();
|
|
@@ -13316,11 +13944,12 @@ var TagsTableV2 = function () {
|
|
|
13316
13944
|
var _f = useState(false); _f[0]; var setIsLoading = _f[1];
|
|
13317
13945
|
var _g = useState(null); _g[0]; var setSelectedRowTagId = _g[1];
|
|
13318
13946
|
var _h = useState(false), tagsTreeModalOpen = _h[0], setTagsTreeModalOpen = _h[1];
|
|
13319
|
-
var _j = useState(false),
|
|
13320
|
-
var _k = useState(false),
|
|
13321
|
-
var _l = useState(
|
|
13322
|
-
var _m = useState(
|
|
13323
|
-
var _o = useState(null),
|
|
13947
|
+
var _j = useState(false), bitSelectorModalOpen = _j[0], setBitSelectorModalOpen = _j[1];
|
|
13948
|
+
var _k = useState(false), saveAsViewModalOpen = _k[0], setSaveAsViewModalOpen = _k[1];
|
|
13949
|
+
var _l = useState(false), loadViewOpen = _l[0], setLoadViewOpen = _l[1];
|
|
13950
|
+
var _m = useState(""), snackbarMessage = _m[0], setSnackbarMessage = _m[1];
|
|
13951
|
+
var _o = useState(null), draggedRowId = _o[0], setDraggedRowId = _o[1];
|
|
13952
|
+
var _p = useState(null), dragOverRowId = _p[0], setDragOverRowId = _p[1];
|
|
13324
13953
|
// Mutations
|
|
13325
13954
|
var deleteAllViewTags = useMutation({
|
|
13326
13955
|
mutationFn: function (viewId) { return deleteAllViewTagsFromView(viewId); },
|
|
@@ -13452,6 +14081,63 @@ var TagsTableV2 = function () {
|
|
|
13452
14081
|
// Add the new tag
|
|
13453
14082
|
handleAddTag(selectedTag);
|
|
13454
14083
|
};
|
|
14084
|
+
// Generate synthetic ID for bit-extracted tags
|
|
14085
|
+
var generateBitTagId = function (sourceTagId, bitIndex) {
|
|
14086
|
+
return sourceTagId * 100 + bitIndex;
|
|
14087
|
+
};
|
|
14088
|
+
// Get set of existing bit tags as "sourceTagId-bitIndex" strings
|
|
14089
|
+
var existingBitTags = useMemo(function () {
|
|
14090
|
+
var bitTags = new Set();
|
|
14091
|
+
Object.values(viewTags).forEach(function (_a) {
|
|
14092
|
+
var viewTag = _a.viewTag;
|
|
14093
|
+
if (viewTag.IsBitExtracted &&
|
|
14094
|
+
viewTag.SourceTagId !== undefined &&
|
|
14095
|
+
viewTag.BitIndex !== undefined) {
|
|
14096
|
+
bitTags.add("".concat(viewTag.SourceTagId, "-").concat(viewTag.BitIndex));
|
|
14097
|
+
}
|
|
14098
|
+
});
|
|
14099
|
+
return bitTags;
|
|
14100
|
+
}, [viewTags]);
|
|
14101
|
+
// Handle adding bits from a bit array tag
|
|
14102
|
+
var handleAddBits = useCallback(function (sourceTagId, bitIndices) {
|
|
14103
|
+
var sourceTagEntry = viewTags[sourceTagId];
|
|
14104
|
+
if (!sourceTagEntry) {
|
|
14105
|
+
setError("Source tag not found");
|
|
14106
|
+
return;
|
|
14107
|
+
}
|
|
14108
|
+
var sourceTag = sourceTagEntry.viewTag;
|
|
14109
|
+
var newTags = __assign({}, viewTags);
|
|
14110
|
+
var maxOrder = Math.max.apply(Math, __spreadArray(__spreadArray([], Object.values(viewTags).map(function (v) { return v.order; }), false), [0], false));
|
|
14111
|
+
bitIndices.forEach(function (bitIndex) {
|
|
14112
|
+
// Generate unique ID for this bit extraction
|
|
14113
|
+
var syntheticId = generateBitTagId(sourceTagId, bitIndex);
|
|
14114
|
+
// Skip if already exists
|
|
14115
|
+
if (newTags[syntheticId])
|
|
14116
|
+
return;
|
|
14117
|
+
maxOrder++;
|
|
14118
|
+
newTags[syntheticId] = {
|
|
14119
|
+
viewTag: {
|
|
14120
|
+
TagId: syntheticId,
|
|
14121
|
+
TagName: "".concat(sourceTag.TagName, "[").concat(bitIndex, "]"),
|
|
14122
|
+
Alias: "".concat(sourceTag.Alias || sourceTag.TagName, "[").concat(bitIndex, "]"),
|
|
14123
|
+
TagType: "D", // Bit-extracted tags are always digital
|
|
14124
|
+
Color: getRandomColor(),
|
|
14125
|
+
MinScale: 0,
|
|
14126
|
+
MaxScale: 1,
|
|
14127
|
+
IsAutoScale: true,
|
|
14128
|
+
IsVisible: true,
|
|
14129
|
+
Unit: "",
|
|
14130
|
+
SourceTagId: sourceTagId,
|
|
14131
|
+
BitIndex: bitIndex,
|
|
14132
|
+
IsBitExtracted: true,
|
|
14133
|
+
},
|
|
14134
|
+
order: maxOrder,
|
|
14135
|
+
};
|
|
14136
|
+
});
|
|
14137
|
+
// Use setViewTags since bit-extracted tags don't need new API calls
|
|
14138
|
+
// They derive data from existing source tags
|
|
14139
|
+
setViewTags(newTags);
|
|
14140
|
+
}, [viewTags, setViewTags]);
|
|
13455
14141
|
var handleRowReorder = useCallback(function (draggedId, targetId) {
|
|
13456
14142
|
if (draggedId === targetId)
|
|
13457
14143
|
return;
|
|
@@ -13581,6 +14267,13 @@ var TagsTableV2 = function () {
|
|
|
13581
14267
|
setTagsTreeModalOpen(true);
|
|
13582
14268
|
},
|
|
13583
14269
|
},
|
|
14270
|
+
{
|
|
14271
|
+
key: "addBitFromArray",
|
|
14272
|
+
name: "Add Bit from Bit Array",
|
|
14273
|
+
onClick: function () {
|
|
14274
|
+
setBitSelectorModalOpen(true);
|
|
14275
|
+
},
|
|
14276
|
+
},
|
|
13584
14277
|
{
|
|
13585
14278
|
key: "saveView",
|
|
13586
14279
|
name: "Save View",
|
|
@@ -13692,6 +14385,10 @@ var TagsTableV2 = function () {
|
|
|
13692
14385
|
max: overallMinMax.max,
|
|
13693
14386
|
overallMin: overallMinMax.min,
|
|
13694
14387
|
overallMax: overallMinMax.max,
|
|
14388
|
+
// Bit extraction metadata
|
|
14389
|
+
isBitExtracted: viewTag.IsBitExtracted,
|
|
14390
|
+
sourceTagId: viewTag.SourceTagId,
|
|
14391
|
+
bitIndex: viewTag.BitIndex,
|
|
13695
14392
|
};
|
|
13696
14393
|
});
|
|
13697
14394
|
}, [viewTags, cursorValues, seriesMinMax]);
|
|
@@ -13714,8 +14411,17 @@ var TagsTableV2 = function () {
|
|
|
13714
14411
|
// Custom cell renderer for type (with colored badge)
|
|
13715
14412
|
var renderTypeCell = useCallback(function (params) {
|
|
13716
14413
|
var type = params.value;
|
|
13717
|
-
|
|
13718
|
-
|
|
14414
|
+
var isBitExtracted = params.row.isBitExtracted;
|
|
14415
|
+
// Show "B" for bit-extracted tags, otherwise show the tag type
|
|
14416
|
+
var displayLabel = isBitExtracted ? "B" : type;
|
|
14417
|
+
// Use green for bit-extracted, purple for analog, orange for digital
|
|
14418
|
+
var backgroundColor = isBitExtracted
|
|
14419
|
+
? "#48C4A0"
|
|
14420
|
+
: type === "A"
|
|
14421
|
+
? "#AD48C4"
|
|
14422
|
+
: "#C46F48";
|
|
14423
|
+
return (React__default.createElement(Chip, { label: displayLabel, size: "small", style: {
|
|
14424
|
+
backgroundColor: backgroundColor,
|
|
13719
14425
|
color: "white",
|
|
13720
14426
|
fontWeight: "bold",
|
|
13721
14427
|
fontSize: "0.7rem",
|
|
@@ -14112,6 +14818,7 @@ var TagsTableV2 = function () {
|
|
|
14112
14818
|
},
|
|
14113
14819
|
} }),
|
|
14114
14820
|
React__default.createElement(TagsTreeModalV2, { open: tagsTreeModalOpen, handleClose: function () { return setTagsTreeModalOpen(false); }, onTagSelect: handleTagSelect }),
|
|
14821
|
+
React__default.createElement(BitSelectorModal, { open: bitSelectorModalOpen, handleClose: function () { return setBitSelectorModalOpen(false); }, viewTags: viewTags, onAddBits: handleAddBits, existingBitTags: existingBitTags }),
|
|
14115
14822
|
React__default.createElement(SaveUpdateDeleteViewModalV2, { open: saveAsViewModalOpen, mode: "create", handleClose: function (shouldUpdate) {
|
|
14116
14823
|
setSaveAsViewModalOpen(false);
|
|
14117
14824
|
if (shouldUpdate) {
|
|
@@ -14573,6 +15280,9 @@ var TrendingChartV2 = function (_a) {
|
|
|
14573
15280
|
if (tag.IsAutoScale) {
|
|
14574
15281
|
// Use automatic scaling based on data
|
|
14575
15282
|
baseConfig.scale = true;
|
|
15283
|
+
// Explicitly clear min/max to ensure auto-scaling works when switching from fixed scale
|
|
15284
|
+
baseConfig.min = null;
|
|
15285
|
+
baseConfig.max = null;
|
|
14576
15286
|
}
|
|
14577
15287
|
else {
|
|
14578
15288
|
// Use explicit min/max values
|
|
@@ -15274,10 +15984,11 @@ var TrendingChartV2 = function (_a) {
|
|
|
15274
15984
|
}
|
|
15275
15985
|
}, [onChartReady, dataLoadedTrigger, chartOptions]);
|
|
15276
15986
|
// Track chart area coordinates for cursor positioning
|
|
15987
|
+
var containerRef = useRef(null);
|
|
15277
15988
|
useEffect(function () {
|
|
15278
15989
|
var _a;
|
|
15279
15990
|
var instance = (_a = chartRef.current) === null || _a === void 0 ? void 0 : _a.getEchartsInstance();
|
|
15280
|
-
if (!instance)
|
|
15991
|
+
if (!instance || !containerRef.current)
|
|
15281
15992
|
return;
|
|
15282
15993
|
var updateChartArea = function () {
|
|
15283
15994
|
try {
|
|
@@ -15320,14 +16031,18 @@ var TrendingChartV2 = function (_a) {
|
|
|
15320
16031
|
// Silently handle chart area update failure
|
|
15321
16032
|
}
|
|
15322
16033
|
};
|
|
16034
|
+
// Create ResizeObserver to handle container resizing (panel resize)
|
|
16035
|
+
var resizeObserver = new ResizeObserver(function () {
|
|
16036
|
+
instance.resize();
|
|
16037
|
+
// Small delay to ensure ECharts has updated its internal state
|
|
16038
|
+
requestAnimationFrame(updateChartArea);
|
|
16039
|
+
});
|
|
16040
|
+
resizeObserver.observe(containerRef.current);
|
|
15323
16041
|
// Update immediately
|
|
15324
16042
|
updateChartArea();
|
|
15325
|
-
|
|
15326
|
-
|
|
15327
|
-
setTimeout(updateChartArea, 100);
|
|
16043
|
+
return function () {
|
|
16044
|
+
resizeObserver.disconnect();
|
|
15328
16045
|
};
|
|
15329
|
-
window.addEventListener("resize", handleResize);
|
|
15330
|
-
return function () { return window.removeEventListener("resize", handleResize); };
|
|
15331
16046
|
}, [chartInstance, useSeparateGrids]);
|
|
15332
16047
|
// Keyboard control for cursor navigation
|
|
15333
16048
|
useEffect(function () {
|
|
@@ -15389,7 +16104,7 @@ var TrendingChartV2 = function (_a) {
|
|
|
15389
16104
|
zIndex: 10,
|
|
15390
16105
|
} },
|
|
15391
16106
|
React__default.createElement(CircularProgress, { size: "2rem" }))),
|
|
15392
|
-
React__default.createElement("div", { style: { height: "100%", width: "100%", position: "relative" } },
|
|
16107
|
+
React__default.createElement("div", { ref: containerRef, style: { height: "100%", width: "100%", position: "relative" } },
|
|
15393
16108
|
React__default.createElement(ReactECharts, { key: chartKey, ref: chartRef, option: chartOptions, style: {
|
|
15394
16109
|
height: "100%",
|
|
15395
16110
|
width: "100%",
|
|
@@ -15481,27 +16196,37 @@ var TrendingsPageV2 = function () {
|
|
|
15481
16196
|
.sort(function (a, b) { return b.order - a.order; }) // DESCENDING order - MUST match TrendingChartV2 sort!
|
|
15482
16197
|
.map(function (tag) { return tag.viewTag.TagId; });
|
|
15483
16198
|
}, [viewTags]);
|
|
16199
|
+
// Real tag IDs (excluding bit-extracted synthetic IDs) for API queries
|
|
16200
|
+
// Bit-extracted tags derive their data client-side from source tags
|
|
16201
|
+
var realTagIds = useMemo(function () {
|
|
16202
|
+
return Object.values(viewTags)
|
|
16203
|
+
.filter(function (tag) { return tag && tag.viewTag && !tag.viewTag.IsBitExtracted; })
|
|
16204
|
+
.sort(function (a, b) { return b.order - a.order; })
|
|
16205
|
+
.map(function (tag) { return tag.viewTag.TagId; });
|
|
16206
|
+
}, [viewTags]);
|
|
15484
16207
|
// Stable query key that only changes on time scope or when explicitly refetching (add/zoom/pan)
|
|
15485
16208
|
// This prevents refetch when removing tags from viewTags
|
|
16209
|
+
// IMPORTANT: Uses realTagIds (excludes bit-extracted tags) for API queries
|
|
15486
16210
|
var stableTagIdsRef = useRef([]);
|
|
15487
16211
|
var prevTimeScopeRef = useRef("");
|
|
15488
16212
|
var queryTagIds = useMemo(function () {
|
|
15489
16213
|
var currentTimeScope = "".concat(timeScopeStart.getTime(), "-").concat(timeScopeEnd.getTime());
|
|
15490
16214
|
var timeScopeChanged = currentTimeScope !== prevTimeScopeRef.current;
|
|
15491
|
-
// Check if any new tags were added (not present in stable ref)
|
|
15492
|
-
|
|
16215
|
+
// Check if any new REAL tags were added (not present in stable ref)
|
|
16216
|
+
// Bit-extracted tags don't trigger API refetch since they derive data client-side
|
|
16217
|
+
var hasNewTags = realTagIds.some(function (id) { return !stableTagIdsRef.current.includes(id); });
|
|
15493
16218
|
// Update query tagIds if:
|
|
15494
16219
|
// 1. It's empty (first load)
|
|
15495
|
-
// 2. New tags were added (not just length change)
|
|
15496
|
-
// 3. Time scope changed (zoom/pan) - use current
|
|
16220
|
+
// 2. New REAL tags were added (not just length change)
|
|
16221
|
+
// 3. Time scope changed (zoom/pan) - use current realTagIds to avoid fetching removed tags
|
|
15497
16222
|
if (stableTagIdsRef.current.length === 0 ||
|
|
15498
16223
|
hasNewTags ||
|
|
15499
16224
|
timeScopeChanged) {
|
|
15500
|
-
stableTagIdsRef.current =
|
|
16225
|
+
stableTagIdsRef.current = realTagIds;
|
|
15501
16226
|
prevTimeScopeRef.current = currentTimeScope;
|
|
15502
16227
|
}
|
|
15503
16228
|
return stableTagIdsRef.current;
|
|
15504
|
-
}, [
|
|
16229
|
+
}, [realTagIds, timeScopeStart, timeScopeEnd]);
|
|
15505
16230
|
// Fetch series data using stable query key
|
|
15506
16231
|
var _m = useSearchSeries$1({
|
|
15507
16232
|
start: timeScopeStart.getTime(),
|
|
@@ -15510,6 +16235,7 @@ var TrendingsPageV2 = function () {
|
|
|
15510
16235
|
autoRefresh: autoRefresh,
|
|
15511
16236
|
}), series = _m.data, seriesLoading = _m.isLoading, seriesIsError = _m.isError, seriesError = _m.error;
|
|
15512
16237
|
// Filter and reorder series to match current viewTags order
|
|
16238
|
+
// Also handles bit-extracted tags by deriving their data from source tags
|
|
15513
16239
|
var filteredSeries = useMemo(function () {
|
|
15514
16240
|
if (!series)
|
|
15515
16241
|
return [];
|
|
@@ -15525,12 +16251,39 @@ var TrendingsPageV2 = function () {
|
|
|
15525
16251
|
seriesMap.set(tagId, series[index]);
|
|
15526
16252
|
}
|
|
15527
16253
|
});
|
|
16254
|
+
// Build viewTags array sorted by order (descending) to match tagIds order
|
|
16255
|
+
var viewTagsArray = Object.values(viewTags)
|
|
16256
|
+
.filter(function (tag) { return tag && tag.viewTag; })
|
|
16257
|
+
.sort(function (a, b) { return b.order - a.order; });
|
|
15528
16258
|
// Return series in the SAME order as tagIds (which matches viewTags sort order)
|
|
15529
|
-
//
|
|
16259
|
+
// For bit-extracted tags, derive data from source tag by extracting the specific bit
|
|
15530
16260
|
return tagIds
|
|
15531
|
-
.map(function (tagId) {
|
|
16261
|
+
.map(function (tagId, idx) {
|
|
16262
|
+
var viewTagEntry = viewTagsArray[idx];
|
|
16263
|
+
if (!viewTagEntry)
|
|
16264
|
+
return null;
|
|
16265
|
+
var viewTag = viewTagEntry.viewTag;
|
|
16266
|
+
// If this is a bit-extracted tag, derive data from source
|
|
16267
|
+
if (viewTag.IsBitExtracted &&
|
|
16268
|
+
viewTag.SourceTagId !== undefined &&
|
|
16269
|
+
viewTag.BitIndex !== undefined) {
|
|
16270
|
+
var sourceData = seriesMap.get(viewTag.SourceTagId);
|
|
16271
|
+
if (!sourceData)
|
|
16272
|
+
return null;
|
|
16273
|
+
// Extract bit from each data point
|
|
16274
|
+
// BitIndex 0 = LSB (least significant bit)
|
|
16275
|
+
return sourceData.map(function (point) { return ({
|
|
16276
|
+
timestamp: point.timestamp,
|
|
16277
|
+
value: point.value !== null
|
|
16278
|
+
? (Math.floor(point.value) >> viewTag.BitIndex) & 1
|
|
16279
|
+
: null,
|
|
16280
|
+
}); });
|
|
16281
|
+
}
|
|
16282
|
+
// Regular tag - use series data directly
|
|
16283
|
+
return seriesMap.get(tagId);
|
|
16284
|
+
})
|
|
15532
16285
|
.filter(Boolean);
|
|
15533
|
-
}, [series, tagIds, queryTagIds]);
|
|
16286
|
+
}, [series, tagIds, queryTagIds, viewTags]);
|
|
15534
16287
|
// Calculate overall min/max values from filtered series data
|
|
15535
16288
|
var seriesMinMaxData = useSeriesMinMax(filteredSeries, tagIds);
|
|
15536
16289
|
// Load initial view when views are fetched
|
|
@@ -15640,12 +16393,14 @@ var TrendingsPageV2 = function () {
|
|
|
15640
16393
|
var isLoading = viewsLoading || viewTagsLoading;
|
|
15641
16394
|
return (React__default.createElement(React__default.Fragment, null,
|
|
15642
16395
|
React__default.createElement(HelmetDexteel, { title: "Trendings" }),
|
|
15643
|
-
React__default.createElement(
|
|
15644
|
-
|
|
16396
|
+
React__default.createElement("div", { style: {
|
|
16397
|
+
padding: "16px",
|
|
15645
16398
|
width: "100%",
|
|
15646
16399
|
height: "92vh",
|
|
15647
16400
|
position: "relative",
|
|
15648
16401
|
backgroundColor: "#FAFAFA",
|
|
16402
|
+
display: "flex",
|
|
16403
|
+
flexDirection: "column",
|
|
15649
16404
|
} },
|
|
15650
16405
|
isLoading && (React__default.createElement("div", { style: {
|
|
15651
16406
|
position: "absolute",
|
|
@@ -15660,14 +16415,38 @@ var TrendingsPageV2 = function () {
|
|
|
15660
16415
|
zIndex: 1000,
|
|
15661
16416
|
} },
|
|
15662
16417
|
React__default.createElement(CircularProgress, { size: "3rem" }))),
|
|
15663
|
-
React__default.createElement(
|
|
16418
|
+
React__default.createElement("div", { style: { flexShrink: 0 } },
|
|
15664
16419
|
React__default.createElement(HeaderSectionV2, { autoRefresh: autoRefresh, setAutoRefresh: setAutoRefresh, setChartOptions: setChartOptions, chartInstance: chartInstance })),
|
|
15665
|
-
React__default.createElement(
|
|
15666
|
-
|
|
15667
|
-
|
|
15668
|
-
|
|
15669
|
-
|
|
15670
|
-
|
|
16420
|
+
React__default.createElement(Divider, { sx: { my: 2 } }),
|
|
16421
|
+
React__default.createElement("div", { style: {
|
|
16422
|
+
flexGrow: 1,
|
|
16423
|
+
minHeight: 0,
|
|
16424
|
+
display: "flex",
|
|
16425
|
+
width: "100%",
|
|
16426
|
+
} },
|
|
16427
|
+
React__default.createElement(Group$1, { orientation: "vertical", style: { width: "100%", height: "100%" } },
|
|
16428
|
+
React__default.createElement(Panel, { defaultSize: 80, minSize: 20 },
|
|
16429
|
+
React__default.createElement("div", { style: { height: "100%", width: "100%" } },
|
|
16430
|
+
React__default.createElement(TrendingChartV2, { customOptions: chartOptions, series: filteredSeries, isLoading: seriesLoading, onChartReady: setChartInstance, dataLoadedTrigger: dataLoadedTrigger }))),
|
|
16431
|
+
React__default.createElement(Separator, { style: {
|
|
16432
|
+
height: "10px",
|
|
16433
|
+
background: "#f0f0f0",
|
|
16434
|
+
cursor: "row-resize",
|
|
16435
|
+
display: "flex",
|
|
16436
|
+
alignItems: "center",
|
|
16437
|
+
justifyContent: "center",
|
|
16438
|
+
borderTop: "1px solid #e0e0e0",
|
|
16439
|
+
borderBottom: "1px solid #e0e0e0",
|
|
16440
|
+
} },
|
|
16441
|
+
React__default.createElement("div", { style: {
|
|
16442
|
+
width: "40px",
|
|
16443
|
+
height: "4px",
|
|
16444
|
+
backgroundColor: "#ccc",
|
|
16445
|
+
borderRadius: "2px",
|
|
16446
|
+
} })),
|
|
16447
|
+
React__default.createElement(Panel, { defaultSize: 20, minSize: 10 },
|
|
16448
|
+
React__default.createElement("div", { style: { height: "100%", width: "100%", overflow: "auto" } },
|
|
16449
|
+
React__default.createElement(TagsTableV2, null)))))),
|
|
15671
16450
|
React__default.createElement(ErrorModal, { error: error, onHide: function () { return setError(""); }, size: "xl", title: "ERROR" })));
|
|
15672
16451
|
};
|
|
15673
16452
|
|
|
@@ -21206,5 +21985,5 @@ var areaSelector = /*#__PURE__*/Object.freeze({
|
|
|
21206
21985
|
AreaSelector: AreaSelector
|
|
21207
21986
|
});
|
|
21208
21987
|
|
|
21209
|
-
export { Account, AssetProvider, AssetTreePicker, AuthContext, AuthProvider, ButtonWithLoading, ChangePassword, CheckBoxControl, Configuration$1 as Configuration, ContextMenu$1 as ContextMenu, ContextMenuMESFProvider, CreateNewAssetDialog, CurrencyFormatter, DataGridControl, DateFormatter, DateTimeFormatter, ENTRY_INITIAL_VALUES, EditAssetDialog, ErrorModal, ExcelIcon, FetchError, FilterPanel, GenericPanel, GenericTable, GetCrewColor, GetShiftColor, HelmetDexteel, IntegerFormatter, LogbookSettingsInitialState, LogbookSettingsProvider, Login, Logout, LongFilterPanel, MESApiService, MESFLogbookEntry, MESFLogbookReport, MESFMain, MESSAGE_API, MESSAGE_ERRORS, MasterDetailPanel, MesfModal, ModalTreeFilterControl, MultipleSelectorControl, NumberFormatter, RemoveAssetDialog, ShiftDayNavigatorControl, ShiftNavigatorProvider, ShiftPeriodNavigatorControl, SimplePasswordControl, SimpleSelectorControl, TimeAndUserMenu, TimeFormatter, TimeService, TreePickerControl, TreePickerControlV2, TrendingsPage, USER_LABELS, UTLSettingsProvider, UserProvider, axiosInstance, deleteUser, dxtServerTimeZone, dxtToLocalServerTime, dxtToUTC, formatNumber, getAuthTypes, getCrewStyle, getDataUser, getEntries, getError, getMomentTz, getShiftByParameters, getShiftStyle, getShiftsRangeByParameters, getTokenFromLS, getUserPermissionsFromAPI, getUsers, logbookNavbar, logbookRoutesMESF, renewToken, routeLogbookEntry, routeLogbookReport, useSearchAssets as searchAssets, useSearchSeries as searchSeries, useSearchTagsTree as searchTagsTree, useSearchViewTags as searchViewTags, useSearchViews as searchViews, setPassword, setProfilesToUser, themeDXT, themeMESF, upsertUser, useAssetContext, useContextMenuMESF, useHasPermission, useHasProfile, useLogbookSettings, useMesfRealtime, useShiftNavigator, useShiftNavigatorManager, useToken, useUTLSettingsContext, useUserContext };
|
|
21988
|
+
export { Account, AssetProvider, AssetTreePicker, AuthContext, AuthProvider, ButtonWithLoading, ChangePassword, CheckBoxControl, Configuration$1 as Configuration, ContextMenu$1 as ContextMenu, ContextMenuMESFProvider, CreateNewAssetDialog, CurrencyFormatter, DataGridControl, DateFormatter, DateTimeFormatter, ENTRY_INITIAL_VALUES, EditAssetDialog, ErrorModal, ExcelIcon, FetchError, FilterPanel, GenericPanel, GenericTable, GetCrewColor, GetShiftColor, HelmetDexteel, IntegerFormatter, LogbookSettingsInitialState, LogbookSettingsProvider, Login, Logout, LongFilterPanel, MESApiService, MESFLogbookEntry, MESFLogbookReport, MESFMain, MESSAGE_API, MESSAGE_ERRORS, MasterDetailPanel, MesfModal, ModalTreeFilterControl, MultipleSelectorControl, NumberFormatter, RemoveAssetDialog, SPExecutorPage, ShiftDayNavigatorControl, ShiftNavigatorProvider, ShiftPeriodNavigatorControl, SimplePasswordControl, SimpleSelectorControl, TimeAndUserMenu, TimeFormatter, TimeService, TreePickerControl, TreePickerControlV2, TrendingsPage, USER_LABELS, UTLSettingsProvider, UserProvider, axiosInstance, deleteUser, dxtServerTimeZone, dxtToLocalServerTime, dxtToUTC, formatNumber, getAuthTypes, getCrewStyle, getDataUser, getEntries, getError, getMomentTz, getShiftByParameters, getShiftStyle, getShiftsRangeByParameters, getTokenFromLS, getUserPermissionsFromAPI, getUsers, logbookNavbar, logbookRoutesMESF, renewToken, routeLogbookEntry, routeLogbookReport, useSearchAssets as searchAssets, useSearchSeries as searchSeries, useSearchTagsTree as searchTagsTree, useSearchViewTags as searchViewTags, useSearchViews as searchViews, setPassword, setProfilesToUser, themeDXT, themeMESF, upsertUser, useAssetContext, useContextMenuMESF, useHasPermission, useHasProfile, useLogbookSettings, useMesfRealtime, useShiftNavigator, useShiftNavigatorManager, useToken, useUTLSettingsContext, useUserContext };
|
|
21210
21989
|
//# sourceMappingURL=index.esm.js.map
|