@dexteel/mesf-core 7.21.0 → 7.22.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.21.0"
2
+ ".": "7.22.1"
3
3
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [7.22.1](https://github.com/dexteel/mesf-core-frontend/compare/@dexteel/mesf-core-v7.22.0...@dexteel/mesf-core-v7.22.1) (2026-05-11)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **logs:** improve large log filtering performance ([80eaa0a](https://github.com/dexteel/mesf-core-frontend/commit/80eaa0a0f0535e0e3f67397d85b97efaa7b8659b))
9
+
10
+ ## [7.22.0](https://github.com/dexteel/mesf-core-frontend/compare/@dexteel/mesf-core-v7.21.0...@dexteel/mesf-core-v7.22.0) (2026-05-09)
11
+
12
+
13
+ ### Features
14
+
15
+ * **trendings-v2:** simplify chart layout ([114ea8f](https://github.com/dexteel/mesf-core-frontend/commit/114ea8fd2f5495f8ccc2d52bcff0bdb6d5202999))
16
+
3
17
  ## [7.21.0](https://github.com/dexteel/mesf-core-frontend/compare/@dexteel/mesf-core-v7.20.1...@dexteel/mesf-core-v7.21.0) (2026-04-24)
4
18
 
5
19
 
@@ -1,4 +1,4 @@
1
1
  import { ColDef } from "ag-grid-community";
2
- export declare const useLogTableData: () => {
2
+ export declare const useLogTableData: (timezone: "UTC" | "Server") => {
3
3
  columnDefs: ColDef<any, any>[];
4
4
  };
package/dist/index.esm.js CHANGED
@@ -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, ExpandLess, ExpandMore, Square as Square$1, Timeline, Send, Menu as Menu$1, People, Storage, Group as Group$1, 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';
28
+ import { ArrowRight, ArrowBackRounded, ArrowForwardRounded, SkipNext, ChevronLeft, ChevronRight, Cloud, ExpandLess, ExpandMore, Square as Square$1, Timeline, Send, Menu as Menu$1, People, Storage, Group as Group$1, Assignment, Chat, ViewList, Build, Settings as Settings$2, Code as Code$1, KeyboardDoubleArrowLeft, KeyboardArrowLeft, KeyboardArrowRight, KeyboardDoubleArrowRight, Update, ZoomIn, Restore, Lock, Create, Delete, Folder, InsertChart, Search, PlaylistAdd, DragIndicator, Save, AttachFile, CloudUpload, GetApp } from '@mui/icons-material';
29
29
  import ContentCopyIcon from '@mui/icons-material/ContentCopy';
30
30
  import FormatListBulletedSharpIcon from '@mui/icons-material/FormatListBulletedSharp';
31
31
  import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
@@ -7853,14 +7853,14 @@ const TagFilter = ({ tagFilters, setTagFilters, filterContext, }) => {
7853
7853
  startDate: filterContext.startDate,
7854
7854
  endDate: filterContext.endDate,
7855
7855
  logTypeCode: filterContext.logTypeCode,
7856
- tagFilters,
7856
+ tagFilters: filterContext.tagFilters,
7857
7857
  });
7858
7858
  const { data: tagValues, isLoading: isLoadingValues, error: valuesError, isError: isValuesError, } = useSearchLogTagValues({
7859
7859
  tagName: selectedTag ? selectedTag.TagName : "",
7860
7860
  startDate: filterContext.startDate,
7861
7861
  endDate: filterContext.endDate,
7862
7862
  logTypeCode: filterContext.logTypeCode,
7863
- tagFilters,
7863
+ tagFilters: filterContext.tagFilters,
7864
7864
  });
7865
7865
  const handleOpenPopover = (event) => {
7866
7866
  setAnchorEl(event.currentTarget);
@@ -8056,17 +8056,24 @@ const SearchFilter = ({ search, setSearch }) => {
8056
8056
  }, label: "Search", variant: "outlined", size: "small", value: search, onChange: (e) => setSearch(e.target.value), autoComplete: "off" })));
8057
8057
  };
8058
8058
 
