@dexteel/mesf-core 7.11.2 → 7.12.1

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.
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "7.11.2"
2
+ ".": "7.12.1"
3
3
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [7.12.1](https://github.com/dexteel/mesf-core-frontend/compare/@dexteel/mesf-core-v7.12.0...@dexteel/mesf-core-v7.12.1) (2026-01-27)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **sp-executor:** exclude backend-managed parameters user from UI and execution payload ([4cd1b89](https://github.com/dexteel/mesf-core-frontend/commit/4cd1b89298cf8830ba21bab40e504d62bfc67d5a))
9
+
10
+ ## [7.12.0](https://github.com/dexteel/mesf-core-frontend/compare/@dexteel/mesf-core-v7.11.2...@dexteel/mesf-core-v7.12.0) (2026-01-22)
11
+
12
+
13
+ ### Features
14
+
15
+ * **Logs:** Implement tag filtering functionality in logs ([9dc7efa](https://github.com/dexteel/mesf-core-frontend/commit/9dc7efa6b7d337bd9bc5903c45cc7a8b13a7c6de))
16
+
3
17
  ## [7.11.2](https://github.com/dexteel/mesf-core-frontend/compare/@dexteel/mesf-core-v7.11.1...@dexteel/mesf-core-v7.11.2) (2026-01-22)
4
18
 
5
19
 
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import type { TagFilterContext, TagFilterType } from "../../models/Tag";
3
+ type Props = {
4
+ tagFilters: TagFilterType[];
5
+ setTagFilters: (filters: TagFilterType[]) => void;
6
+ filterContext: TagFilterContext;
7
+ };
8
+ export declare const TagFilter: ({ tagFilters, setTagFilters, filterContext, }: Props) => React.JSX.Element;
9
+ export {};
@@ -0,0 +1,19 @@
1
+ export interface Tag {
2
+ TagId: number;
3
+ TagName: string;
4
+ HasData: boolean;
5
+ }
6
+ export interface TagValue {
7
+ Value: string;
8
+ HasData: boolean;
9
+ }
10
+ export interface TagFilterType {
11
+ TagName: string;
12
+ Values: string[];
13
+ }
14
+ export interface TagFilterContext {
15
+ startDate: Date;
16
+ endDate: Date | null;
17
+ logTypeCode: string | null;
18
+ tagFilters: TagFilterType[];
19
+ }
@@ -1,8 +1,10 @@
1
1
  import { Log } from "../models/Log";
2
+ import { TagFilterType } from "../models/Tag";
2
3
  type Props = {
3
4
  startDate: Date;
4
5
  endDate: Date | null;
5
6
  logTypeCode: number | string | null;
7
+ tagFilters?: TagFilterType[];
6
8
  };
7
- export declare const getLogs: ({ startDate, endDate, logTypeCode }: Props) => Promise<Log[]>;
9
+ export declare const getLogs: ({ startDate, endDate, logTypeCode, tagFilters, }: Props) => Promise<Log[]>;
8
10
  export {};
@@ -0,0 +1,3 @@
1
+ import type { Tag, TagFilterContext, TagValue } from "../models/Tag";
2
+ export declare const getLogTags: (context?: TagFilterContext) => Promise<Tag[]>;
3
+ export declare const getLogTagValues: (tagName: string, context?: TagFilterContext) => Promise<TagValue[]>;
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, Grid, Accordion, AccordionSummary, AccordionDetails, Tabs, Tab, Autocomplete as Autocomplete$1, useMediaQuery, ListSubheader, ListItemButton, StyledEngineProvider, ThemeProvider, ListItemSecondaryAction } from '@mui/material';
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, Autocomplete, Hidden, Drawer, Grid, Accordion, AccordionSummary, AccordionDetails, Tabs, Tab, useMediaQuery, ListSubheader, ListItemButton, 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';
@@ -11,7 +11,7 @@ import { createPart, themeMaterial, provideGlobalGridOptions } from 'ag-grid-com
11
11
  import { values, get, isEmpty, isNil } from 'lodash-es';
12
12
  import { useForm, Controller } from 'react-hook-form';
13
13
  import { isAncestor, Tree, DndProvider as DndProvider$1 } from '@minoru/react-dnd-treeview';
14
- import { Alert as Alert$4, AlertTitle, Autocomplete } from '@mui/lab';
14
+ import { Alert as Alert$4, AlertTitle, Autocomplete as Autocomplete$1 } from '@mui/lab';
15
15
  import { Helmet, HelmetProvider } from 'react-helmet-async';
16
16
  import AccountTree from '@mui/icons-material/AccountTree';
17
17
  import Settings$1 from '@mui/icons-material/Settings';
@@ -50,6 +50,8 @@ import ToggleOfIcon from '@mui/icons-material/ToggleOff';
50
50
  import ToggleOnIcon from '@mui/icons-material/ToggleOn';
51
51
  import { useComplexState } from 'use-complex-state';
52
52
  import { createSlice } from '@reduxjs/toolkit';
53
+ import CheckBoxIcon from '@mui/icons-material/CheckBox';
54
+ import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';
53
55
  import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment';
54
56
  import { DndProvider } from 'react-dnd';
55
57
  import { HTML5Backend } from 'react-dnd-html5-backend';
@@ -7239,6 +7241,246 @@ const JobsPage = (props) => {
7239
7241
  React.createElement(Jobs, null)));
7240
7242
  };
7241
7243
 
