@sentio/ui-dashboard 0.3.7 → 0.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -4061,6 +4061,29 @@ function timeBefore(time, duration2, asStart = true) {
4061
4061
  return t.subtract(durationValue, TimeUnitShortNames2[duration2.unit]);
4062
4062
  }
4063
4063
  }
4064
+ function fromTimeLike(tl) {
4065
+ if (!tl) {
4066
+ return void 0;
4067
+ }
4068
+ if (tl.relativeTime) {
4069
+ const value = tl.relativeTime.value || 0;
4070
+ return {
4071
+ value: Math.abs(value),
4072
+ unit: tl.relativeTime.unit,
4073
+ sign: value < 0 ? -1 : 1
4074
+ };
4075
+ }
4076
+ return dayjs4.unix(parseInt(tl.absoluteTime || ""));
4077
+ }
4078
+ function toTimeLike(t) {
4079
+ if (dayjs4.isDayjs(t)) {
4080
+ return { absoluteTime: `${t.unix()}` };
4081
+ }
4082
+ const rt = t;
4083
+ return {
4084
+ relativeTime: { unit: rt.unit, value: rt.sign * rt.value, align: rt.align }
4085
+ };
4086
+ }
4064
4087
 
4065
4088
  // src/charts/TimeSeriesChart.tsx
4066
4089
  import {
@@ -7341,6 +7364,375 @@ var ShareDashboardDialog = ({
7341
7364
  }
7342
7365
  );
7343
7366
  };