8059
- const useLogTableData = () => {
8059
+ const useLogTableData = (timezone) => {
8060
8060
  const backgroundColor = (logTypeCode) => {
8061
8061
  return get(LOG_TYPE_CODES, `${logTypeCode[0]}.color`, "#BBBBBB");
8062
8062
  };
8063
- const [columnDefs] = useState([
8063
+ const columnDefs = useMemo(() => [
8064
8064
  {
8065
8065
  field: "Timestamp",
8066
8066
  headerName: "Time",
8067
8067
  minWidth: 220,
8068
8068
  flex: 1,
8069
8069
  headerClass: "ag-header-cell-centered",
8070
+ valueFormatter: ({ value }) => {
8071
+ if (!value)
8072
+ return "";
8073
+ return timezone === "UTC"
8074
+ ? moment$g(value).utc().format("YYYY-MM-DD HH:mm:ss z")
8075
+ : dxtToLocalServerTime(value, "yyyy-MM-dd HH:mm:ss z");
8076
+ },
8070
8077
  },
8071
8078
  {
8072
8079
  field: "Source",
@@ -8126,7 +8133,7 @@ const useLogTableData = () => {
8126
8133
  valueFormatter: ({ value }) => value || " ",
8127
8134
  headerClass: "ag-header-cell-centered",
8128
8135
  },
8129
- ]);
8136
+ ], [timezone]);
8130
8137
  return { columnDefs };
8131
8138
  };
8132
8139
 
@@ -8148,7 +8155,7 @@ const getLogs = (params, signal) => __awaiter(void 0, void 0, void 0, function*
8148
8155
  },
8149
8156
  { name: "TagFilters", value: tagFiltersJson },
8150
8157
  ];
8151
- const resp = yield apiService.callV2("[MES].[GetLogs]", parameters);
8158
+ const resp = yield apiService.callV2("[MES].[GetLogs]", parameters, signal);
8152
8159
  if (resp.ok) {
8153
8160
  let rows = get(resp, "data.tables[0].rows", []);
8154
8161
  rows = rows.map((log) => (Object.assign(Object.assign({}, log), { Timestamp: log.Timestamp ? moment$g.utc(log["Timestamp"]).toDate() : null })));
@@ -8271,48 +8278,55 @@ const useSearchLogs = ({ startDate, endDate, logTypeCode, autoRefresh, tagFilter
8271
8278
  endDate,
8272
8279
  logTypeCode,
8273
8280
  tagFilters,
8274
- }),
8281
+ }, signal),
8275
8282
  refetchInterval: autoRefresh ? 5000 : false,
8276
8283
  enabled: !!startDate && (!!endDate || autoRefresh),
8284
+ keepPreviousData: true,
8277
8285
  staleTime: 10000,
8278
8286
  });
8279
8287
  };
8280
8288
  const getLogTypeByCodeId = (logTypeCodeId) => {
8281
8289
  return get(LOG_TYPE_CODES, `${logTypeCodeId}.description`, " -");
8282
8290
  };