7244
+ // Get all tags that have been used in logs
7245
+ const getLogTags = (context) => __awaiter(void 0, void 0, void 0, function* () {
7246
+ var _a;
7247
+ const apiService = new MESApiService();
7248
+ const tomorrow = new Date();
7249
+ tomorrow.setDate(tomorrow.getDate() + 1);
7250
+ const parameters = context
7251
+ ? [
7252
+ { name: "Start", value: context.startDate },
7253
+ { name: "End", value: (_a = context.endDate) !== null && _a !== void 0 ? _a : tomorrow },
7254
+ {
7255
+ name: "LogTypeCode",
7256
+ value: context.logTypeCode === "A" ? null : context.logTypeCode,
7257
+ },
7258
+ {
7259
+ name: "TagFilters",
7260
+ value: context.tagFilters.length > 0
7261
+ ? JSON.stringify(context.tagFilters)
7262
+ : null,
7263
+ },
7264
+ ]
7265
+ : [];
7266
+ const resp = yield apiService.callV2("[SYSTEM].[GetLogTags]", parameters);
7267
+ if (resp.ok) {
7268
+ const rows = get(resp, "data.tables[0].rows", []);
7269
+ return rows;
7270
+ }
7271
+ else {
7272
+ throw new Error(resp.message || "Error fetching log tags");
7273
+ }
7274
+ });
7275
+ // Get all distinct values for a specific tag
7276
+ const getLogTagValues = (tagName, context) => __awaiter(void 0, void 0, void 0, function* () {
7277
+ var _a;
7278
+ const apiService = new MESApiService();
7279
+ const tomorrow = new Date();
7280
+ tomorrow.setDate(tomorrow.getDate() + 1);
7281
+ // When getting values for a tag, exclude that tag from the filter context
7282
+ // so we show all possible values that match the OTHER filters
7283
+ const otherTagFilters = context === null || context === void 0 ? void 0 : context.tagFilters.filter((f) => f.TagName !== tagName);
7284
+ const parameters = [
7285
+ { name: "TagName", value: tagName },
7286
+ ...(context
7287
+ ? [
7288
+ { name: "Start", value: context.startDate },
7289
+ { name: "End", value: (_a = context.endDate) !== null && _a !== void 0 ? _a : tomorrow },
7290
+ {
7291
+ name: "LogTypeCode",
7292
+ value: context.logTypeCode === "A" ? null : context.logTypeCode,
7293
+ },
7294
+ {
7295
+ name: "TagFilters",
7296
+ value: otherTagFilters && otherTagFilters.length > 0
7297
+ ? JSON.stringify(otherTagFilters)
7298
+ : null,
7299
+ },
7300
+ ]
7301
+ : []),
7302
+ ];
7303
+ const resp = yield apiService.callV2("[SYSTEM].[GetLogTagValues]", parameters);
7304
+ if (resp.ok) {
7305
+ const rows = get(resp, "data.tables[0].rows", []);
7306
+ return rows;
7307
+ }
7308
+ else {
7309
+ throw new Error(resp.message || "Error fetching tag values");
7310
+ }
7311
+ });
7312
+
7313
+ const icon = React__default.createElement(CheckBoxOutlineBlankIcon, { fontSize: "small" });
7314
+ const checkedIcon = React__default.createElement(CheckBoxIcon, { fontSize: "small" });
7315
+ const useSearchLogTags = ({ startDate, endDate, logTypeCode, tagFilters, }) => {
7316
+ return useQuery({
7317
+ queryKey: [
7318
+ "logTags",
7319
+ startDate.getTime(),
7320
+ endDate === null || endDate === void 0 ? void 0 : endDate.getTime(),
7321
+ logTypeCode,
7322
+ tagFilters,
7323
+ ],
7324
+ queryFn: () => getLogTags({ startDate, endDate, logTypeCode, tagFilters }),
7325
+ });
7326
+ };
7327
+ const useSearchLogTagValues = ({ tagName, startDate, endDate, logTypeCode, tagFilters, }) => {
7328
+ return useQuery({
7329
+ queryKey: [
7330
+ "logTagValues",
7331
+ tagName,
7332
+ startDate,
7333
+ endDate,
7334
+ logTypeCode,
7335
+ tagFilters,
7336
+ ],
7337
+ queryFn: () => getLogTagValues(tagName, { startDate, endDate, logTypeCode, tagFilters }),
7338
+ enabled: !!tagName,
7339
+ });
7340
+ };
7341
+ const TagFilter = ({ tagFilters, setTagFilters, filterContext, }) => {
7342
+ const [anchorEl, setAnchorEl] = useState(null);
7343
+ const [selectedTag, setSelectedTag] = useState(null);
7344
+ const [selectedValues, setSelectedValues] = useState([]);
7345
+ const [showOnlyWithData, setShowOnlyWithData] = useState(true);
7346
+ const [error, setError] = useState("");
7347
+ const { data: availableTags, isLoading: isLoadingTags, error: tagsError, isError: isTagsError, } = useSearchLogTags({
7348
+ startDate: filterContext.startDate,
7349
+ endDate: filterContext.endDate,
7350
+ logTypeCode: filterContext.logTypeCode,
7351
+ tagFilters,
7352
+ });
7353
+ const { data: tagValues, isLoading: isLoadingValues, error: valuesError, isError: isValuesError, } = useSearchLogTagValues({
7354
+ tagName: selectedTag ? selectedTag.TagName : "",
7355
+ startDate: filterContext.startDate,
7356
+ endDate: filterContext.endDate,
7357
+ logTypeCode: filterContext.logTypeCode,
7358
+ tagFilters,
7359
+ });
7360
+ const handleOpenPopover = (event) => {
7361
+ setAnchorEl(event.currentTarget);
7362
+ setSelectedTag(null);
7363
+ setSelectedValues([]);
7364
+ };
7365
+ const handleClosePopover = () => {
7366
+ setAnchorEl(null);
7367
+ setSelectedTag(null);
7368
+ setSelectedValues([]);
7369
+ };
7370
+ const handleAddFilter = () => {
7371
+ if (selectedTag && selectedValues.length > 0) {
7372
+ // Check if this tag already has a filter
7373
+ const existingIndex = tagFilters.findIndex((f) => f.TagName === selectedTag.TagName);
7374
+ const valueStrings = selectedValues.map((v) => v.Value);
7375
+ if (existingIndex >= 0) {
7376
+ // Update existing filter
7377
+ const newFilters = [...tagFilters];
7378
+ newFilters[existingIndex] = {
7379
+ TagName: selectedTag.TagName,
7380
+ Values: valueStrings,
7381
+ };
7382
+ setTagFilters(newFilters);
7383
+ }
7384
+ else {
7385
+ // Add new filter
7386
+ setTagFilters([
7387
+ ...tagFilters,
7388
+ {
7389
+ TagName: selectedTag.TagName,
7390
+ Values: valueStrings,
7391
+ },
7392
+ ]);
7393
+ }
7394
+ handleClosePopover();
7395
+ }
7396
+ };
7397
+ const handleRemoveFilter = (tagName) => {
7398
+ setTagFilters(tagFilters.filter((f) => f.TagName !== tagName));
7399
+ };
7400
+ const handleEditFilter = (event, filter) => {
7401
+ const tag = availableTags === null || availableTags === void 0 ? void 0 : availableTags.find((t) => t.TagName === filter.TagName);
7402
+ if (tag) {
7403
+ setSelectedTag(tag);
7404
+ setSelectedValues(filter.Values.map((v) => ({ Value: v, HasData: true })));
7405
+ setAnchorEl(event.currentTarget);
7406
+ }
7407
+ };
7408
+ const availableTagsForSelection = (availableTags === null || availableTags === void 0 ? void 0 : availableTags.filter((tag) => (!tagFilters.some((f) => f.TagName === tag.TagName) ||
7409
+ (selectedTag === null || selectedTag === void 0 ? void 0 : selectedTag.TagName) === tag.TagName) &&
7410
+ (!showOnlyWithData || tag.HasData))) || [];
7411
+ const availableTagValues = (tagValues === null || tagValues === void 0 ? void 0 : tagValues.filter((tv) => !showOnlyWithData || tv.HasData)) || [];
7412
+ const open = Boolean(anchorEl);
7413
+ useEffect(() => {
7414
+ if (tagValues && selectedValues.length > 0) {
7415
+ const syncedValues = selectedValues
7416
+ .map((sv) => tagValues.find((tv) => tv.Value === sv.Value))
7417
+ .filter((tv) => tv !== undefined);
7418
+ if (syncedValues.length > 0) {
7419
+ setSelectedValues(syncedValues);
7420
+ }
7421
+ }
7422
+ }, [tagValues]);
7423
+ useEffect(() => {
7424
+ if (isTagsError && tagsError) {
7425
+ setError(tagsError.message);
7426
+ }
7427
+ if (isValuesError && valuesError) {
7428
+ setError(valuesError.message);
7429
+ }
7430
+ }, [isTagsError, tagsError, isValuesError, valuesError]);
7431
+ return (React__default.createElement(React__default.Fragment, null,
7432
+ React__default.createElement(Box, { sx: { display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" } },
7433
+ React__default.createElement(Typography$1, { variant: "body2", sx: { fontWeight: 500, color: "#666" } }, "Tags:"),
7434
+ tagFilters.map((filter) => {
7435
+ const tag = availableTags === null || availableTags === void 0 ? void 0 : availableTags.find((t) => t.TagName === filter.TagName);
7436
+ const hasData = (tag === null || tag === void 0 ? void 0 : tag.HasData) !== false;
7437
+ return (React__default.createElement(Chip, { key: filter.TagName, label: `${filter.TagName} = ${filter.Values.join(", ")}`, onDelete: () => handleRemoveFilter(filter.TagName), onClick: (e) => handleEditFilter(e, filter), size: "small", color: hasData ? "primary" : "default", variant: "outlined", sx: {
7438
+ cursor: "pointer",
7439
+ opacity: hasData ? 1 : 0.5,
7440
+ } }));
7441
+ }),
7442
+ isLoadingTags ? (React__default.createElement(CircularProgress, { size: 20 })) : (availableTagsForSelection.length > 0 && (React__default.createElement(Button, { size: "small", variant: "text", onClick: handleOpenPopover, sx: { minWidth: "auto", textTransform: "none" } }, "+ Add Tag Filter"))),
7443
+ React__default.createElement(Popover, { open: open, anchorEl: anchorEl, onClose: handleClosePopover, anchorOrigin: {
7444
+ vertical: "bottom",
7445
+ horizontal: "left",
7446
+ }, transformOrigin: {
7447
+ vertical: "top",
7448
+ horizontal: "left",
7449
+ } },
7450
+ React__default.createElement(Box, { sx: {
7451
+ p: 2,
7452
+ minWidth: 350,
7453
+ display: "flex",
7454
+ flexDirection: "column",
7455
+ gap: 2,
7456
+ } },
7457
+ React__default.createElement(Box, { sx: {
7458
+ display: "flex",
7459
+ justifyContent: "space-between",
7460
+ alignItems: "center",
7461
+ } },
7462
+ React__default.createElement(Typography$1, { variant: "subtitle2" }, selectedTag ? "Edit Tag Filter" : "Add Tag Filter"),
7463
+ React__default.createElement(FormControlLabel, { control: React__default.createElement(Checkbox, { size: "small", checked: showOnlyWithData, onChange: (e) => setShowOnlyWithData(e.target.checked) }), label: React__default.createElement(Typography$1, { variant: "caption" }, "Only with data"), sx: { mr: 0 } })),
7464
+ React__default.createElement(Autocomplete, { size: "small", options: availableTagsForSelection, getOptionLabel: (option) => option.TagName, value: selectedTag, onChange: (_, newValue) => {
7465
+ setSelectedTag(newValue);
7466
+ setSelectedValues([]);
7467
+ }, renderOption: (props, option) => (React__default.createElement("li", Object.assign({}, props, { style: {
7468
+ opacity: option.HasData ? 1 : 0.8,
7469
+ } }), option.TagName)), renderInput: (params) => (React__default.createElement(TextField, Object.assign({}, params, { label: "Tag Name", variant: "outlined" }))) }),
7470
+ selectedTag && (React__default.createElement(React__default.Fragment, null, isLoadingValues ? (React__default.createElement(Box, { sx: { display: "flex", justifyContent: "center", py: 2 } },
7471
+ React__default.createElement(CircularProgress, { size: 24 }))) : (React__default.createElement(Autocomplete, { multiple: true, size: "small", options: availableTagValues, getOptionLabel: (option) => option.Value, value: selectedValues, onChange: (_, newValue) => setSelectedValues(newValue), isOptionEqualToValue: (option, value) => option.Value === value.Value, disableCloseOnSelect: true, renderOption: (props, option, { selected }) => (React__default.createElement("li", Object.assign({}, props, { style: {
7472
+ opacity: option.HasData ? 1 : 0.8,
7473
+ } }),
7474
+ React__default.createElement(Checkbox, { icon: icon, checkedIcon: checkedIcon, style: { marginRight: 8 }, checked: selected, size: "small" }),
7475
+ option.Value)), renderInput: (params) => (React__default.createElement(TextField, Object.assign({}, params, { label: "Tag Values", variant: "outlined", placeholder: "Select values..." }))) })))),
7476
+ React__default.createElement(Box, { sx: { display: "flex", justifyContent: "flex-end", gap: 1 } },
7477
+ React__default.createElement(Button, { size: "small", onClick: handleClosePopover }, "Cancel"),
7478
+ React__default.createElement(Button, { size: "small", variant: "contained", onClick: handleAddFilter, disabled: !selectedTag || selectedValues.length === 0 }, tagFilters.some((f) => f.TagName === (selectedTag === null || selectedTag === void 0 ? void 0 : selectedTag.TagName))
7479
+ ? "Update"
7480
+ : "Add"))))),
7481
+ React__default.createElement(ErrorModal, { error: error, onHide: () => setError("") })));
7482
+ };
7483
+
7242
7484
  const LOG_TYPE_CODES = {
7243
7485
  I: { id: "I", color: "#3f51b5", description: "Info" },
7244
7486
  E: { id: "E", color: "#f44336", description: "Error" },
@@ -7384,11 +7626,12 @@ const useLogTableData = () => {
7384
7626
  };
7385
7627
 
7386
7628
  //fx obtener logs
7387
- const getLogs = (_a) => __awaiter(void 0, [_a], void 0, function* ({ startDate, endDate, logTypeCode }) {
7629
+ const getLogs = (_a) => __awaiter(void 0, [_a], void 0, function* ({ startDate, endDate, logTypeCode, tagFilters, }) {
7388
7630
  const apiService = new MESApiService();
7389
7631
  const tomorrow = new Date();
7390
7632
  tomorrow.setDate(tomorrow.getDate() + 1);
7391
7633
  const end = endDate ? endDate : tomorrow;
7634
+ const tagFiltersJson = tagFilters && tagFilters.length > 0 ? JSON.stringify(tagFilters) : null;
7392
7635
  const parameters = [
7393
7636
  { name: "Start", value: startDate },
7394
7637
  { name: "End", value: end },
@@ -7396,6 +7639,7 @@ const getLogs = (_a) => __awaiter(void 0, [_a], void 0, function* ({ startDate,
7396
7639
  name: "LogTypeCode",
7397
7640
  value: logTypeCode === "A" ? null : logTypeCode,
7398
7641
  },
7642
+ { name: "TagFilters", value: tagFiltersJson },
7399
7643
  ];
7400
7644
  const resp = yield apiService.callV2("[MES].[GetLogs]", parameters);
7401
7645
  if (resp.ok) {
@@ -7506,13 +7750,14 @@ const useLogsOptionsFunctions = ({ setSelectedLog, setShowLogModal, handleResetB
7506
7750
  };
7507
7751
  };
7508
7752
 
7509
- const useSearchLogs = ({ startDate, endDate, logTypeCode, autoRefresh, }) => {
7753
+ const useSearchLogs = ({ startDate, endDate, logTypeCode, autoRefresh, tagFilters, }) => {
7510
7754
  return useQuery({
7511
- queryKey: ["logs", startDate, endDate, logTypeCode],
7755
+ queryKey: ["logs", startDate, endDate, logTypeCode, tagFilters],
7512
7756
  queryFn: () => getLogs({
7513
7757
  startDate,
7514
7758
  endDate,
7515
7759
  logTypeCode,
7760
+ tagFilters,
7516
7761
  }),
7517
7762
  refetchInterval: autoRefresh ? 5000 : false,
7518
7763
  });
@@ -7527,6 +7772,7 @@ const TableLogs = () => {
7527
7772
  const [search, setSearch] = useState("");
7528
7773
  const [logTypeCode, setLogTypeCode] = useState(["I", "W", "E"]);
7529
7774
  const [autoRefresh, setAutoRefresh] = useState(false);
7775
+ const [tagFilters, setTagFilters] = useState([]);
7530
7776
  const [gridAPI, setGridAPI] = useState(null);
7531
7777
  const [error, setError] = useState("");
7532
7778
  const [showLogModal, setShowLogModal] = useState(false);
@@ -7536,6 +7782,7 @@ const TableLogs = () => {
7536
7782
  endDate,
7537
7783
  logTypeCode: logTypeCode.join(","),
7538
7784
  autoRefresh,
7785
+ tagFilters,
7539
7786
  });
7540
7787
  const onGridReady = (params) => {
7541
7788
  setGridAPI(params.api);
@@ -7567,23 +7814,15 @@ const TableLogs = () => {
7567
7814
  }, []);
7568
7815
  const { showContextMenu, registerConfig } = useContextMenuMESF();
7569
7816
  const handleResetButtonClick = () => {
7570
- resetFilter();
7571
- setStartDate(moment$f().add(-5, "days").hour(0).minute(0).second(0).toDate());
7572
- setEndDate(moment$f().hour(23).minute(59).second(59).toDate());
7573
- setSearch("");
7574
- gridAPI === null || gridAPI === void 0 ? void 0 : gridAPI.setGridOption("quickFilterText", "");
7575
- setLogTypeCode(["I", "W", "E"]);
7576
- refetch();
7577
- setError("");
7578
- };
7579
- // Btn reset data
7580
- const resetFilter = () => {
7581
7817
  setStartDate(moment$f().add(-5, "days").hour(0).minute(0).second(0).toDate());
7582
7818
  setEndDate(moment$f().hour(23).minute(59).second(59).toDate());
7583
7819
  setSearch("");
7584
7820
  gridAPI === null || gridAPI === void 0 ? void 0 : gridAPI.setGridOption("quickFilterText", "");
7585
7821
  setLogTypeCode(["I", "W", "E"]);
7822
+ setTagFilters([]);
7586
7823
  setSelectedLog(undefined);
7824
+ setError("");
7825
+ refetch();
7587
7826
  };
7588
7827
  const rowClicked = (rowClickedEvent) => {
7589
7828
  let data = rowClickedEvent.data;
@@ -7670,7 +7909,14 @@ const TableLogs = () => {
7670
7909
  gridAPI === null || gridAPI === void 0 ? void 0 : gridAPI.setGridOption("quickFilterText", search);
7671
7910
  } })),
7672
7911
  React.createElement(Grid2, { size: { md: 1, xs: 12 }, style: { paddingTop: 8 } },
7673
- React.createElement(Button, { variant: "contained", color: "inherit", onClick: handleResetButtonClick, fullWidth: true }, "Reset")))))),
7912
+ React.createElement(Button, { variant: "contained", color: "inherit", onClick: handleResetButtonClick, fullWidth: true }, "Reset")),
7913
+ React.createElement(Grid2, { size: { md: 12, xs: 12 }, sx: { mt: 1 } },
7914
+ React.createElement(TagFilter, { tagFilters: tagFilters, setTagFilters: setTagFilters, filterContext: {
7915
+ startDate,
7916
+ endDate,
7917
+ logTypeCode: logTypeCode.join(","),
7918
+ tagFilters,
7919
+ } })))))),
7674
7920
  React.createElement(Grid2, { size: { md: 12, xs: 12 }, style: {
7675
7921
  height: "70vh",
7676
7922
  } },
@@ -9627,9 +9873,9 @@ const QueryCacheInvalidations = () => {
9627
9873
  React__default.createElement(MesfModal.Content, { dividers: true },
9628
9874
  React__default.createElement(Grid2, { container: true, spacing: 3 },
9629
9875
  React__default.createElement(Grid2, { size: { xs: 12 } },
9630
- React__default.createElement(Controller, { control: control, name: "source", render: (params) => (React__default.createElement(Autocomplete, { options: actions, getOptionLabel: (option) => `${option.ActionName}`, value: params.field.value, onChange: (_, value) => params.field.onChange(value), renderInput: (params) => (React__default.createElement(TextField, Object.assign({}, params, { label: "Select Source Action", variant: "outlined", size: "medium" }))), disabled: modal === "edit" })) })),
9876
+ React__default.createElement(Controller, { control: control, name: "source", render: (params) => (React__default.createElement(Autocomplete$1, { options: actions, getOptionLabel: (option) => `${option.ActionName}`, value: params.field.value, onChange: (_, value) => params.field.onChange(value), renderInput: (params) => (React__default.createElement(TextField, Object.assign({}, params, { label: "Select Source Action", variant: "outlined", size: "medium" }))), disabled: modal === "edit" })) })),
9631
9877
  React__default.createElement(Grid2, { size: { xs: 12 } },
9632
- React__default.createElement(Controller, { control: control, name: "targets", render: (params) => (React__default.createElement(Autocomplete, { multiple: true, options: actions.filter((a) => { var _a; return a.ActionId !== ((_a = control._formValues.source) === null || _a === void 0 ? void 0 : _a.ActionId); }), getOptionLabel: (option) => {
9878
+ React__default.createElement(Controller, { control: control, name: "targets", render: (params) => (React__default.createElement(Autocomplete$1, { multiple: true, options: actions.filter((a) => { var _a; return a.ActionId !== ((_a = control._formValues.source) === null || _a === void 0 ? void 0 : _a.ActionId); }), getOptionLabel: (option) => {
9633
9879
  if (typeof option === "string") {
9634
9880
  return option;
9635
9881
  }
@@ -9928,7 +10174,7 @@ const ResultsList = ({ results, onDeleteResult, onClearAll }) => {
9928
10174
  };
9929
10175
 
9930
10176
  const SPAutocomplete = ({ procedures, value, onChange, isLoading, disabled = false, }) => {
9931
- return (React__default.createElement(Autocomplete$1, { options: procedures, value: value, onChange: (_, newValue) => onChange(newValue), getOptionLabel: (option) => option.FullName, groupBy: (option) => option.SchemaName, disabled: disabled, isOptionEqualToValue: (option, val) => option.FullName === val.FullName, renderInput: (params) => (React__default.createElement(TextField, Object.assign({}, params, { label: "Select Stored Procedure", variant: "outlined", fullWidth: true, slotProps: {
10177
+ return (React__default.createElement(Autocomplete, { options: procedures, value: value, onChange: (_, newValue) => onChange(newValue), getOptionLabel: (option) => option.FullName, groupBy: (option) => option.SchemaName, disabled: disabled, isOptionEqualToValue: (option, val) => option.FullName === val.FullName, renderInput: (params) => (React__default.createElement(TextField, Object.assign({}, params, { label: "Select Stored Procedure", variant: "outlined", fullWidth: true, slotProps: {
9932
10178
  input: Object.assign(Object.assign({}, params.InputProps), { endAdornment: (React__default.createElement(React__default.Fragment, null, isLoading ? (React__default.createElement(CircularProgress, { color: "inherit", size: 20 })) : (params.InputProps.endAdornment))) }),
9933
10179
  } }))), renderOption: (props, option) => (React__default.createElement("li", Object.assign({}, props, { key: option.FullName }),
9934
10180
  option.SchemaName,
@@ -9949,6 +10195,7 @@ const executeStoredProcedure = (procedureName, parameters) => __awaiter(void 0,
9949
10195
  return yield apiService.callV2(procedureName, parameters);
9950
10196
  });
9951
10197
 
10198
+ const BACKEND_MANAGED_PARAMS = ["@user"];
9952
10199
  const SPExecutorPage = () => {
9953
10200
  const [procedures, setProcedures] = useState([]);
9954
10201
  const [allParameters, setAllParameters] = useState([]);
@@ -9976,10 +10223,12 @@ const SPExecutorPage = () => {
9976
10223
  useEffect(() => {
9977
10224
  loadData();
9978
10225
  }, []);
10226
+ // Parameters that should be excluded from the UI (handled by the backend)
9979
10227
  const currentParameters = useMemo(() => {
9980
10228
  if (!selectedProcedure)
9981
10229
  return [];
9982
- return allParameters.filter((p) => p.FullName === selectedProcedure.FullName);
10230
+ return allParameters.filter((p) => p.FullName === selectedProcedure.FullName &&
10231
+ !BACKEND_MANAGED_PARAMS.includes(p.ParameterName.toLowerCase()));
9983
10232
  }, [selectedProcedure, allParameters]);
9984
10233
  const handleProcedureChange = (proc) => {
9985
10234
  setSelectedProcedure(proc);
@@ -9991,8 +10240,10 @@ const SPExecutorPage = () => {
9991
10240
  setError("");
9992
10241
  const startTime = Date.now();
9993
10242
  // Build parameters array - only include checked parameters
10243
+ // Also filter out backend-managed params (@User) as a safety net
9994
10244
  const parameters = formState
9995
- .filter((p) => p.include)
10245
+ .filter((p) => p.include &&
10246
+ !BACKEND_MANAGED_PARAMS.includes(p.parameterName.toLowerCase()))
9996
10247
  .map((p) => ({
9997
10248
  name: p.parameterName,
9998
10249
  value: p.sendAsNull ? null : p.value,
@@ -10812,7 +11063,7 @@ const SaveUpdateDeleteViewModalV2 = ({ open, mode, handleClose, view, }) => {
10812
11063
  React__default.createElement("form", { onSubmit: handleSubmit(onSubmit) },
10813
11064
  React__default.createElement(MesfModal.Content, { dividers: true, style: { padding: "15px 30px" } },
10814
11065
  React__default.createElement(Grid2, { container: true, spacing: 1 },
10815
- React__default.createElement(Grid2, { size: 12 }, mode === "create" && views.length > 0 && viewSelected ? (React__default.createElement(Autocomplete$1, { size: "small", id: "list-of-views", options: views, defaultValue: viewSelected, getOptionLabel: (option) => {
11066
+ React__default.createElement(Grid2, { size: 12 }, mode === "create" && views.length > 0 && viewSelected ? (React__default.createElement(Autocomplete, { size: "small", id: "list-of-views", options: views, defaultValue: viewSelected, getOptionLabel: (option) => {
10816
11067
  if (typeof option === "string") {
10817
11068
  return option;
10818
11069
  }
@@ -11242,7 +11493,7 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
11242
11493
  backgroundColor: "white",
11243
11494
  width: "100%",
11244
11495
  } },
11245
- React__default.createElement(Autocomplete$1, { size: "small", id: "view-selector", options: views, getOptionLabel: (option) => option.ViewName, value: viewSelected, isOptionEqualToValue: (option, value) => option.ViewId === (value === null || value === void 0 ? void 0 : value.ViewId), onChange: handleViewChange, noOptionsText: "No views available", renderOption: (props, option) => (React__default.createElement(Box, Object.assign({}, props, { component: "li", style: {
11496
+ React__default.createElement(Autocomplete, { size: "small", id: "view-selector", options: views, getOptionLabel: (option) => option.ViewName, value: viewSelected, isOptionEqualToValue: (option, value) => option.ViewId === (value === null || value === void 0 ? void 0 : value.ViewId), onChange: handleViewChange, noOptionsText: "No views available", renderOption: (props, option) => (React__default.createElement(Box, Object.assign({}, props, { component: "li", style: {
11246
11497
  display: "flex",
11247
11498
  justifyContent: "space-between",
11248
11499
  width: "100%",
@@ -12163,7 +12414,7 @@ const BitSelectorModal = ({ open, handleClose, viewTags, onAddBits, existingBitT
12163
12414
  React__default.createElement(Grid2, { container: true, spacing: 2 },
12164
12415
  React__default.createElement(Grid2, { size: 12 },
12165
12416
  React__default.createElement(Typography$1, { variant: "subtitle2", sx: { mb: 1 } }, "Select Source Tag"),
12166
- React__default.createElement(Autocomplete$1, { size: "small", id: "source-tag-selector", options: availableTags, getOptionLabel: (option) => option.Alias || option.TagName, value: selectedTag, onChange: handleTagChange, noOptionsText: "No tags available in current view", renderOption: (props, option) => (React__default.createElement(Box, Object.assign({}, props, { component: "li" }),
12417
+ React__default.createElement(Autocomplete, { size: "small", id: "source-tag-selector", options: availableTags, getOptionLabel: (option) => option.Alias || option.TagName, value: selectedTag, onChange: handleTagChange, noOptionsText: "No tags available in current view", renderOption: (props, option) => (React__default.createElement(Box, Object.assign({}, props, { component: "li" }),
12167
12418
  React__default.createElement(Box, { sx: {
12168
12419
  display: "flex",
12169
12420
  justifyContent: "space-between",
@@ -12273,7 +12524,7 @@ const LoadViewModalV2 = ({ open, handleClose }) => {
12273
12524
  React__default.createElement("input", { type: "checkbox", checked: allViewsChecked, onChange: handleAllViewsCheckbox }),
12274
12525
  React__default.createElement(Typography$1, null, "All Views")))),
12275
12526
  React__default.createElement(Grid2, { size: 12 },
12276
- React__default.createElement(Autocomplete$1, { size: "small", id: "list-of-views", noOptionsText: allViewsChecked
12527
+ React__default.createElement(Autocomplete, { size: "small", id: "list-of-views", noOptionsText: allViewsChecked
12277
12528
  ? "No views detected, please create a new view"
12278
12529
  : "No public views detected, please create a new view", options: displayedViews, getOptionLabel: (option) => option.ViewName, onChange: (ev, val) => setOptionSelected(val), defaultValue: optionSelected || viewSelected, style: { width: "100%" }, renderOption: (props, option) => (React__default.createElement(Box, Object.assign({}, props, { component: "li" }),
12279
12530
  React__default.createElement(Box, { sx: {
@@ -15501,7 +15752,7 @@ const AssetsFilter = ({ label = "Asset", value, onChange, filterAreaAssets = fal
15501
15752
  ];
15502
15753
  const selectedOption = options.find((option) => option.value === (value || null)) || options[0];
15503
15754
  return (React__default.createElement(React__default.Fragment, null,
15504
- React__default.createElement(Autocomplete$1, { options: filterAreaAssets ? options.filter((o) => o.isAreaAsset) : options, value: selectedOption, onChange: (event, newValue) => {
15755
+ React__default.createElement(Autocomplete, { options: filterAreaAssets ? options.filter((o) => o.isAreaAsset) : options, value: selectedOption, onChange: (event, newValue) => {
15505
15756
  var _a;
15506
15757
  if (newValue) {
15507
15758
  onChange((_a = newValue.value) !== null && _a !== void 0 ? _a : null);
@@ -15592,7 +15843,7 @@ const ShiftAutocomplete = ({ currentShiftId, value, onShiftSelected, disabled, s
15592
15843
  return (React__default.createElement(React__default.Fragment, null,
15593
15844
  React__default.createElement(Grid2, { container: true },
15594
15845
  React__default.createElement(Grid2, { size: { xs: 12 } },
15595
- React__default.createElement(Autocomplete, { loading: isLoading, options: rows || [], getOptionLabel: (option) => {
15846
+ React__default.createElement(Autocomplete$1, { loading: isLoading, options: rows || [], getOptionLabel: (option) => {
15596
15847
  return `${moment$c
15597
15848
  .utc(option.ProductionDate)
15598
15849
  .format("MM/DD/YYYY")} - ${option.Shift} - ${option.Crew}`;
@@ -15620,7 +15871,7 @@ const ShiftSelector = ({ label = "Shift - Crew", value, onChange = () => { }, fi
15620
15871
  }
15621
15872
  }, [isError, e]);
15622
15873
  return (React__default.createElement(React__default.Fragment, null,
15623
- React__default.createElement(Autocomplete, { id: "clear-on-escape", clearOnEscape: true, options: shifts || [], getOptionLabel: (option) => `${option.CurrentShift} - ${option.CurrentCrew}`, disabled: disabled, renderInput: (params) => (React__default.createElement(TextField, Object.assign({}, params, { label: label, variant: "outlined", fullWidth: true, size: "small", error: !!fieldError, helperText: fieldError === null || fieldError === void 0 ? void 0 : fieldError.message, InputProps: Object.assign(Object.assign({}, params.InputProps), { endAdornment: (React__default.createElement(React__default.Fragment, null, isLoading ? (React__default.createElement(CircularProgress, { color: "inherit", size: 20 })) : (React__default.createElement(React__default.Fragment, null, params.InputProps.endAdornment)))) }) }))), value: selectedShift, onChange: (event, newValue) => {
15874
+ React__default.createElement(Autocomplete$1, { id: "clear-on-escape", clearOnEscape: true, options: shifts || [], getOptionLabel: (option) => `${option.CurrentShift} - ${option.CurrentCrew}`, disabled: disabled, renderInput: (params) => (React__default.createElement(TextField, Object.assign({}, params, { label: label, variant: "outlined", fullWidth: true, size: "small", error: !!fieldError, helperText: fieldError === null || fieldError === void 0 ? void 0 : fieldError.message, InputProps: Object.assign(Object.assign({}, params.InputProps), { endAdornment: (React__default.createElement(React__default.Fragment, null, isLoading ? (React__default.createElement(CircularProgress, { color: "inherit", size: 20 })) : (React__default.createElement(React__default.Fragment, null, params.InputProps.endAdornment)))) }) }))), value: selectedShift, onChange: (event, newValue) => {
15624
15875
  var _a;
15625
15876
  onChange((_a = newValue === null || newValue === void 0 ? void 0 : newValue.CurrentShiftId) !== null && _a !== void 0 ? _a : null);
15626
15877
  } }),
@@ -17858,7 +18109,7 @@ const SectionSelector = ({ value, onChange, topSectionsCount = 5, disabled = fal
17858
18109
  gap: 1,
17859
18110
  flexWrap: "wrap",
17860
18111
  } },
17861
- React__default.createElement(Autocomplete$1, { open: open, onOpen: () => setOpen(true), onClose: () => setOpen(false), value: value, onChange: (_, newValue) => onChange(newValue), inputValue: inputValue, onInputChange: (_, newInputValue) => setInputValue(newInputValue), options: options, loading: loading, disabled: disabled, getOptionLabel: (option) => option.SectionName, isOptionEqualToValue: (option, value) => option.SectionId === value.SectionId, sx: { minWidth: 120, maxWidth: 150 }, renderOption: (props, option) => (React__default.createElement(Box, Object.assign({ component: "li" }, props, { key: option.SectionId, sx: { display: "flex", justifyContent: "space-between" } }),
18112
+ React__default.createElement(Autocomplete, { open: open, onOpen: () => setOpen(true), onClose: () => setOpen(false), value: value, onChange: (_, newValue) => onChange(newValue), inputValue: inputValue, onInputChange: (_, newInputValue) => setInputValue(newInputValue), options: options, loading: loading, disabled: disabled, getOptionLabel: (option) => option.SectionName, isOptionEqualToValue: (option, value) => option.SectionId === value.SectionId, sx: { minWidth: 120, maxWidth: 150 }, renderOption: (props, option) => (React__default.createElement(Box, Object.assign({ component: "li" }, props, { key: option.SectionId, sx: { display: "flex", justifyContent: "space-between" } }),
17862
18113
  React__default.createElement(Typography$1, { fontWeight: 500 }, option.SectionName))), renderInput: (params) => (React__default.createElement(TextField, Object.assign({}, params, { label: label, placeholder: "####", size: "small", slotProps: {
17863
18114
  input: Object.assign(Object.assign({}, params.InputProps), { endAdornment: (React__default.createElement(React__default.Fragment, null,
17864
18115
  loading ? (React__default.createElement(CircularProgress, { color: "inherit", size: 16 })) : null,
@@ -17904,7 +18155,7 @@ const SectionMultiSelect = ({ value, onChange, topSectionsCount = 5, disabled =
17904
18155
  gap: 1,
17905
18156
  flexWrap: "wrap",
17906
18157
  } },
17907
- React__default.createElement(Autocomplete$1, { multiple: true, open: open, onOpen: () => setOpen(true), onClose: () => setOpen(false), value: value, onChange: (_, newValue) => onChange(newValue), inputValue: inputValue, onInputChange: (_, newInputValue) => setInputValue(newInputValue), options: options, loading: loading, disabled: disabled, getOptionLabel: (option) => option.SectionName, isOptionEqualToValue: (option, val) => option.SectionId === val.SectionId, limitTags: 2, size: "small", sx: { minWidth: 200, flex: 1 }, renderOption: (props, option) => (React__default.createElement(Box, Object.assign({ component: "li" }, props, { key: option.SectionId, sx: { display: "flex", justifyContent: "space-between" } }),
18158
+ React__default.createElement(Autocomplete, { multiple: true, open: open, onOpen: () => setOpen(true), onClose: () => setOpen(false), value: value, onChange: (_, newValue) => onChange(newValue), inputValue: inputValue, onInputChange: (_, newInputValue) => setInputValue(newInputValue), options: options, loading: loading, disabled: disabled, getOptionLabel: (option) => option.SectionName, isOptionEqualToValue: (option, val) => option.SectionId === val.SectionId, limitTags: 2, size: "small", sx: { minWidth: 200, flex: 1 }, renderOption: (props, option) => (React__default.createElement(Box, Object.assign({ component: "li" }, props, { key: option.SectionId, sx: { display: "flex", justifyContent: "space-between" } }),
17908
18159
  React__default.createElement(Typography$1, { fontWeight: 500 }, option.SectionName))), renderInput: (params) => (React__default.createElement(TextField, Object.assign({}, params, { label: label, placeholder: value.length === 0 ? "All sections" : "", size: "small", slotProps: {
17909
18160
  input: Object.assign(Object.assign({}, params.InputProps), { endAdornment: (React__default.createElement(React__default.Fragment, null,
17910
18161
  loading ? (React__default.createElement(CircularProgress, { color: "inherit", size: 16 })) : null,