7367
+
7368
+ // src/dashboard/TimeRangeOverride.tsx
7369
+ import { defaults as defaults9 } from "lodash";
7370
+ import { produce as produce15 } from "immer";
7371
+ import { Switch, TimeRangePicker } from "@sentio/ui-core";
7372
+ import { jsx as jsx44, jsxs as jsxs34 } from "react/jsx-runtime";
7373
+ var defaultConfig8 = {
7374
+ enabled: false
7375
+ };
7376
+ function TimeRangeOverride({
7377
+ config,
7378
+ onChange,
7379
+ globalStartTime,
7380
+ globalEndTime,
7381
+ globalTz,
7382
+ onSetGlobalTimeRange
7383
+ }) {
7384
+ config = defaults9(config || {}, defaultConfig8);
7385
+ const setEnabled = (enabled) => {
7386
+ config && onChange(
7387
+ produce15(config, (draft) => {
7388
+ draft.enabled = enabled;
7389
+ if (enabled) {
7390
+ draft.timeRange = {
7391
+ start: toTimeLike(globalStartTime),
7392
+ end: toTimeLike(globalEndTime),
7393
+ step: draft.timeRange?.step,
7394
+ interval: draft.timeRange?.interval,
7395
+ timezone: draft.timeRange?.timezone
7396
+ };
7397
+ }
7398
+ })
7399
+ );
7400
+ };
7401
+ function onTimeRangeChange(start, end, tz) {
7402
+ if (config?.enabled) {
7403
+ onChange(
7404
+ produce15(config, (draft) => {
7405
+ draft.timeRange = {
7406
+ start: toTimeLike(start),
7407
+ end: toTimeLike(end),
7408
+ timezone: tz,
7409
+ step: draft.timeRange?.step,
7410
+ interval: draft.timeRange?.interval
7411
+ };
7412
+ })
7413
+ );
7414
+ } else {
7415
+ onSetGlobalTimeRange(start, end, tz);
7416
+ }
7417
+ }
7418
+ return /* @__PURE__ */ jsxs34("div", { className: "flex flex-wrap items-center gap-4 p-2", children: [
7419
+ /* @__PURE__ */ jsx44("div", { className: "flex items-center", children: /* @__PURE__ */ jsx44(
7420
+ Switch,
7421
+ {
7422
+ checked: config.enabled || false,
7423
+ onChange: setEnabled,
7424
+ label: "Override Global Time"
7425
+ }
7426
+ ) }),
7427
+ /* @__PURE__ */ jsx44(
7428
+ TimeRangePicker,
7429
+ {
7430
+ startTime: config.enabled ? fromTimeLike(config.timeRange?.start) : globalStartTime,
7431
+ endTime: config.enabled ? fromTimeLike(config.timeRange?.end) : globalEndTime,
7432
+ tz: config.enabled ? config.timeRange?.timezone || globalTz : globalTz,
7433
+ onChange: onTimeRangeChange
7434
+ }
7435
+ )
7436
+ ] });
7437
+ }
7438
+
7439
+ // src/dashboard/SeriesControls.tsx
7440
+ import { useEffect as useEffect13, useRef as useRef8, useState as useState15, useLayoutEffect } from "react";
7441
+ import { Select as Select3, classNames as classNames14 } from "@sentio/ui-core";
7442
+ import { useVirtualizer } from "@tanstack/react-virtual";
7443
+ import { LuChevronRight, LuMountainSnow } from "react-icons/lu";
7444
+ import { cloneDeep } from "lodash";
7445
+ import { Disclosure } from "@headlessui/react";
7446
+ import { jsx as jsx45, jsxs as jsxs35 } from "react/jsx-runtime";
7447
+ var seriesChartTypes = [
7448
+ {
7449
+ value: "default",
7450
+ label: /* @__PURE__ */ jsxs35("div", { className: "flex items-center", children: [
7451
+ /* @__PURE__ */ jsx45(LuMountainSnow, { className: "mr-2 h-4 w-4" }),
7452
+ "Default"
7453
+ ] })
7454
+ },
7455
+ {
7456
+ value: "LINE",
7457
+ label: /* @__PURE__ */ jsxs35("div", { className: "flex items-center", children: [
7458
+ /* @__PURE__ */ jsx45(LineIcon_default, { className: "mr-2 h-4 w-4" }),
7459
+ "Line"
7460
+ ] })
7461
+ },
7462
+ {
7463
+ value: "BAR",
7464
+ label: /* @__PURE__ */ jsxs35("div", { className: "flex items-center", children: [
7465
+ /* @__PURE__ */ jsx45(BarIcon_default, { className: "mr-2 h-4 w-4" }),
7466
+ "Bar"
7467
+ ] })
7468
+ },
7469
+ {
7470
+ value: "AREA",
7471
+ label: /* @__PURE__ */ jsxs35("div", { className: "flex items-center", children: [
7472
+ /* @__PURE__ */ jsx45(AreaIcon_default, { className: "mr-2 h-4 w-4" }),
7473
+ "Area"
7474
+ ] })
7475
+ }
7476
+ ];
7477
+ var SeriesControls = ({
7478
+ config,
7479
+ setSeriesConfig,
7480
+ series,
7481
+ enabled
7482
+ }) => {
7483
+ const parentRef = useRef8(null);
7484
+ const [isDisclosureOpen, setIsDisclosureOpen] = useState15(true);
7485
+ const shouldVirtualize = series.length > 10;
7486
+ const virtualizer = useVirtualizer({
7487
+ count: shouldVirtualize && isDisclosureOpen ? series.length : 0,
7488
+ getScrollElement: () => parentRef.current,
7489
+ estimateSize: () => 40,
7490
+ overscan: 5
7491
+ // Render 5 extra items outside viewport for smooth scrolling
7492
+ });
7493
+ useLayoutEffect(() => {
7494
+ if (isDisclosureOpen && shouldVirtualize && parentRef.current) {
7495
+ const timeoutId = setTimeout(() => {
7496
+ virtualizer.measure();
7497
+ }, 10);
7498
+ return () => clearTimeout(timeoutId);
7499
+ }
7500
+ }, [isDisclosureOpen, shouldVirtualize, virtualizer]);
7501
+ const handleSeriesTypeChange = (seriesName, selectedType) => {
7502
+ const currentSeriesConfig = config?.seriesConfig || { series: {} };
7503
+ if (selectedType === "default") {
7504
+ const newSeriesConfig2 = cloneDeep(currentSeriesConfig);
7505
+ if (newSeriesConfig2.series && newSeriesConfig2.series[seriesName]) {
7506
+ delete newSeriesConfig2.series[seriesName];
7507
+ }
7508
+ setSeriesConfig(newSeriesConfig2);
7509
+ return;
7510
+ }
7511
+ const newSeriesConfig = {
7512
+ ...currentSeriesConfig,
7513
+ series: {
7514
+ ...currentSeriesConfig.series,
7515
+ [seriesName]: { type: selectedType }
7516
+ }
7517
+ };
7518
+ setSeriesConfig(newSeriesConfig);
7519
+ };
7520
+ const handleReset = () => {
7521
+ setSeriesConfig({ series: {} });
7522
+ };
7523
+ const renderSeriesItem = (seriesName) => {
7524
+ const currentType = config?.seriesConfig?.series?.[seriesName]?.type || "default";
7525
+ return /* @__PURE__ */ jsxs35(
7526
+ "div",
7527
+ {
7528
+ className: "text-icontent inline-flex h-8 w-full basis-0 px-2",
7529
+ children: [
7530
+ /* @__PURE__ */ jsx45("div", { className: "sm:text-icontent bg-sentio-gray-100 dark:bg-sentio-gray-200 border-main inline-flex shrink items-center rounded-l-md border border-r-0 px-2 font-medium sm:min-w-[160px]", children: /* @__PURE__ */ jsx45("span", { className: "truncate", title: seriesName, children: seriesName }) }),
7531
+ /* @__PURE__ */ jsx45("span", { className: "sm:text-icontent bg-sentio-gray-100 dark:bg-sentio-gray-200 border-main inline-flex items-center whitespace-nowrap border border-r-0 px-2", children: "Show as" }),
7532
+ /* @__PURE__ */ jsx45("div", { className: "w-40", children: /* @__PURE__ */ jsx45(
7533
+ Select3,
7534
+ {
7535
+ options: seriesChartTypes,
7536
+ value: currentType,
7537
+ onChange: (selectedType) => handleSeriesTypeChange(seriesName, selectedType),
7538
+ className: "focus:border-primary-500 sm:text-icontent border-main h-full rounded-r-md border",
7539
+ buttonClassName: "border-none! h-full!",
7540
+ placeholder: "Select chart type",
7541
+ asLayer: true
7542
+ }
7543
+ ) })
7544
+ ]
7545
+ },
7546
+ seriesName
7547
+ );
7548
+ };
7549
+ if (!enabled) {
7550
+ return null;
7551
+ }
7552
+ const titleWithReset = /* @__PURE__ */ jsxs35("div", { className: "flex w-full items-center justify-between pr-2", children: [
7553
+ /* @__PURE__ */ jsx45("span", { children: `Series (${series.length})` }),
7554
+ /* @__PURE__ */ jsx45(
7555
+ "button",
7556
+ {
7557
+ type: "button",
7558
+ onClick: (e) => {
7559
+ e.stopPropagation();
7560
+ handleReset();
7561
+ },
7562
+ className: "rounded-sm bg-gray-200 px-2 py-1 text-xs transition-colors hover:bg-gray-300",
7563
+ title: "Reset all series to default",
7564
+ children: "Reset"
7565
+ }
7566
+ )
7567
+ ] });
7568
+ return /* @__PURE__ */ jsx45(Disclosure, { defaultOpen: true, children: ({ open }) => {
7569
+ useEffect13(() => {
7570
+ setIsDisclosureOpen(open);
7571
+ }, [open]);
7572
+ return /* @__PURE__ */ jsxs35("div", { className: "bg-default-bg w-full rounded-sm", children: [
7573
+ /* @__PURE__ */ jsxs35(
7574
+ Disclosure.Button,
7575
+ {
7576
+ className: classNames14(
7577
+ open ? "rounded-t" : "rounded-sm",
7578
+ "focus-visible:ring-primary-500/75 text-ilabel font-ilabel text-text-foreground hover:bg-sentio-gray-100 dark:hover:bg-sentio-gray-400 focus:outline-hidden focus-visible:ring-3 flex w-full px-2 py-1.5 text-left"
7579
+ ),
7580
+ children: [
7581
+ /* @__PURE__ */ jsx45(
7582
+ LuChevronRight,
7583
+ {
7584
+ className: classNames14(
7585
+ open ? "rotate-90 transform" : "",
7586
+ "mr-1 h-5 w-5 self-center transition-all"
7587
+ )
7588
+ }
7589
+ ),
7590
+ titleWithReset
7591
+ ]
7592
+ }
7593
+ ),
7594
+ /* @__PURE__ */ jsx45(Disclosure.Panel, { className: "p-2", children: shouldVirtualize && open ? (
7595
+ // Virtualized rendering for large lists - only render when open
7596
+ /* @__PURE__ */ jsx45(
7597
+ "div",
7598
+ {
7599
+ ref: parentRef,
7600
+ className: "text-icontent h-[200px] overflow-auto",
7601
+ style: {
7602
+ contain: "strict"
7603
+ },
7604
+ children: /* @__PURE__ */ jsx45(
7605
+ "div",
7606
+ {
7607
+ style: {
7608
+ height: `${virtualizer?.getTotalSize() ?? 0}px`,
7609
+ width: "100%",
7610
+ position: "relative"
7611
+ },
7612
+ children: virtualizer?.getVirtualItems().map((virtualItem) => {
7613
+ const seriesName = series[virtualItem.index];
7614
+ if (!seriesName) return null;
7615
+ return /* @__PURE__ */ jsx45(
7616
+ "div",
7617
+ {
7618
+ style: {
7619
+ position: "absolute",
7620
+ top: 0,
7621
+ left: 0,
7622
+ width: "100%",
7623
+ height: `${virtualItem.size}px`,
7624
+ transform: `translateY(${virtualItem.start}px)`
7625
+ },
7626
+ children: renderSeriesItem(seriesName)
7627
+ },
7628
+ virtualItem.key
7629
+ );
7630
+ })
7631
+ }
7632
+ )
7633
+ }
7634
+ )
7635
+ ) : (
7636
+ // Normal rendering for small lists
7637
+ /* @__PURE__ */ jsx45("div", { className: "text-icontent flex max-h-[200px] flex-col gap-2 overflow-y-auto", children: series.map((seriesName) => renderSeriesItem(seriesName)) })
7638
+ ) })
7639
+ ] });
7640
+ } });
7641
+ };
7642
+
7643
+ // src/dashboard/QueryValueControls.tsx
7644
+ import { produce as produce16 } from "immer";
7645
+ import { defaults as defaults10 } from "lodash";
7646
+ import { Checkbox as Checkbox7, DisclosurePanel as DisclosurePanel12 } from "@sentio/ui-core";
7647
+ import { jsx as jsx46, jsxs as jsxs36 } from "react/jsx-runtime";
7648
+ var defaultConfig9 = {
7649
+ calculation: "LAST",
7650
+ colorTheme: {
7651
+ themeType: "Gray"
7652
+ },
7653
+ showBackgroundChart: false
7654
+ };
7655
+ var CalculationItems4 = [
7656
+ { label: "Last", value: "LAST" },
7657
+ { label: "First", value: "FIRST" },
7658
+ { label: "Total", value: "TOTAL" },
7659
+ { label: "Mean", value: "MEAN" },
7660
+ { label: "Max", value: "MAX" },
7661
+ { label: "Min", value: "MIN" }
7662
+ ];
7663
+ function QueryValueControls({
7664
+ config,
7665
+ defaultOpen,
7666
+ onChange,
7667
+ renderColorSelect
7668
+ }) {
7669
+ config = defaults10(config, defaultConfig9);
7670
+ function onCalculationChange(cal) {
7671
+ config && onChange(produce16(config, (draft) => void (draft.calculation = cal)));
7672
+ }
7673
+ function onSeriesCalculationChange(cal) {
7674
+ config && onChange(produce16(config, (draft) => void (draft.seriesCalculation = cal)));
7675
+ }
7676
+ function onSelectColor(c) {
7677
+ config && onChange(
7678
+ produce16(config, (draft) => {
7679
+ draft.colorTheme = c.value;
7680
+ })
7681
+ );
7682
+ }
7683
+ function toggleShowBackgroundChart() {
7684
+ config && onChange(
7685
+ produce16(config, (draft) => {
7686
+ draft.showBackgroundChart = !draft.showBackgroundChart;
7687
+ })
7688
+ );
7689
+ }
7690
+ return /* @__PURE__ */ jsx46(
7691
+ DisclosurePanel12,
7692
+ {
7693
+ title: "Query Value Options",
7694
+ defaultOpen,
7695
+ containerClassName: "w-full bg-default-bg",
7696
+ children: /* @__PURE__ */ jsxs36("div", { className: "flex flex-wrap items-center gap-4", children: [
7697
+ /* @__PURE__ */ jsxs36("div", { className: "shadow-xs flex h-8 rounded-md", children: [
7698
+ /* @__PURE__ */ jsx46("span", { className: "sm:text-ilabel border-main text-text-foreground inline-flex items-center whitespace-nowrap rounded-l-md border bg-gray-50 px-3", children: "For each series, calculate the" }),
7699
+ /* @__PURE__ */ jsx46(
7700
+ "select",
7701
+ {
7702
+ value: config?.calculation,
7703
+ className: "sm:text-ilabel border-main text-text-foreground inline-flex items-center border border-x-0 py-0.5 pl-4 pr-7",
7704
+ onChange: (e) => onCalculationChange(e.target.value),
7705
+ children: CalculationItems4.map((d) => /* @__PURE__ */ jsx46("option", { value: d.value, children: d.label }, d.value))
7706
+ }
7707
+ ),
7708
+ /* @__PURE__ */ jsx46("span", { className: "sm:text-ilabel border-main text-text-foreground inline-flex items-center whitespace-nowrap border bg-gray-50 px-3", children: "value, then show the" }),
7709
+ /* @__PURE__ */ jsx46(
7710
+ "select",
7711
+ {
7712
+ value: config?.seriesCalculation,
7713
+ className: "sm:text-ilabel border-main text-text-foreground inline-flex items-center border border-x-0 py-0.5 pl-4 pr-7",
7714
+ onChange: (e) => onSeriesCalculationChange(e.target.value),
7715
+ children: CalculationItems4.map((d) => /* @__PURE__ */ jsx46("option", { value: d.value, children: d.label }, d.value))
7716
+ }
7717
+ ),
7718
+ /* @__PURE__ */ jsx46("span", { className: "sm:text-ilabel border-main text-text-foreground inline-flex items-center whitespace-nowrap rounded-r-md border bg-gray-50 px-3", children: "value of multiple series" })
7719
+ ] }),
7720
+ /* @__PURE__ */ jsxs36("div", { className: "focus-within:ring-primary-500 shadow-xs border-main flex h-8 divide-x divide-gray-300 rounded-md border focus-within:border-transparent focus-within:ring-2", children: [
7721
+ /* @__PURE__ */ jsx46("span", { className: "sm:text-ilabel text-text-foreground inline-flex items-center whitespace-nowrap rounded-l-md bg-gray-50 px-3", children: "Color Theme" }),
7722
+ renderColorSelect(config?.colorTheme, onSelectColor)
7723
+ ] }),
7724
+ /* @__PURE__ */ jsx46(
7725
+ Checkbox7,
7726
+ {
7727
+ checked: config?.showBackgroundChart,
7728
+ onChange: toggleShowBackgroundChart,
7729
+ label: "Show Background Chart"
7730
+ }
7731
+ )
7732
+ ] })
7733
+ }
7734
+ );
7735
+ }
7344
7736
  export {
7345
7737
  AggregateInput,
7346
7738
  AreaIcon_default as AreaIcon,
@@ -7375,6 +7767,7 @@ export {
7375
7767
  PieChartControls,
7376
7768
  PieIcon_default as PieIcon,
7377
7769
  QueryValueChart,
7770
+ QueryValueControls,
7378
7771
  QueryValueIcon_default as QueryValueIcon,
7379
7772
  ReactEChartsBase,
7380
7773
  RefreshButton,
@@ -7382,10 +7775,12 @@ export {
7382
7775
  ScatterChartTooltip,
7383
7776
  ScatterControls,
7384
7777
  ScatterIcon_default as ScatterIcon,
7778
+ SeriesControls,
7385
7779
  ShareDashboardDialog,
7386
7780
  SystemLabels,
7387
7781
  TableControls,
7388
7782
  TableIcon_default as TableIcon,
7783
+ TimeRangeOverride,
7389
7784
  TimeSeriesChart,
7390
7785
  ValueControls,
7391
7786
  ValueFormatters,
@@ -7396,8 +7791,10 @@ export {
7396
7791
  defaultConfig2 as defaultBarGaugeConfig,
7397
7792
  defaultConfig5 as defaultDataConfig,
7398
7793
  defaultConfig as defaultPieConfig,
7794
+ defaultConfig9 as defaultQueryValueConfig,
7399
7795
  defaultConfig6 as defaultScatterConfig,
7400
7796
  defaultConfig7 as defaultTableConfig,
7797
+ defaultConfig8 as defaultTimeRangeOverrideConfig,
7401
7798
  defaultConfig3 as defaultValueConfig,
7402
7799
  defaultConfig4 as defaultValueControlsConfig,
7403
7800
  getDefaultValueConfig,