8291
+ const getDefaultFilters = () => ({
8292
+ startDate: moment$g().add(-5, "days").hour(0).minute(0).second(0).toDate(),
8293
+ endDate: moment$g().hour(23).minute(59).second(59).toDate(),
8294
+ logTypeCode: ["I", "W", "E"],
8295
+ autoRefresh: false,
8296
+ tagFilters: [],
8297
+ });
8298
+ const copyFilters = (filters) => (Object.assign(Object.assign({}, filters), { logTypeCode: [...filters.logTypeCode], tagFilters: [...filters.tagFilters] }));
8283
8299
  const TableLogs = () => {
8284
- const [startDate, setStartDate] = useState(moment$g().add(-5, "days").hour(0).minute(0).second(0).toDate());
8285
- const [endDate, setEndDate] = useState(moment$g().hour(23).minute(59).second(59).toDate());
8300
+ var _a;
8301
+ const [draftFilters, setDraftFilters] = useState(() => getDefaultFilters());
8302
+ const [appliedFilters, setAppliedFilters] = useState(() => getDefaultFilters());
8303
+ const [isApplyingFilters, setIsApplyingFilters] = useState(false);
8304
+ const hasMountedRef = useRef(false);
8286
8305
  const [timezone, setTimezone] = useState("UTC");
8287
8306
  const [search, setSearch] = useState("");
8288
- const [logTypeCode, setLogTypeCode] = useState(["I", "W", "E"]);
8289
- const [autoRefresh, setAutoRefresh] = useState(false);
8290
- const [tagFilters, setTagFilters] = useState([]);
8291
8307
  const [gridAPI, setGridAPI] = useState(null);
8292
8308
  const [error, setError] = useState("");
8293
8309
  const [showLogModal, setShowLogModal] = useState(false);
8294
8310
  const [selectedLog, setSelectedLog] = useState(undefined);
8295
- const { data: rows, isLoading, refetch, isError, error: e, } = useSearchLogs({
8296
- startDate,
8297
- endDate,
8298
- logTypeCode: logTypeCode.join(","),
8299
- autoRefresh,
8300
- tagFilters,
8311
+ const { data: rows, isLoading, isFetching, isError, error: e, } = useSearchLogs({
8312
+ startDate: appliedFilters.startDate,
8313
+ endDate: appliedFilters.endDate,
8314
+ logTypeCode: appliedFilters.logTypeCode.join(","),
8315
+ autoRefresh: appliedFilters.autoRefresh,
8316
+ tagFilters: appliedFilters.tagFilters,
8301
8317
  });
8302
8318
  const onGridReady = (params) => {
8303
8319
  setGridAPI(params.api);
8304
8320
  };
8305
- const formattedRows = rows === null || rows === void 0 ? void 0 : rows.map(({ LogId, Timestamp, Source, Message, LogTypeCode, User }) => ({
8321
+ const formattedRows = useMemo(() => rows === null || rows === void 0 ? void 0 : rows.map(({ LogId, Timestamp, Source, Message, LogTypeCode, User }) => ({
8306
8322
  id: LogId,
8307
- Timestamp: timezone === "UTC"
8308
- ? moment$g(Timestamp).utc().format("YYYY-MM-DD HH:mm:ss z")
8309
- : dxtToLocalServerTime(Timestamp, "yyyy-MM-dd HH:mm:ss z"),
8323
+ Timestamp,
8310
8324
  Source,
8311
8325
  Message: isNil(Message) ? "" : Message.replaceAll("Added", " Added"),
8312
8326
  LogTypeCode: getLogTypeByCodeId(LogTypeCode),
8313
8327
  User,
8314
- }));
8315
- const { columnDefs } = useLogTableData();
8328
+ })), [rows]);
8329
+ const { columnDefs } = useLogTableData(timezone);
8316
8330
  const defaultColDef = useMemo(() => {
8317
8331
  return {
8318
8332
  sortable: true,
@@ -8328,16 +8342,17 @@ const TableLogs = () => {
8328
8342
  };
8329
8343
  }, []);
8330
8344
  const { showContextMenu, registerConfig } = useContextMenuMESF();
8345
+ const handleAutoRefreshChange = (checked) => {
8346
+ const nextFilters = checked
8347
+ ? Object.assign(Object.assign({}, draftFilters), { startDate: moment$g().add(-15, "minutes").toDate(), endDate: null, autoRefresh: true }) : Object.assign(Object.assign({}, draftFilters), { endDate: moment$g().hour(23).minute(59).second(59).toDate(), autoRefresh: false });
8348
+ setDraftFilters(copyFilters(nextFilters));
8349
+ };
8331
8350
  const handleResetButtonClick = () => {
8332
- setStartDate(moment$g().add(-5, "days").hour(0).minute(0).second(0).toDate());
8333
- setEndDate(moment$g().hour(23).minute(59).second(59).toDate());
8351
+ const filters = getDefaultFilters();
8352
+ setDraftFilters(copyFilters(filters));
8334
8353
  setSearch("");
8335
- gridAPI === null || gridAPI === void 0 ? void 0 : gridAPI.setGridOption("quickFilterText", "");
8336
- setLogTypeCode(["I", "W", "E"]);
8337
- setTagFilters([]);
8338
8354
  setSelectedLog(undefined);
8339
8355
  setError("");
8340
- refetch();
8341
8356
  };
8342
8357
  const rowClicked = (rowClickedEvent) => {
8343
8358
  let data = rowClickedEvent.data;
@@ -8360,11 +8375,11 @@ const TableLogs = () => {
8360
8375
  handleResetButtonClick,
8361
8376
  });
8362
8377
  const filterContext = useMemo(() => ({
8363
- startDate,
8364
- endDate,
8365
- logTypeCode: logTypeCode.join(","),
8366
- tagFilters,
8367
- }), [startDate, endDate, logTypeCode, tagFilters]);
8378
+ startDate: appliedFilters.startDate,
8379
+ endDate: appliedFilters.endDate,
8380
+ logTypeCode: appliedFilters.logTypeCode.join(","),
8381
+ tagFilters: appliedFilters.tagFilters,
8382
+ }), [appliedFilters]);
8368
8383
  useEffect(() => {
8369
8384
  registerConfig({
8370
8385
  id: "TableLogs",
@@ -8376,6 +8391,24 @@ const TableLogs = () => {
8376
8391
  setError(e.message);
8377
8392
  }
8378
8393
  }, [isError, e]);
8394
+ useEffect(() => {
8395
+ if (!hasMountedRef.current) {
8396
+ hasMountedRef.current = true;
8397
+ return;
8398
+ }
8399
+ setIsApplyingFilters(true);
8400
+ const timeout = window.setTimeout(() => {
8401
+ setAppliedFilters(copyFilters(draftFilters));
8402
+ setIsApplyingFilters(false);
8403
+ }, 100);
8404
+ return () => window.clearTimeout(timeout);
8405
+ }, [draftFilters]);
8406
+ useEffect(() => {
8407
+ const timeout = window.setTimeout(() => {
8408
+ gridAPI === null || gridAPI === void 0 ? void 0 : gridAPI.setGridOption("quickFilterText", search);
8409
+ }, 350);
8410
+ return () => window.clearTimeout(timeout);
8411
+ }, [gridAPI, search]);
8379
8412
  return (React.createElement(React.Fragment, null,
8380
8413
  React.createElement(Grid2, { container: true, justifyContent: "flex-start", p: 1, spacing: 1 },
8381
8414
  React.createElement(Grid2, { size: { md: 12, xs: 12 } },
@@ -8402,43 +8435,32 @@ const TableLogs = () => {
8402
8435
  React.createElement(CardContent, { sx: { width: "100%" } },
8403
8436
  React.createElement(Grid2, { container: true, alignItems: "center", direction: "row", spacing: 2 },
8404
8437
  React.createElement(Grid2, { size: { md: 1.5 } },
8405
- React.createElement(DateFilter, { label: "From", date: startDate, setDate: (date) => setStartDate(date || new Date()), maxDate: endDate !== null && endDate !== void 0 ? endDate : undefined })),
8438
+ React.createElement(DateFilter, { label: "From", date: draftFilters.startDate, setDate: (date) => setDraftFilters(Object.assign(Object.assign({}, draftFilters), { startDate: date || new Date() })), maxDate: (_a = draftFilters.endDate) !== null && _a !== void 0 ? _a : undefined })),
8406
8439
  React.createElement(Grid2, { size: { md: 1.5 } },
8407
- React.createElement(DateFilter, { label: "To", date: endDate, setDate: (date) => {
8440
+ React.createElement(DateFilter, { label: "To", date: draftFilters.endDate, setDate: (date) => {
8408
8441
  if (date) {
8409
- setEndDate(date);
8410
- setAutoRefresh(false);
8442
+ setDraftFilters(Object.assign(Object.assign({}, draftFilters), { endDate: date, autoRefresh: false }));
8411
8443
  }
8412
- }, minDate: startDate })),
8444
+ }, minDate: draftFilters.startDate })),
8413
8445
  React.createElement(Grid2, { size: { md: 2, xs: 12 } },
8414
- React.createElement(CodeFilter, { LogTypeCode: logTypeCode, setLogTypeCodeFilter: (logTypeCodes) => setLogTypeCode(logTypeCodes) })),
8446
+ React.createElement(CodeFilter, { LogTypeCode: draftFilters.logTypeCode, setLogTypeCodeFilter: (logTypeCodes) => setDraftFilters(Object.assign(Object.assign({}, draftFilters), { logTypeCode: logTypeCodes })) })),
8415
8447
  React.createElement(Grid2, { size: { md: 1, xs: 12 } },
8416
8448
  React.createElement(TimezoneSelector, { value: timezone, onChange: setTimezone })),
8417
8449
  React.createElement(Grid2, { size: { md: 1.5, xs: 12 } },
8418
- React.createElement(FormControlLabel, { checked: autoRefresh, control: React.createElement(Switch, { color: "primary" }), label: "Auto Refresh", onChange: (e, checked) => {
8419
- if (checked) {
8420
- setEndDate(null);
8421
- }
8422
- else {
8423
- setEndDate(moment$g().hour(23).minute(59).second(59).toDate());
8424
- }
8425
- setAutoRefresh(checked);
8426
- } })),
8450
+ React.createElement(FormControlLabel, { checked: draftFilters.autoRefresh, control: React.createElement(Switch, { color: "primary" }), label: "Auto Refresh", onChange: (e, checked) => handleAutoRefreshChange(checked) })),
8427
8451
  React.createElement(Grid2, { size: { md: 3.5, xs: 12 } },
8428
- React.createElement(SearchFilter, { search: search, setSearch: (search) => {
8429
- setSearch(search);
8430
- gridAPI === null || gridAPI === void 0 ? void 0 : gridAPI.setGridOption("quickFilterText", search);
8431
- } })),
8452
+ React.createElement(SearchFilter, { search: search, setSearch: setSearch })),
8432
8453
  React.createElement(Grid2, { size: { md: 1, xs: 12 }, style: { paddingTop: 8 } },
8433
8454
  React.createElement(Button, { variant: "contained", color: "inherit", onClick: handleResetButtonClick, fullWidth: true }, "Reset")),
8434
8455
  React.createElement(Grid2, { size: { md: 12, xs: 12 }, sx: { mt: 1 } },
8435
- React.createElement(TagFilter, { tagFilters: tagFilters, setTagFilters: setTagFilters, filterContext: filterContext })))))),
8456
+ React.createElement(TagFilter, { tagFilters: draftFilters.tagFilters, setTagFilters: (tagFilters) => setDraftFilters(Object.assign(Object.assign({}, draftFilters), { tagFilters })), filterContext: filterContext })))))),
8436
8457
  React.createElement(Grid2, { size: { md: 12, xs: 12 }, style: {
8437
8458
  height: "70vh",
8438
8459
  } },
8439
8460
  React.createElement(Paper, { style: { height: "100%", width: "100%" } },
8440
- React.createElement(AgGridReact, { loading: isLoading, gridOptions: {
8461
+ React.createElement(AgGridReact, { loading: isLoading || isApplyingFilters || isFetching, gridOptions: {
8441
8462
  theme: themeDXT,
8463
+ cacheQuickFilter: true,
8442
8464
  }, rowData: formattedRows, columnDefs: columnDefs, defaultColDef: defaultColDef, onGridReady: onGridReady, getRowId: (params) => params.data.id, rowHeight: 34, headerHeight: 40, animateRows: true, loadingOverlayComponent: CenteredLazyLoading, getContextMenuItems: (e) => getContextMenuItems(e), rowSelection: "single", onRowDoubleClicked: (e) => {
8443
8465
  rowClicked(e);
8444
8466
  } })))),
@@ -11861,9 +11883,9 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
11861
11883
  steppedLines: true,
11862
11884
  showLegend: false,
11863
11885
  showTooltip: true,
11864
- combinedView: false,
11886
+ combinedView: true,
11865
11887
  showToolbox: true,
11866
- showYAxisNames: true,
11888
+ showYAxisNames: false,
11867
11889
  });
