@localstack/appinspector-ui 1.0.60 → 1.0.62

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.js CHANGED
@@ -58,13 +58,13 @@ var init_is_prop_valid_esm = __esm({
58
58
 
59
59
  // src/pages/spans-list-page.tsx
60
60
  import { Box as Box18 } from "@mui/material";
61
- import { useCallback as useCallback8, useState as useState12 } from "react";
61
+ import { useCallback as useCallback9, useState as useState13 } from "react";
62
62
 
63
63
  // src/components/spans-list/spans-list.tsx
64
64
  import { Alert, Box as Box4, Button as Button2 } from "@mui/material";
65
65
 
66
66
  // src/components/spans-list/spans-data-grid.tsx
67
- import { DeleteForeverOutlined } from "@mui/icons-material";
67
+ import { DeleteForeverOutlined, PauseOutlined, PlayArrowOutlined, SwapVertOutlined } from "@mui/icons-material";
68
68
  import {
69
69
  Box as Box3,
70
70
  Button,
@@ -12145,6 +12145,16 @@ var newSpanBackgroundColor = {
12145
12145
  dark: "#887b02",
12146
12146
  light: "#ffde7b"
12147
12147
  };
12148
+ var LABEL_BEGINNING_OF_STREAM = "This is the beginning of the stream";
12149
+ var LABEL_END_OF_STREAM = "This is the end of the stream";
12150
+ var LABEL_NO_SPANS = "There are no spans";
12151
+ var LABEL_LOAD_OLDER = "Load older spans";
12152
+ var LABEL_LOAD_NEWER = "Load newer spans";
12153
+ var StreamBoundaryRow = ({ colSpan, label }) => /* @__PURE__ */ jsx124(TableRow, { children: /* @__PURE__ */ jsx124(TableCell, { colSpan, sx: { fontStyle: "italic", textAlign: "center" }, children: /* @__PURE__ */ jsx124("span", { children: label }) }) });
12154
+ var LoadSpansRow = ({ colSpan, fetching, label, onFetch }) => /* @__PURE__ */ jsx124(TableRow, { children: /* @__PURE__ */ jsxs120(TableCell, { colSpan, sx: { textAlign: "center" }, children: [
12155
+ !fetching && /* @__PURE__ */ jsx124(Button, { onClick: onFetch, sx: { my: 1 }, children: label }),
12156
+ fetching && /* @__PURE__ */ jsx124(CircularProgress, { size: 24, sx: { m: 2 } })
12157
+ ] }) });
12148
12158
  var SpansDataGridRow = memo8(
12149
12159
  ({ row }) => {
12150
12160
  const theme = useTheme2();
@@ -12200,12 +12210,18 @@ var SpansDataGridRow = memo8(
12200
12210
  var SpansDataGrid = ({
12201
12211
  clearingSpans,
12202
12212
  fetchingBackward,
12213
+ fetchingForward,
12203
12214
  hasMoreBackward,
12204
12215
  hasMoreForward,
12205
12216
  onClearSpans,
12206
12217
  onFetchBackward,
12218
+ onFetchForward,
12219
+ onOrderChange,
12207
12220
  onSpanClick,
12208
- spans
12221
+ onToggleStream,
12222
+ order: order2,
12223
+ spans,
12224
+ streamPaused
12209
12225
  }) => {
12210
12226
  const columns = useMemo5(() => [
12211
12227
  columnHelper.accessor("trace_id", {
@@ -12294,6 +12310,38 @@ var SpansDataGrid = ({
12294
12310
  return /* @__PURE__ */ jsxs120(Fragment3, { children: [
12295
12311
  /* @__PURE__ */ jsx124(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsxs120(Box3, { sx: { alignItems: "center", display: "flex", gap: "0.5rem" }, children: [
12296
12312
  /* @__PURE__ */ jsx124(Box3, { sx: { flexGrow: 1 } }),
12313
+ /* @__PURE__ */ jsx124(
12314
+ FormControlLabel,
12315
+ {
12316
+ control: /* @__PURE__ */ jsx124(
12317
+ Button,
12318
+ {
12319
+ onClick: onToggleStream,
12320
+ startIcon: streamPaused ? /* @__PURE__ */ jsx124(PlayArrowOutlined, {}) : /* @__PURE__ */ jsx124(PauseOutlined, {}),
12321
+ variant: "text",
12322
+ children: streamPaused ? "Resume Stream" : "Pause Stream"
12323
+ }
12324
+ ),
12325
+ label: ""
12326
+ }
12327
+ ),
12328
+ /* @__PURE__ */ jsx124(
12329
+ FormControlLabel,
12330
+ {
12331
+ control: /* @__PURE__ */ jsx124(
12332
+ Button,
12333
+ {
12334
+ onClick: () => {
12335
+ onOrderChange(order2 === "newest_first" ? "oldest_first" : "newest_first");
12336
+ },
12337
+ startIcon: /* @__PURE__ */ jsx124(SwapVertOutlined, {}),
12338
+ variant: "text",
12339
+ children: order2 === "newest_first" ? "Newest First" : "Oldest First"
12340
+ }
12341
+ ),
12342
+ label: ""
12343
+ }
12344
+ ),
12297
12345
  /* @__PURE__ */ jsx124(
12298
12346
  FormControlLabel,
12299
12347
  {
@@ -12351,21 +12399,30 @@ var SpansDataGrid = ({
12351
12399
  }) }),
12352
12400
  /* @__PURE__ */ jsxs120(TableBody, { children: [
12353
12401
  spans === void 0 && /* @__PURE__ */ jsx124(TableRow, { children: /* @__PURE__ */ jsx124(TableCell, { colSpan: columnCount, sx: { fontStyle: "italic", textAlign: "center" }, children: /* @__PURE__ */ jsx124(CircularProgress, { size: 48, sx: { m: 4 } }) }) }),
12354
- spans?.length === 0 && /* @__PURE__ */ jsx124(TableRow, { children: /* @__PURE__ */ jsx124(TableCell, { colSpan: columnCount, sx: { fontStyle: "italic", textAlign: "center" }, children: /* @__PURE__ */ jsx124("span", { children: "There are no spans" }) }) }),
12355
- hasRows && !hasMoreBackward && /* @__PURE__ */ jsx124(TableRow, { children: /* @__PURE__ */ jsx124(TableCell, { colSpan: columnCount, sx: { fontStyle: "italic", textAlign: "center" }, children: /* @__PURE__ */ jsx124("span", { children: "This is the beginning of the stream" }) }) }),
12356
- hasRows && hasMoreBackward && /* @__PURE__ */ jsx124(TableRow, { children: /* @__PURE__ */ jsxs120(TableCell, { colSpan: columnCount, sx: { textAlign: "center" }, children: [
12357
- !fetchingBackward && /* @__PURE__ */ jsx124(
12358
- Button,
12359
- {
12360
- onClick: onFetchBackward,
12361
- sx: { my: 1 },
12362
- children: "Load older spans"
12402
+ spans?.length === 0 && /* @__PURE__ */ jsx124(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_NO_SPANS }),
12403
+ order2 === "newest_first" && /* @__PURE__ */ jsxs120(Fragment3, { children: [
12404
+ hasRows && hasMoreForward && /* @__PURE__ */ jsx124(LoadSpansRow, { colSpan: columnCount, fetching: fetchingForward, label: LABEL_LOAD_NEWER, onFetch: onFetchForward }),
12405
+ hasRows && !hasMoreForward && /* @__PURE__ */ jsx124(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_END_OF_STREAM }),
12406
+ hasRows && /* @__PURE__ */ jsx124(AnimatePresence, { initial: false, children: (() => {
12407
+ const reversed = [];
12408
+ for (let index2 = rows.length - 1; index2 >= 0; index2--) {
12409
+ const row = rows.at(index2);
12410
+ reversed.push(
12411
+ /* @__PURE__ */ jsx124(SpansDataGridRow, { row }, row.original.span_id)
12412
+ );
12363
12413
  }
12364
- ),
12365
- fetchingBackward && /* @__PURE__ */ jsx124(CircularProgress, { size: 24, sx: { m: 2 } })
12366
- ] }) }),
12367
- hasRows && /* @__PURE__ */ jsx124(AnimatePresence, { initial: false, children: rows.map((row) => /* @__PURE__ */ jsx124(SpansDataGridRow, { row }, row.original.span_id)) }),
12368
- hasRows && !hasMoreForward && /* @__PURE__ */ jsx124(TableRow, { children: /* @__PURE__ */ jsx124(TableCell, { colSpan: columnCount, sx: { fontStyle: "italic", textAlign: "center" }, children: /* @__PURE__ */ jsx124("span", { children: "This is the end of the stream" }) }) })
12414
+ return reversed;
12415
+ })() }),
12416
+ hasRows && hasMoreBackward && /* @__PURE__ */ jsx124(LoadSpansRow, { colSpan: columnCount, fetching: fetchingBackward, label: LABEL_LOAD_OLDER, onFetch: onFetchBackward }),
12417
+ hasRows && !hasMoreBackward && /* @__PURE__ */ jsx124(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_BEGINNING_OF_STREAM })
12418
+ ] }),
12419
+ order2 === "oldest_first" && /* @__PURE__ */ jsxs120(Fragment3, { children: [
12420
+ hasRows && !hasMoreBackward && /* @__PURE__ */ jsx124(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_BEGINNING_OF_STREAM }),
12421
+ hasRows && hasMoreBackward && /* @__PURE__ */ jsx124(LoadSpansRow, { colSpan: columnCount, fetching: fetchingBackward, label: LABEL_LOAD_OLDER, onFetch: onFetchBackward }),
12422
+ hasRows && /* @__PURE__ */ jsx124(AnimatePresence, { initial: false, children: rows.map((row) => /* @__PURE__ */ jsx124(SpansDataGridRow, { row }, row.original.span_id)) }),
12423
+ hasRows && hasMoreForward && /* @__PURE__ */ jsx124(LoadSpansRow, { colSpan: columnCount, fetching: fetchingForward, label: LABEL_LOAD_NEWER, onFetch: onFetchForward }),
12424
+ hasRows && !hasMoreForward && /* @__PURE__ */ jsx124(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_END_OF_STREAM })
12425
+ ] })
12369
12426
  ] })
12370
12427
  ]
12371
12428
  }
@@ -12402,9 +12459,12 @@ var SpansList = (props) => {
12402
12459
  onClearSpans: props.onClearSpans,
12403
12460
  onFetchBackward: props.onFetchBackward,
12404
12461
  onFetchForward: props.onFetchForward,
12462
+ onOrderChange: props.onOrderChange,
12405
12463
  onSpanClick: props.onSpanClick,
12406
- refetching: props.refetching,
12407
- spans: props.spans
12464
+ onToggleStream: props.onToggleStream,
12465
+ order: props.order,
12466
+ spans: props.spans,
12467
+ streamPaused: props.streamPaused
12408
12468
  }
12409
12469
  )
12410
12470
  ] });
@@ -12707,8 +12767,53 @@ var StatusMessage = ({
12707
12767
  return /* @__PURE__ */ jsx126(Fragment4, {});
12708
12768
  };
12709
12769
 
12770
+ // src/hooks/use-local-storage.tsx
12771
+ import { useCallback as useCallback3, useEffect as useEffect11, useState as useState4 } from "react";
12772
+ function useLocalStorage(key, initialValue) {
12773
+ const [storedValue, setStoredValue] = useState4(() => {
12774
+ try {
12775
+ const item = globalThis.localStorage.getItem(key);
12776
+ return item ? JSON.parse(item) : initialValue;
12777
+ } catch (error) {
12778
+ console.error(`Error reading localStorage key "${key}":`, error);
12779
+ return initialValue;
12780
+ }
12781
+ });
12782
+ const setValue = useCallback3((value) => {
12783
+ try {
12784
+ setStoredValue((previousState) => {
12785
+ const next = typeof value === "function" ? value(previousState) : value;
12786
+ globalThis.localStorage.setItem(key, JSON.stringify(next));
12787
+ globalThis.dispatchEvent(new StorageEvent("storage", {
12788
+ key,
12789
+ newValue: JSON.stringify(next)
12790
+ }));
12791
+ return next;
12792
+ });
12793
+ } catch (error) {
12794
+ console.error(`Error setting localStorage key "${key}":`, error);
12795
+ }
12796
+ }, [key]);
12797
+ useEffect11(() => {
12798
+ const handleStorageChange = (event) => {
12799
+ if (event.key === key && event.newValue !== null) {
12800
+ try {
12801
+ setStoredValue(JSON.parse(event.newValue));
12802
+ } catch (error) {
12803
+ console.error(`Error parsing localStorage key "${key}":`, error);
12804
+ }
12805
+ }
12806
+ };
12807
+ globalThis.addEventListener("storage", handleStorageChange);
12808
+ return () => {
12809
+ globalThis.removeEventListener("storage", handleStorageChange);
12810
+ };
12811
+ }, [key]);
12812
+ return [storedValue, setValue];
12813
+ }
12814
+
12710
12815
  // src/hooks/use-spans.ts
12711
- import { useCallback as useCallback6, useEffect as useEffect13, useRef as useRef10, useState as useState6 } from "react";
12816
+ import { useCallback as useCallback7, useEffect as useEffect14, useRef as useRef10, useState as useState7 } from "react";
12712
12817
 
12713
12818
  // src/api/use-api.tsx
12714
12819
  import { createContext as createContext7, useContext as useContext14 } from "react";
@@ -12726,15 +12831,15 @@ var useAppInspectorApi = () => {
12726
12831
  };
12727
12832
 
12728
12833
  // src/hooks/use-status.tsx
12729
- import { useCallback as useCallback3, useEffect as useEffect11, useRef as useRef8, useState as useState4 } from "react";
12834
+ import { useCallback as useCallback4, useEffect as useEffect12, useRef as useRef8, useState as useState5 } from "react";
12730
12835
  var useStatus = () => {
12731
12836
  const api = useAppInspectorApi();
12732
- const [checking, setChecking] = useState4(true);
12733
- const [status, setStatus] = useState4();
12734
- const [error, setError] = useState4();
12837
+ const [checking, setChecking] = useState5(true);
12838
+ const [status, setStatus] = useState5();
12839
+ const [error, setError] = useState5();
12735
12840
  const hasFetchedReference = useRef8(false);
12736
12841
  const abortControllerReference = useRef8(null);
12737
- const checkStatus = useCallback3(async () => {
12842
+ const checkStatus = useCallback4(async () => {
12738
12843
  if (abortControllerReference.current !== null) {
12739
12844
  abortControllerReference.current.abort();
12740
12845
  }
@@ -12758,7 +12863,7 @@ var useStatus = () => {
12758
12863
  }
12759
12864
  }
12760
12865
  }, [api]);
12761
- useEffect11(() => {
12866
+ useEffect12(() => {
12762
12867
  if (!hasFetchedReference.current) {
12763
12868
  hasFetchedReference.current = true;
12764
12869
  void checkStatus();
@@ -12809,7 +12914,6 @@ var createPaginationBuffer = (options) => {
12809
12914
  let hasMoreBackward = void 0;
12810
12915
  let fetchingForward = false;
12811
12916
  let fetchingBackward = false;
12812
- const refetching = false;
12813
12917
  const reportDataChange = () => {
12814
12918
  options.onDataChange({
12815
12919
  hasMoreBackward: hasMoreBackward ?? false,
@@ -12820,8 +12924,7 @@ var createPaginationBuffer = (options) => {
12820
12924
  const reportStatusChange = () => {
12821
12925
  options.onStatusChange?.({
12822
12926
  fetchingBackward,
12823
- fetchingForward,
12824
- refetching
12927
+ fetchingForward
12825
12928
  });
12826
12929
  };
12827
12930
  const reportError = (error) => {
@@ -12829,6 +12932,25 @@ var createPaginationBuffer = (options) => {
12829
12932
  };
12830
12933
  let fetchForwardLater = false;
12831
12934
  let fetchBackwardLater = false;
12935
+ let fetchForwardSilentlyLater = false;
12936
+ const checkIfThereAreMoreItemsForward = async () => {
12937
+ if (hasMoreForward === true) {
12938
+ return;
12939
+ }
12940
+ fetchingForward = true;
12941
+ reportStatusChange();
12942
+ try {
12943
+ const newPage = await fetchPage(nextForwardToken);
12944
+ hasMoreForward = newPage.items.length > 0;
12945
+ reportDataChange();
12946
+ } catch (error) {
12947
+ reportError(error instanceof Error ? error : new Error("Failed to fetch forward page", { cause: error }));
12948
+ } finally {
12949
+ fetchingForward = false;
12950
+ reportStatusChange();
12951
+ }
12952
+ runPostFetchActions();
12953
+ };
12832
12954
  const fetchForward = async () => {
12833
12955
  fetchingForward = true;
12834
12956
  reportStatusChange();
@@ -12892,8 +13014,19 @@ var createPaginationBuffer = (options) => {
12892
13014
  fetchForwardLater = false;
12893
13015
  void fetchForward();
12894
13016
  }
13017
+ if (fetchForwardSilentlyLater) {
13018
+ fetchForwardSilentlyLater = false;
13019
+ void checkIfThereAreMoreItemsForward();
13020
+ }
12895
13021
  };
12896
13022
  return {
13023
+ checkIfThereAreMoreItemsForward: () => {
13024
+ if (fetchingForward || fetchingBackward) {
13025
+ fetchForwardSilentlyLater = true;
13026
+ return;
13027
+ }
13028
+ void checkIfThereAreMoreItemsForward();
13029
+ },
12897
13030
  clear: () => {
12898
13031
  if (items !== void 0) {
12899
13032
  items.length = 0;
@@ -12916,11 +13049,11 @@ var createPaginationBuffer = (options) => {
12916
13049
  };
12917
13050
 
12918
13051
  // src/hooks/use-spans-ws.tsx
12919
- import { useCallback as useCallback5, useEffect as useEffect12, useRef as useRef9, useState as useState5 } from "react";
13052
+ import { useCallback as useCallback6, useEffect as useEffect13, useRef as useRef9, useState as useState6 } from "react";
12920
13053
 
12921
13054
  // src/context.tsx
12922
13055
  import { createContext as createContext8, useContext as useContext15 } from "react";
12923
- import { useCallback as useCallback4, useMemo as useMemo6 } from "react";
13056
+ import { useCallback as useCallback5, useMemo as useMemo6 } from "react";
12924
13057
 
12925
13058
  // src/utils/time.ts
12926
13059
  function unixNanoToDate(unixNanoString) {
@@ -13125,7 +13258,7 @@ var AppInspectorContextProvider = (props) => {
13125
13258
  const api = useMemo6(() => {
13126
13259
  return false ? createApiClientMock() : createApiClient({ localstackEndpoint: props.localstackEndpoint });
13127
13260
  }, [props.localstackEndpoint]);
13128
- const resolveLink = useCallback4(
13261
+ const resolveLink = useCallback5(
13129
13262
  (options) => {
13130
13263
  if (options.to === "settings") {
13131
13264
  return `${props.routePrefix}/settings`;
@@ -13152,14 +13285,14 @@ var AppInspectorContextProvider = (props) => {
13152
13285
  function useSpansWebSocket(options) {
13153
13286
  const { onMessage } = options;
13154
13287
  const onMessageRef = useRef9(onMessage);
13155
- useEffect12(() => {
13288
+ useEffect13(() => {
13156
13289
  onMessageRef.current = onMessage;
13157
13290
  }, [onMessage]);
13158
- const [connected, setConnected] = useState5(false);
13291
+ const [connected, setConnected] = useState6(false);
13159
13292
  const wsRef = useRef9(void 0);
13160
13293
  const reconnectRef = useRef9(void 0);
13161
13294
  const { localstackEndpoint } = useAppInspector();
13162
- const connect = useCallback5(() => {
13295
+ const connect = useCallback6(() => {
13163
13296
  if (wsRef.current !== void 0) return;
13164
13297
  const url = new URL(getAppInspectorApiUrl(localstackEndpoint, API_ENDPOINTS.WEBSOCKET_SPANS));
13165
13298
  url.protocol = globalThis.location.protocol === "https:" ? "wss" : "ws";
@@ -13185,7 +13318,7 @@ function useSpansWebSocket(options) {
13185
13318
  }
13186
13319
  });
13187
13320
  }, [localstackEndpoint]);
13188
- useEffect12(() => {
13321
+ useEffect13(() => {
13189
13322
  connect();
13190
13323
  return () => {
13191
13324
  if (reconnectRef.current !== void 0) clearTimeout(reconnectRef.current);
@@ -13205,11 +13338,10 @@ function useSpansWebSocket(options) {
13205
13338
  var PAGE_SIZE = 30;
13206
13339
  var useSpans = () => {
13207
13340
  const api = useAppInspectorApi();
13208
- const [spans, setSpans] = useState6();
13209
- const [fetchError, setFetchError] = useState6();
13210
- const [fetchingForward, setFetchingForward] = useState6(false);
13211
- const [fetchingBackward, setFetchingBackward] = useState6(false);
13212
- const [refetching, setRefetching] = useState6(false);
13341
+ const [spans, setSpans] = useState7();
13342
+ const [fetchError, setFetchError] = useState7();
13343
+ const [fetchingForward, setFetchingForward] = useState7(false);
13344
+ const [fetchingBackward, setFetchingBackward] = useState7(false);
13213
13345
  const paginationBuffer = useRef10(createPaginationBuffer({
13214
13346
  async fetchPage(token) {
13215
13347
  const response = await api.getSpans({
@@ -13236,7 +13368,6 @@ var useSpans = () => {
13236
13368
  onStatusChange(status2) {
13237
13369
  setFetchingBackward(status2.fetchingBackward);
13238
13370
  setFetchingForward(status2.fetchingForward);
13239
- setRefetching(status2.refetching);
13240
13371
  },
13241
13372
  // The spans endpoint is sorted by span ingestion time, which might differ from
13242
13373
  // the span timestamp. In order to accomodate for this, we will sort the spans
@@ -13245,20 +13376,20 @@ var useSpans = () => {
13245
13376
  return a2.start_time_unix_nano < b2.start_time_unix_nano ? -1 : 1;
13246
13377
  }
13247
13378
  }));
13248
- const [hasMoreBackward, setHasMoreBackward] = useState6();
13249
- const [hasMoreForward, setHasMoreForward] = useState6();
13250
- const fetchForward = useCallback6(() => {
13379
+ const [hasMoreBackward, setHasMoreBackward] = useState7();
13380
+ const [hasMoreForward, setHasMoreForward] = useState7();
13381
+ const fetchForward = useCallback7(() => {
13251
13382
  paginationBuffer.current.fetchForward();
13252
13383
  }, []);
13253
- const fetchBackward = useCallback6(() => {
13384
+ const fetchBackward = useCallback7(() => {
13254
13385
  paginationBuffer.current.fetchBackward();
13255
13386
  }, []);
13256
- useEffect13(() => {
13387
+ useEffect14(() => {
13257
13388
  fetchForward();
13258
13389
  }, [fetchForward]);
13259
13390
  const { checkStatus, error: statusError, status } = useStatus();
13260
- const [clearingSpans, setClearingSpans] = useState6(false);
13261
- const clearSpans = useCallback6(async () => {
13391
+ const [clearingSpans, setClearingSpans] = useState7(false);
13392
+ const clearSpans = useCallback7(async () => {
13262
13393
  setClearingSpans(true);
13263
13394
  try {
13264
13395
  await api.deleteSpans();
@@ -13270,9 +13401,19 @@ var useSpans = () => {
13270
13401
  setClearingSpans(false);
13271
13402
  }
13272
13403
  }, [paginationBuffer, api]);
13404
+ const [streamPaused, setStreamPaused] = useState7(false);
13405
+ const toggleStream = useCallback7(() => {
13406
+ setStreamPaused((previous) => !previous);
13407
+ }, []);
13273
13408
  useSpansWebSocket({
13274
13409
  onMessage: () => {
13275
- paginationBuffer.current.fetchForward();
13410
+ if (!hasMoreForward) {
13411
+ if (streamPaused) {
13412
+ paginationBuffer.current.checkIfThereAreMoreItemsForward();
13413
+ } else {
13414
+ paginationBuffer.current.fetchForward();
13415
+ }
13416
+ }
13276
13417
  }
13277
13418
  });
13278
13419
  return {
@@ -13286,10 +13427,11 @@ var useSpans = () => {
13286
13427
  fetchingForward,
13287
13428
  hasMoreBackward,
13288
13429
  hasMoreForward,
13289
- refetching,
13290
13430
  spans,
13291
13431
  status,
13292
- statusError
13432
+ statusError,
13433
+ streamPaused,
13434
+ toggleStream
13293
13435
  };
13294
13436
  };
13295
13437
 
@@ -13298,7 +13440,7 @@ import { ArrowBack } from "@mui/icons-material";
13298
13440
  import { Box as Box17, Button as Button5, Drawer, Paper as Paper2 } from "@mui/material";
13299
13441
  import { styled } from "@mui/material/styles";
13300
13442
  import { ReactFlowProvider } from "@xyflow/react";
13301
- import { useCallback as useCallback7, useEffect as useEffect16, useRef as useRef12, useState as useState11 } from "react";
13443
+ import { useCallback as useCallback8, useEffect as useEffect17, useRef as useRef12, useState as useState12 } from "react";
13302
13444
 
13303
13445
  // src/components/event-details/event-details.tsx
13304
13446
  import { Box as Box13, Chip as Chip3, Divider as Divider2, Stack, Typography as Typography9 } from "@mui/material";
@@ -13536,7 +13678,7 @@ import { Box as Box12 } from "@mui/material";
13536
13678
  // src/components/event-details/event-detail.tsx
13537
13679
  import { KeyboardArrowDown as KeyboardArrowDown2, KeyboardArrowRight as KeyboardArrowRight2 } from "@mui/icons-material";
13538
13680
  import { Box as Box10, Grid as Grid3, IconButton as IconButton3, Typography as Typography7 } from "@mui/material";
13539
- import { useEffect as useEffect14, useMemo as useMemo8, useRef as useRef11, useState as useState8 } from "react";
13681
+ import { useEffect as useEffect15, useMemo as useMemo8, useRef as useRef11, useState as useState9 } from "react";
13540
13682
 
13541
13683
  // src/components/status-icon.tsx
13542
13684
  import { Cancel, CheckCircle, Error as Error2, Info, RemoveCircle } from "@mui/icons-material";
@@ -13687,7 +13829,7 @@ var IAMEventDetail = ({ event }) => {
13687
13829
  // src/components/event-details/iam-permission-detail.tsx
13688
13830
  import { KeyboardArrowDown, KeyboardArrowRight } from "@mui/icons-material";
13689
13831
  import { Box as Box9, Chip as Chip2, IconButton as IconButton2, Typography as Typography6 } from "@mui/material";
13690
- import { useMemo as useMemo7, useState as useState7 } from "react";
13832
+ import { useMemo as useMemo7, useState as useState8 } from "react";
13691
13833
  import { jsx as jsx132, jsxs as jsxs125 } from "react/jsx-runtime";
13692
13834
  var getChipColors = (status) => {
13693
13835
  const isAllowed = status === "explicitly_allowed" || status === "implicitly_allowed";
@@ -13697,7 +13839,7 @@ var getChipColors = (status) => {
13697
13839
  };
13698
13840
  };
13699
13841
  var IAMPermissionItem = ({ event }) => {
13700
- const [isOpen, setIsOpen] = useState7(false);
13842
+ const [isOpen, setIsOpen] = useState8(false);
13701
13843
  const parsedData = useMemo7(() => {
13702
13844
  const payloadString = event.attributes?.payload;
13703
13845
  if (!payloadString) {
@@ -13768,15 +13910,15 @@ var DetailRow2 = ({ content, label }) => /* @__PURE__ */ jsxs126(Grid3, { contai
13768
13910
  ) : content })
13769
13911
  ] });
13770
13912
  var EventMessage = ({ event }) => {
13771
- const [isOpen, setIsOpen] = useState8(false);
13772
- const [isOverflowing, setIsOverflowing] = useState8(false);
13913
+ const [isOpen, setIsOpen] = useState9(false);
13914
+ const [isOverflowing, setIsOverflowing] = useState9(false);
13773
13915
  const textReference = useRef11(null);
13774
13916
  const parsedMessage = useMemo8(() => parseEventMessage(event), [event]);
13775
13917
  const isIAMPolicyEvent = useMemo8(
13776
13918
  () => event.event_type === "iam.policy_evaluation" && event.attributes?.payload && typeof event.attributes.payload === "string",
13777
13919
  [event]
13778
13920
  );
13779
- useEffect14(() => {
13921
+ useEffect15(() => {
13780
13922
  const checkOverflow = () => {
13781
13923
  const element = textReference.current;
13782
13924
  if (element) {
@@ -13935,10 +14077,10 @@ var EventDetail = ({
13935
14077
  // src/components/event-details/toggle-section.tsx
13936
14078
  import { KeyboardArrowDown as KeyboardArrowDown3, KeyboardArrowRight as KeyboardArrowRight3 } from "@mui/icons-material";
13937
14079
  import { Box as Box11, Typography as Typography8 } from "@mui/material";
13938
- import { useState as useState9 } from "react";
14080
+ import { useState as useState10 } from "react";
13939
14081
  import { jsx as jsx134, jsxs as jsxs127 } from "react/jsx-runtime";
13940
14082
  var ToggleSection = ({ children, headline, initialOpen = true }) => {
13941
- const [isOpen, setIsOpen] = useState9(initialOpen);
14083
+ const [isOpen, setIsOpen] = useState10(initialOpen);
13942
14084
  return /* @__PURE__ */ jsxs127(Box11, { sx: { mt: 4 }, children: [
13943
14085
  /* @__PURE__ */ jsx134(
13944
14086
  Box11,
@@ -14138,7 +14280,7 @@ function renderKeyValue(key, value) {
14138
14280
  import "@xyflow/react/dist/base.css";
14139
14281
  import { Alert as Alert3, Button as Button4, useTheme as useTheme3 } from "@mui/material";
14140
14282
  import { Background, ReactFlow, useNodesState } from "@xyflow/react";
14141
- import { useEffect as useEffect15, useState as useState10 } from "react";
14283
+ import { useEffect as useEffect16, useState as useState11 } from "react";
14142
14284
 
14143
14285
  // src/components/trace-graph/service-node.tsx
14144
14286
  import { Box as Box15, Stack as Stack2, Typography as Typography10 } from "@mui/material";
@@ -14489,8 +14631,8 @@ var TraceGraph = ({
14489
14631
  spans
14490
14632
  }) => {
14491
14633
  const [nodes, setNodes, onNodesChange] = useNodesState([]);
14492
- const [edges, setEdges] = useState10([]);
14493
- useEffect15(() => {
14634
+ const [edges, setEdges] = useState11([]);
14635
+ useEffect16(() => {
14494
14636
  const spansMap = /* @__PURE__ */ new Map();
14495
14637
  const rootSpans = [];
14496
14638
  for (const span of spans.data ?? []) {
@@ -14734,10 +14876,10 @@ async function fetchConnectedTraces(api, traceIds, allSpans = /* @__PURE__ */ ne
14734
14876
  }
14735
14877
  var TraceGraphPage = ({ onClose, spanId, traceId }) => {
14736
14878
  const api = useAppInspectorApi();
14737
- const [spans, setSpans] = useState11();
14738
- const [loading, setLoading] = useState11(false);
14739
- const [fetchError, setFetchError] = useState11();
14740
- const fetchSpans = useCallback7(async () => {
14879
+ const [spans, setSpans] = useState12();
14880
+ const [loading, setLoading] = useState12(false);
14881
+ const [fetchError, setFetchError] = useState12();
14882
+ const fetchSpans = useCallback8(async () => {
14741
14883
  setLoading(true);
14742
14884
  try {
14743
14885
  const spans2 = await fetchConnectedTraces(api, [traceId]);
@@ -14750,28 +14892,28 @@ var TraceGraphPage = ({ onClose, spanId, traceId }) => {
14750
14892
  setLoading(false);
14751
14893
  }
14752
14894
  }, [api, traceId]);
14753
- useEffect16(() => {
14895
+ useEffect17(() => {
14754
14896
  void fetchSpans();
14755
14897
  }, [fetchSpans]);
14756
- const [open, setOpen] = useState11(true);
14757
- const [selectedEvent, setSelectedEvent] = useState11(() => spans?.find((span) => span.span_id === spanId));
14898
+ const [open, setOpen] = useState12(true);
14899
+ const [selectedEvent, setSelectedEvent] = useState12(() => spans?.find((span) => span.span_id === spanId));
14758
14900
  const spansReference = useRef12();
14759
- useEffect16(() => {
14901
+ useEffect17(() => {
14760
14902
  if (!spansReference.current && spans) {
14761
14903
  setSelectedEvent(spans.find((span) => span.span_id === spanId));
14762
14904
  spansReference.current = spans;
14763
14905
  }
14764
14906
  }, [spans, setSelectedEvent, spanId]);
14765
14907
  const { checkStatus, error: statusError, status } = useStatus();
14766
- const handleEventSelect = useCallback7((spanId2) => {
14908
+ const handleEventSelect = useCallback8((spanId2) => {
14767
14909
  const span = spans?.find((s) => s.span_id === spanId2);
14768
14910
  setSelectedEvent(span);
14769
14911
  setOpen(true);
14770
14912
  }, [spans]);
14771
- const handleRetry = useCallback7(() => {
14913
+ const handleRetry = useCallback8(() => {
14772
14914
  void checkStatus();
14773
14915
  }, [checkStatus]);
14774
- const navigateToSpansList = useCallback7(() => {
14916
+ const navigateToSpansList = useCallback8(() => {
14775
14917
  onClose?.();
14776
14918
  }, [onClose]);
14777
14919
  return /* @__PURE__ */ jsx141(
@@ -14811,21 +14953,23 @@ var SpansListPage = () => {
14811
14953
  fetchingForward,
14812
14954
  hasMoreBackward,
14813
14955
  hasMoreForward,
14814
- refetching,
14815
14956
  spans,
14816
14957
  status,
14817
- statusError
14958
+ statusError,
14959
+ streamPaused,
14960
+ toggleStream
14818
14961
  } = useSpans();
14819
- const clearSpansSync = useCallback8(() => {
14962
+ const clearSpansSync = useCallback9(() => {
14820
14963
  void clearSpans();
14821
14964
  }, [clearSpans]);
14822
- const [selectedTraceId, setSelectedTraceId] = useState12();
14823
- const [selectedSpanId, setSelectedSpanId] = useState12();
14824
- const navigateToSpan = useCallback8((span) => {
14965
+ const [order2, setOrder] = useLocalStorage("spans-order", "oldest_first");
14966
+ const [selectedTraceId, setSelectedTraceId] = useState13();
14967
+ const [selectedSpanId, setSelectedSpanId] = useState13();
14968
+ const navigateToSpan = useCallback9((span) => {
14825
14969
  setSelectedTraceId(span.trace_id);
14826
14970
  setSelectedSpanId(span.span_id);
14827
14971
  }, []);
14828
- const handleRetry = useCallback8(() => {
14972
+ const handleRetry = useCallback9(() => {
14829
14973
  void checkStatus();
14830
14974
  }, [checkStatus]);
14831
14975
  const shouldShowStatusMessage = Boolean(statusError) || status?.status === "DISABLED";
@@ -14864,9 +15008,12 @@ var SpansListPage = () => {
14864
15008
  onClearSpans: clearSpansSync,
14865
15009
  onFetchBackward: fetchBackward,
14866
15010
  onFetchForward: fetchForward,
15011
+ onOrderChange: setOrder,
14867
15012
  onSpanClick: navigateToSpan,
14868
- refetching,
14869
- spans
15013
+ onToggleStream: toggleStream,
15014
+ order: order2,
15015
+ spans,
15016
+ streamPaused
14870
15017
  }
14871
15018
  )
14872
15019
  }