11868
11890
  const [aggregationMode, setAggregationModeState] = useState("avg");
11869
11891
  // View management state
@@ -11999,12 +12021,13 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
11999
12021
  width: "100%",
12000
12022
  } },
12001
12023
  React__default.createElement(Grid2, null,
12002
- React__default.createElement(IconButton$1, { onClick: () => handleDateNavigator("subtract"), size: "small" },
12003
- React__default.createElement(ChevronLeft, { fontSize: "medium", sx: { color: "black" } }))),
12024
+ React__default.createElement(Tooltip, { title: "Previous period", arrow: true },
12025
+ React__default.createElement(IconButton$1, { onClick: () => handleDateNavigator("subtract"), size: "small" },
12026
+ React__default.createElement(KeyboardDoubleArrowLeft, { fontSize: "medium", sx: { color: "black" } })))),
12004
12027
  React__default.createElement(Grid2, null,
12005
- React__default.createElement(Tooltip, { title: "Navigate backward 20%", arrow: true },
12028
+ React__default.createElement(Tooltip, { title: "Pan backward 20%", arrow: true },
12006
12029
  React__default.createElement(IconButton$1, { onClick: () => handlePartialDateNavigator("subtract"), size: "small" },
12007
- React__default.createElement(FastRewind, { fontSize: "medium", sx: { color: "black" } })))),
12030
+ React__default.createElement(KeyboardArrowLeft, { fontSize: "medium", sx: { color: "black" } })))),
12008
12031
  React__default.createElement(Grid2, { size: { md: 3.5 } },
12009
12032
  React__default.createElement(LocalizationProvider$1, { dateAdapter: AdapterMoment },
12010
12033
  React__default.createElement(DateTimePicker, { label: "Start", format: "MM/DD/YYYY HH:mm:ss", value: moment$g(timeScopeStart), onChange: (newValue) => {
@@ -12042,15 +12065,17 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
12042
12065
  },
12043
12066
  }, disabled: autoRefresh }))),
12044
12067
  React__default.createElement(Grid2, null,
12045
- React__default.createElement(Tooltip, { title: "Navigate forward 20%", arrow: true },
12068
+ React__default.createElement(Tooltip, { title: "Pan forward 20%", arrow: true },
12046
12069
  React__default.createElement(IconButton$1, { onClick: () => handlePartialDateNavigator("add"), size: "small" },
12047
- React__default.createElement(FastForward, { fontSize: "medium", sx: { color: "black" } })))),
12070
+ React__default.createElement(KeyboardArrowRight, { fontSize: "medium", sx: { color: "black" } })))),
12048
12071
  React__default.createElement(Grid2, null,
12049
- React__default.createElement(IconButton$1, { onClick: () => handleDateNavigator("add"), size: "small" },
12050
- React__default.createElement(ChevronRight, { fontSize: "medium", sx: { color: "black" } }))),
12072
+ React__default.createElement(Tooltip, { title: "Next period", arrow: true },
12073
+ React__default.createElement(IconButton$1, { onClick: () => handleDateNavigator("add"), size: "small" },
12074
+ React__default.createElement(KeyboardDoubleArrowRight, { fontSize: "medium", sx: { color: "black" } })))),
12051
12075
  React__default.createElement(Grid2, null,
12052
- React__default.createElement(IconButton$1, { onClick: () => handleDateNavigator("subtract", true), size: "small" },
12053
- React__default.createElement(SkipNext, { fontSize: "medium", sx: { color: "black" } }))))),
12076
+ React__default.createElement(Tooltip, { title: "Jump to current time", arrow: true },
12077
+ React__default.createElement(IconButton$1, { onClick: () => handleDateNavigator("subtract", true), size: "small" },
12078
+ React__default.createElement(Update, { fontSize: "medium", sx: { color: "black" } })))))),
12054
12079
  React__default.createElement(Grid2, { size: { md: 5, sm: 6, xs: 12 } },
12055
12080
  React__default.createElement(Paper, { elevation: 0, sx: {
12056
12081
  p: 1,
@@ -12062,7 +12087,7 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
12062
12087
  alignItems: "stretch",
12063
12088
  justifyContent: "space-between",
12064
12089
  } },
12065
- React__default.createElement(Box, { sx: { width: 230 } },
12090
+ React__default.createElement(Box, { sx: { width: 155 } },
12066
12091
  React__default.createElement(FormControl, { fullWidth: true, size: "small" },
12067
12092
  React__default.createElement(Select, { multiple: true, value: [
12068
12093
  ...(customOptions.showGridLines ? ["grid"] : []),
@@ -12076,20 +12101,10 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
12076
12101
  const selected = e.target.value;
12077
12102
  setCustomOptions((prevOptions) => (Object.assign(Object.assign({}, prevOptions), { showGridLines: selected.includes("grid"), showSymbols: selected.includes("symbols"), smoothLines: selected.includes("smooth") &&
12078
12103
  !selected.includes("stepped"), steppedLines: selected.includes("stepped"), showTooltip: selected.includes("tooltip"), showToolbox: selected.includes("toolbox"), showYAxisNames: selected.includes("yAxisNames") })));
12079
- }, renderValue: (selected) => {
12080
- const labels = {
12081
- grid: "Grid",
12082
- symbols: "Symbols",
12083
- smooth: "Smooth",
12084
- stepped: "Stepped",
12085
- tooltip: "Tooltip",
12086
- toolbox: "Toolbox",
12087
- yAxisNames: "Y-Axis Names",
12088
- };
12089
- return (React__default.createElement("span", { style: { fontSize: "0.75rem" } }, selected
12090
- .map((val) => labels[val])
12091
- .join(", ")));
12092
- } },
12104
+ }, renderValue: (selected) => (React__default.createElement("span", { style: { fontSize: "0.75rem" } },
12105
+ "Chart: ",
12106
+ selected.length,
12107
+ " options")) },
12093
12108
  React__default.createElement(MenuItem, { value: "grid", style: { padding: 0 } },
12094
12109
  React__default.createElement(Checkbox, { checked: customOptions.showGridLines, size: "small" }),
12095
12110
  React__default.createElement(ListItemText, null, "Grid")),
@@ -12115,16 +12130,14 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
12115
12130
  React__default.createElement(FormControl, { fullWidth: true, size: "small" },
12116
12131
  React__default.createElement(Select, { value: aggregationMode, onChange: (e) => {
12117
12132
  setAggregationModeState(e.target.value);
12118
- }, renderValue: (selected) => selected === "last"
12119
- ? "Aggregation: Last value"
12120
- : "Aggregation: Average" },
12133
+ }, renderValue: (selected) => selected === "last" ? "Agg: Last" : "Agg: Avg" },
12121
12134
  React__default.createElement(MenuItem, { value: "avg" }, "Average"),
12122
12135
  React__default.createElement(MenuItem, { value: "last" }, "Last value")))),
12123
12136
  React__default.createElement(Divider, { orientation: "vertical", flexItem: true }),
12124
12137
  React__default.createElement(FormControlLabel, { checked: customOptions.combinedView, control: React__default.createElement(Switch, { color: "primary", size: "small" }), label: React__default.createElement("span", { style: { fontSize: "0.75rem", fontWeight: 600 } }, "Combined"), style: { margin: "0" }, onChange: (e, checked) => {
12125
12138
  setCustomOptions((prevOptions) => (Object.assign(Object.assign({}, prevOptions), { combinedView: checked })));
12126
12139
  } }),
12127
- React__default.createElement(FormControlLabel, { checked: autoRefresh, control: React__default.createElement(Switch, { color: "primary", size: "small" }), label: React__default.createElement("span", { style: { fontSize: "0.75rem", fontWeight: 600 } }, "Auto Refresh"), style: { margin: "0" }, onChange: (e, checked) => {
12140
+ React__default.createElement(FormControlLabel, { checked: autoRefresh, control: React__default.createElement(Switch, { color: "primary", size: "small" }), label: React__default.createElement("span", { style: { fontSize: "0.75rem", fontWeight: 600 } }, "Auto"), style: { margin: "0" }, onChange: (e, checked) => {
12128
12141
  if (checked) {
12129
12142
  // When enabling auto-refresh, set end to now
12130
12143
  // and keep the current period to calculate start
@@ -12143,8 +12156,12 @@ const HeaderSectionV2 = React__default.memo(({ autoRefresh, setAutoRefresh, setC
12143
12156
  setAutoRefresh(checked);
12144
12157
  } }),
12145
12158
  React__default.createElement(Divider, { orientation: "vertical", flexItem: true }),
12146
- React__default.createElement(Button, { variant: "outlined", size: "small", color: "primary", startIcon: React__default.createElement(ZoomIn, null), onClick: handleZoomIn, style: { fontSize: "0.7rem" } }, "Zoom"),
12147
- React__default.createElement(Button, { variant: "outlined", size: "small", color: "primary", startIcon: React__default.createElement(Restore, null), onClick: handleRestoreZoom, style: { fontSize: "0.7rem" } }, "Restore")))),
12159
+ React__default.createElement(Tooltip, { title: "Area zoom", arrow: true },
12160
+ React__default.createElement(IconButton$1, { color: "primary", onClick: handleZoomIn, size: "small" },
12161
+ React__default.createElement(ZoomIn, { fontSize: "small" }))),
12162
+ React__default.createElement(Tooltip, { title: "Restore zoom", arrow: true },
12163
+ React__default.createElement(IconButton$1, { color: "primary", onClick: handleRestoreZoom, size: "small" },
12164
+ React__default.createElement(Restore, { fontSize: "small" })))))),
12148
12165
  React__default.createElement(Grid2, { size: { md: 2, sm: 6, xs: 12 }, container: true, justifyContent: "flex-end", alignItems: "center" },
12149
12166
  React__default.createElement(Paper, { elevation: 0, sx: {
12150
12167
  p: 1,
@@ -14539,10 +14556,21 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14539
14556
  steppedLines: true,
14540
14557
  showLegend: true,
14541
14558
  showTooltip: true,
14542
- combinedView: false,
14559
+ combinedView: true,
14543
14560
  showToolbox: true,
14544
- showYAxisNames: true,
14561
+ showYAxisNames: false,
14545
14562
  };
14563
+ const getTagName = useCallback((tag) => tag.Alias || tag.TagName, []);
14564
+ const getActiveAxisTag = useCallback((tags) => {
14565
+ if (tags.length === 0)
14566
+ return null;
14567
+ if (highlightedSeries) {
14568
+ const highlightedTag = tags.find((tag) => tag.IsVisible && getTagName(tag) === highlightedSeries);
14569
+ if (highlightedTag)
14570
+ return highlightedTag;
14571
+ }
14572
+ return tags.find((tag) => tag.IsVisible) || null;
14573
+ }, [highlightedSeries, getTagName]);
14546
14574
  // Clear zoom state when time scope changes or combined view toggles
14547
14575
  useEffect(() => {
14548
14576
  const currentTimeScope = `${timeScopeStart.getTime()}-${timeScopeEnd.getTime()}`;
@@ -14561,13 +14589,14 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14561
14589
  prevCombinedViewRef.current = opts.combinedView;
14562
14590
  }, [timeScopeStart, timeScopeEnd, opts.combinedView]);
14563
14591
  // Helper to build yAxis config with scale settings
14564
- const buildYAxisConfig = useCallback((tag, gridIndex, position, offset = 0) => {
14592
+ const buildYAxisConfig = useCallback((tag, gridIndex, position, offset = 0, isAxisVisible = true) => {
14565
14593
  const baseConfig = {
14566
14594
  gridIndex,
14567
14595
  type: "value",
14568
- name: opts.showYAxisNames ? tag.Alias || tag.TagName : "",
14596
+ show: isAxisVisible,
14597
+ name: isAxisVisible && opts.showYAxisNames ? getTagName(tag) : "",
14569
14598
  nameLocation: "middle",
14570
- nameGap: 45 + offset,
14599
+ nameGap: 45,
14571
14600
  position,
14572
14601
  offset,
14573
14602
  splitNumber: 8, // Suggest 8 divisions, ECharts will adjust for readability
@@ -14577,21 +14606,24 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14577
14606
  fontWeight: "bold",
14578
14607
  },
14579
14608
  axisLine: {
14580
- show: true,
14609
+ show: isAxisVisible,
14581
14610
  lineStyle: {
14582
14611
  color: tag.Color,
14612
+ width: 2,
14583
14613
  },
14584
14614
  },
14585
14615
  axisTick: {
14586
- show: true,
14616
+ show: isAxisVisible,
14587
14617
  },
14588
14618
  axisLabel: {
14589
- show: true,
14619
+ show: isAxisVisible,
14590
14620
  color: tag.Color,
14591
14621
  fontSize: 10,
14592
14622
  },
14593
14623
  splitLine: {
14594
- show: position === "left" && offset === 0 ? opts.showGridLines : false,
14624
+ show: isAxisVisible && position === "left" && offset === 0
14625
+ ? opts.showGridLines
14626
+ : false,
14595
14627
  lineStyle: {
14596
14628
  color: "#e0e0e0",
14597
14629
  type: "solid",
@@ -14623,7 +14655,7 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14623
14655
  delete baseConfig.scale;
14624
14656
  }
14625
14657
  return baseConfig;
14626
- }, [opts.showGridLines, true, opts.showYAxisNames]);
14658
+ }, [opts.showGridLines, opts.showYAxisNames, getTagName]);
14627
14659
  // Determine if we should use separate grids (analog/digital)
14628
14660
  const useSeparateGrids = !opts.combinedView &&
14629
14661
  processedData.analogTags.length > 0 &&
@@ -14754,21 +14786,8 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14754
14786
  isUserDraggingRef.current = false;
14755
14787
  }, [handleCursor2Change]);
14756
14788
  const chartOptions = useMemo(() => {
14757
- // Calculate dynamic margins based on number of tags to ensure all Y-axes are visible
14758
- // Formula: Each pair of tags (left + right) needs 60px offset
14759
- // Base margin is 60px, then add 60px for each additional pair
14760
- const calculateMargin = (tagCount) => {
14761
- if (tagCount === 0)
14762
- return 60;
14763
- // Number of axes on each side (alternating left/right)
14764
- const axesPerSide = Math.ceil(tagCount / 2);
14765
- // Last axis offset = (axesPerSide - 1) * 60
14766
- // Total margin = last offset + base margin (60px)
14767
- return (axesPerSide - 1) * 60 + 60;
14768
- };
14769
- const analogMargin = calculateMargin(processedData.analogTags.length);
14770
- const digitalMargin = calculateMargin(processedData.digitalTags.length);
14771
- const combinedMargin = calculateMargin(processedData.analogTags.length + processedData.digitalTags.length);
14789
+ const chartLeftMargin = opts.showYAxisNames ? 96 : 72;
14790
+ const chartRightMargin = 32;
14772
14791
  return {
14773
14792
  animation: false,
14774
14793
  backgroundColor: "#fff",
@@ -14777,16 +14796,16 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14777
14796
  ? [
14778
14797
  {
14779
14798
  id: "analog",
14780
- left: `${analogMargin}px`,
14781
- right: `${analogMargin}px`,
14799
+ left: `${chartLeftMargin}px`,
14800
+ right: `${chartRightMargin}px`,
14782
14801
  top: opts.showLegend ? "70px" : "50px", // Increased to prevent cursor circle clipping
14783
14802
  bottom: "55%",
14784
14803
  containLabel: false,
14785
14804
  },
14786
14805
  {
14787
14806
  id: "digital",
14788
- left: `${digitalMargin}px`,
14789
- right: `${digitalMargin}px`,
14807
+ left: `${chartLeftMargin}px`,
14808
+ right: `${chartRightMargin}px`,
14790
14809
  top: "55%",
14791
14810
  bottom: 60,
14792
14811
  containLabel: false,
@@ -14795,8 +14814,8 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
14795
14814
  : [
14796
14815
  {
14797
14816
  id: "combined",
14798
- left: `${combinedMargin}px`,
14799
- right: `${combinedMargin}px`,
14817
+ left: `${chartLeftMargin}px`,
14818
+ right: `${chartRightMargin}px`,
14800
14819
  top: opts.showLegend ? "70px" : "50px", // Increased to prevent cursor circle clipping
14801
14820
  bottom: 60,
14802
14821
  containLabel: false,
@@ -15023,34 +15042,25 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
15023
15042
  yAxis: (() => {
15024
15043
  const yAxisArray = [];
15025
15044
  if (useSeparateGrids) {
15026
- // Separate view with both analog and digital: analog in grid 0, digital in grid 1
15027
- // Add analog axes (grid 0)
15045
+ const activeAnalogTag = getActiveAxisTag(processedData.analogTags);
15046
+ const activeDigitalTag = getActiveAxisTag(processedData.digitalTags);
15028
15047
  processedData.analogTags.forEach((tag, idx) => {
15029
- const position = idx % 2 === 0 ? "left" : "right";
15030
- const offset = Math.floor(idx / 2) * 60;
15031
- yAxisArray.push(buildYAxisConfig(tag, 0, position, offset));
15048
+ yAxisArray.push(buildYAxisConfig(tag, 0, "left", 0, tag === activeAnalogTag));
15032
15049
  });
15033
- // Add digital axes (grid 1)
15034
- processedData.digitalTags.forEach((tag, idx) => {
15035
- const position = idx % 2 === 0 ? "left" : "right";
15036
- const offset = Math.floor(idx / 2) * 60;
15037
- yAxisArray.push(buildYAxisConfig(tag, 1, position, offset));
15050
+ processedData.digitalTags.forEach((tag) => {
15051
+ yAxisArray.push(buildYAxisConfig(tag, 1, "left", 0, tag === activeDigitalTag));
15038
15052
  });
15039
15053
  }
15040
15054
  else {
15041
- // Combined view or only one type: all axes in grid 0
15042
- // Add analog axes
15043
- processedData.analogTags.forEach((tag, idx) => {
15044
- const position = idx % 2 === 0 ? "left" : "right";
15045
- const offset = Math.floor(idx / 2) * 60;
15046
- yAxisArray.push(buildYAxisConfig(tag, 0, position, offset));
15055
+ const activeCombinedTag = getActiveAxisTag([
15056
+ ...processedData.analogTags,
15057
+ ...processedData.digitalTags,
15058
+ ]);
15059
+ processedData.analogTags.forEach((tag) => {
15060
+ yAxisArray.push(buildYAxisConfig(tag, 0, "left", 0, tag === activeCombinedTag));
15047
15061
  });
15048
- // Add digital axes
15049
- processedData.digitalTags.forEach((tag, idx) => {
15050
- const position = idx % 2 === 0 ? "left" : "right";
15051
- const baseOffset = Math.ceil(processedData.analogTags.length / 2) * 60;
15052
- const offset = baseOffset + Math.floor(idx / 2) * 60;
15053
- yAxisArray.push(buildYAxisConfig(tag, 0, position, offset));
15062
+ processedData.digitalTags.forEach((tag) => {
15063
+ yAxisArray.push(buildYAxisConfig(tag, 0, "left", 0, tag === activeCombinedTag));
15054
15064
  });
15055
15065
  }
15056
15066
  // If no axes were created at all, add a default one to prevent errors
@@ -15239,6 +15249,7 @@ const TrendingChartV2 = ({ series = [], customOptions, isLoading = false, onChar
15239
15249
  timeScopeStart,
15240
15250
  timeScopeEnd,
15241
15251
  buildYAxisConfig,
15252
+ getActiveAxisTag,
15242
15253
  zoomState,
15243
15254
  useSeparateGrids,
15244
15255
  ]);
@@ -15609,9 +15620,9 @@ const TrendingsPageV2 = () => {
15609
15620
  steppedLines: true,
15610
15621
  showLegend: false,
15611
15622
  showTooltip: true,
15612
- combinedView: false,
15623
+ combinedView: true,
15613
15624
  showToolbox: true,
15614
- showYAxisNames: true,
15625
+ showYAxisNames: false,
15615
15626
  });
15616
15627
  const [aggregationMode, setAggregationMode] = useState("avg");
15617
15628
  const [error, setError] = useState("");