@datawheel/data-explorer 0.2.3 → 0.2.5

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.
Files changed (2) hide show
  1. package/dist/main.js +219 -178
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -1,7 +1,7 @@
1
- import { keyframes, createStyles, Select, rem, Flex, Title, Text, Group, Button, Box, Anchor, Input, Stack, SimpleGrid, ScrollArea, Table, MultiSelect, Center, Alert, Loader, Modal, NumberInput, Menu, ActionIcon, useMantineTheme, MantineProvider, Paper, useComponentDefaultProps, Switch, ThemeIcon, Tooltip, Tabs, CloseButton, Drawer, Checkbox, UnstyledButton, TextInput, Accordion, Popover, Divider } from '@mantine/core';
1
+ import { keyframes, createStyles, Select, rem, Flex, Title, Text, Group, Button, Box, Anchor, Input, Stack, SimpleGrid, ScrollArea, LoadingOverlay, Table, MultiSelect, Center, Alert, Loader, Modal, NumberInput, Menu, ActionIcon, MantineProvider, Paper, useComponentDefaultProps, Switch, ThemeIcon, Tooltip, useMantineTheme, Tabs, CloseButton, Drawer, Checkbox, UnstyledButton, TextInput, Accordion, Popover, Divider } from '@mantine/core';
2
2
  import { useClipboard, useClickOutside, useFullscreen, useMediaQuery, useDebouncedValue, useDisclosure } from '@mantine/hooks';
3
3
  import { Prism } from '@mantine/prism';
4
- import { IconWorld, IconExternalLink, IconClipboard, IconAlertCircle, IconAlertTriangle, IconSettings, IconMathGreater, IconMathLower, IconArrowsLeftRight, IconCopy, IconDownload, IconDotsVertical, IconArrowsMinimize, IconArrowsMaximize, IconInfoCircleFilled, IconTrash, IconSearch, IconPhotoDown, IconVectorTriangle, IconStack3, IconFilterOff, IconFilter, IconArrowsSort, IconSortDescendingNumbers, IconSortDescendingLetters, IconSortAscendingNumbers, IconSortAscendingLetters, IconLanguage } from '@tabler/icons-react';
4
+ import { IconWorld, IconExternalLink, IconClipboard, IconAlertCircle, IconAlertTriangle, IconSettings, IconMathGreater, IconMathLower, IconArrowsLeftRight, IconCopy, IconDownload, IconDotsVertical, IconArrowsMinimize, IconArrowsMaximize, IconInfoCircleFilled, IconTrash, IconSearch, IconPhotoDown, IconVectorTriangle, IconPlus, IconStack3, IconFilterOff, IconFilter, IconArrowsSort, IconSortDescendingNumbers, IconSortDescendingLetters, IconSortAscendingNumbers, IconSortAscendingLetters, IconLanguage } from '@tabler/icons-react';
5
5
  import * as React10 from 'react';
6
6
  import React10__default, { createContext, forwardRef, useMemo, useCallback, useContext, useState, useEffect, useRef, Suspense, useLayoutEffect } from 'react';
7
7
  import { translationFactory } from '@datawheel/use-translation';
@@ -228,7 +228,7 @@ var defaultTranslation = {
228
228
  json: "JSON",
229
229
  jsonarrays: "JSON Arrays",
230
230
  jsonrecords: "JSON Records",
231
- xls: "XLS"
231
+ xlsx: "XLSX"
232
232
  },
233
233
  loading: {
234
234
  title: "Loading...",
@@ -803,6 +803,9 @@ var serverSlice = createSlice({
803
803
  updateServer(state, action) {
804
804
  return { ...state, ...action.payload };
805
805
  },
806
+ resetServer(state, action) {
807
+ return { ...initialState };
808
+ },
806
809
  /**
807
810
  * Updates the type of endpoint to use in the current query.
808
811
  */
@@ -827,16 +830,18 @@ var selectServerSoftware = createSelector(selectServerState, (server) => server.
827
830
  var selectServerEndpoint = createSelector(selectServerState, (server) => server.endpoint);
828
831
  var selectServerFormatsEnabled = createSelector(
829
832
  selectServerSoftware,
830
- (software) => software === TesseractDataSource.softwareName ? [Format.csv, Format.jsonarrays, Format.jsonrecords] : [Format.csv, Format.json, Format.jsonrecords, Format.xls]
833
+ (software) => software === TesseractDataSource.softwareName ? [Format.csv, Format.jsonarrays, Format.jsonrecords] : [
834
+ Format.csv,
835
+ // Format.jsonarrays,
836
+ Format.jsonrecords,
837
+ Format.xlsx
838
+ ]
831
839
  );
832
840
  createSelector(
833
841
  selectServerSoftware,
834
842
  (software) => software === TesseractDataSource.softwareName ? ["debug", "exclude_default_members", "parents", "sparse"] : ["debug", "distinct", "nonempty", "parents", "sparse"]
835
843
  );
836
- var selectOlapCubeMap = createSelector(
837
- selectServerState,
838
- (server) => server.cubeMap
839
- );
844
+ var selectOlapCubeMap = createSelector(selectServerState, (server) => server.cubeMap);
840
845
  createSelector(selectOlapCubeMap, getKeys);
841
846
  var selectOlapCubeItems = createSelector(selectOlapCubeMap, getValues);
842
847
 
@@ -913,8 +918,8 @@ var queriesSlice = createSlice({
913
918
  delete query.params.drilldowns[action.payload];
914
919
  },
915
920
  /**
916
- * Remove a single DrilldownItem from the current QueryItem.
917
- */
921
+ * Remove a single DrilldownItem from the current QueryItem.
922
+ */
918
923
  removeMeasure(state, action) {
919
924
  const query = taintCurrentQuery(state);
920
925
  delete query.params.measures[action.payload];
@@ -1002,14 +1007,14 @@ var queriesSlice = createSlice({
1002
1007
  */
1003
1008
  updateCut(state, { payload }) {
1004
1009
  const query = taintCurrentQuery(state);
1005
- query.params.cuts[payload.fullName] = payload;
1010
+ query.params.cuts[payload.key] = payload;
1006
1011
  },
1007
1012
  /**
1008
1013
  * Replaces a single DrilldownItem in the current QueryItem.
1009
1014
  */
1010
1015
  updateDrilldown(state, { payload }) {
1011
1016
  const query = taintCurrentQuery(state);
1012
- query.params.drilldowns[payload.fullName] = payload;
1017
+ query.params.drilldowns[payload.key] = payload;
1013
1018
  },
1014
1019
  /**
1015
1020
  * Replaces a single FilterItem in the current QueryItem.
@@ -1083,10 +1088,7 @@ var selectCurrentQueryParams = createSelector(
1083
1088
  selectCurrentQueryItem,
1084
1089
  (query) => query.params
1085
1090
  );
1086
- var selectCubeName = createSelector(
1087
- selectCurrentQueryParams,
1088
- (params) => params.cube
1089
- );
1091
+ var selectCubeName = createSelector(selectCurrentQueryParams, (params) => params.cube);
1090
1092
  var selectLocale = createSelector(
1091
1093
  [selectCurrentQueryParams, selectServerState],
1092
1094
  (params, server) => {
@@ -1098,10 +1100,7 @@ var selectLocale = createSelector(
1098
1100
  };
1099
1101
  }
1100
1102
  );
1101
- var selectCutMap = createSelector(
1102
- selectCurrentQueryParams,
1103
- (params) => params.cuts
1104
- );
1103
+ var selectCutMap = createSelector(selectCurrentQueryParams, (params) => params.cuts);
1105
1104
  createSelector(selectCutMap, getKeys);
1106
1105
  var selectCutItems = createSelector(selectCutMap, getValues);
1107
1106
  var selectDrilldownMap = createSelector(
@@ -1110,34 +1109,25 @@ var selectDrilldownMap = createSelector(
1110
1109
  );
1111
1110
  createSelector(selectDrilldownMap, getKeys);
1112
1111
  var selectDrilldownItems = createSelector(selectDrilldownMap, getValues);
1113
- var selectFilterMap = createSelector(
1114
- selectCurrentQueryParams,
1115
- (params) => params.filters
1116
- );
1112
+ var selectFilterMap = createSelector(selectCurrentQueryParams, (params) => params.filters);
1117
1113
  createSelector(selectFilterMap, getKeys);
1118
1114
  var selectFilterItems = createSelector(selectFilterMap, getValues);
1119
- var selectMeasureMap = createSelector(
1120
- selectCurrentQueryParams,
1121
- (params) => params.measures
1122
- );
1115
+ var selectMeasureMap = createSelector(selectCurrentQueryParams, (params) => params.measures);
1123
1116
  createSelector(selectMeasureMap, getKeys);
1124
1117
  var selectMeasureItems = createSelector(selectMeasureMap, getValues);
1125
- createSelector(
1126
- selectCurrentQueryParams,
1127
- (params) => params.booleans
1128
- );
1118
+ createSelector(selectCurrentQueryParams, (params) => params.booleans);
1129
1119
  var selectIsPreviewMode = createSelector(
1130
1120
  selectCurrentQueryParams,
1131
1121
  (params) => params.isPreview
1132
1122
  );
1133
- var selectPaginationParams = createSelector(
1134
- selectCurrentQueryParams,
1135
- (params) => ({ limit: params.pagiLimit || 0, offset: params.pagiOffset || 0 })
1136
- );
1137
- createSelector(
1138
- selectCurrentQueryParams,
1139
- (params) => ({ sortKey: params.sortKey || "", sortDir: params.sortDir })
1140
- );
1123
+ var selectPaginationParams = createSelector(selectCurrentQueryParams, (params) => ({
1124
+ limit: params.pagiLimit || 0,
1125
+ offset: params.pagiOffset || 0
1126
+ }));
1127
+ createSelector(selectCurrentQueryParams, (params) => ({
1128
+ sortKey: params.sortKey || "",
1129
+ sortDir: params.sortDir
1130
+ }));
1141
1131
  createSelector(
1142
1132
  selectCurrentQueryParams,
1143
1133
  (params) => isValidQueryVerbose(params)
@@ -1193,6 +1183,9 @@ var loadingActions = {
1193
1183
  return { type: `${name3}/setLoadingState:${status}`, payload: message };
1194
1184
  }
1195
1185
  };
1186
+ function selectLoadingState(state) {
1187
+ return state[name3];
1188
+ }
1196
1189
  function isFetchingAction(action) {
1197
1190
  return action.type.endsWith(`:${LOADINGSTATUS.FETCHING}`);
1198
1191
  }
@@ -1382,9 +1375,12 @@ function parseStateFromSearchParams(query) {
1382
1375
  function usePermalink(isEnabled, options) {
1383
1376
  const cubeMap = useSelector(selectOlapCubeMap);
1384
1377
  const { isDirty, panel, params } = useSelector(selectCurrentQueryItem);
1385
- const listener = useCallback((evt) => {
1386
- evt.state && options.onChange(evt.state);
1387
- }, [options.onChange]);
1378
+ const listener = useCallback(
1379
+ (evt) => {
1380
+ evt.state && options.onChange(evt.state);
1381
+ },
1382
+ [options.onChange]
1383
+ );
1388
1384
  useEffect(() => {
1389
1385
  if (isEnabled) {
1390
1386
  window.addEventListener("popstate", listener);
@@ -1407,6 +1403,31 @@ function usePermalink(isEnabled, options) {
1407
1403
  }, [cubeMap, isDirty, panel]);
1408
1404
  return null;
1409
1405
  }
1406
+ function useUpdatePermaLink({
1407
+ isFetched,
1408
+ cube,
1409
+ enabled,
1410
+ isLoading
1411
+ }) {
1412
+ const { panel, params } = useSelector(selectCurrentQueryItem);
1413
+ useEffect(() => {
1414
+ if (isFetched && cube && enabled && !isLoading) {
1415
+ const currPermalink = window.location.search.slice(1);
1416
+ const nextPermalink = serializePermalink(params, panel);
1417
+ if (currPermalink !== nextPermalink) {
1418
+ const nextLocation = `${window.location.pathname}?${nextPermalink}`;
1419
+ window.history.pushState(params, "", nextLocation);
1420
+ }
1421
+ }
1422
+ }, [isFetched, cube, params, panel, enabled, isLoading]);
1423
+ }
1424
+ function useKey() {
1425
+ const { panel, params } = useSelector(selectCurrentQueryItem);
1426
+ if (Object.keys(params.drilldowns).length > 0 && Object.keys(params.measures).length > 0) {
1427
+ return serializePermalink(params, panel);
1428
+ }
1429
+ return false;
1430
+ }
1410
1431
 
1411
1432
  // src/hooks/settings.tsx
1412
1433
  var SettingsContext = createContext(void 0);
@@ -1574,6 +1595,7 @@ function calcMaxMemberCount(query, params, dispatch) {
1574
1595
  memberCount: members.length,
1575
1596
  members
1576
1597
  };
1598
+ dispatch(actions.updateDrilldown(buildDrilldown({ ...ddd, key: stringifyName(ddd) })));
1577
1599
  createCutHandler(params.cuts, ddd, dispatch);
1578
1600
  }
1579
1601
  return members.length;
@@ -1590,7 +1612,7 @@ function hydrateDrilldownProperties(cube, drilldownItem) {
1590
1612
  if (level.matches(drilldownItem)) {
1591
1613
  return buildDrilldown({
1592
1614
  ...drilldownItem,
1593
- key: stringifyName(drilldownItem),
1615
+ // key: stringifyName(drilldownItem),
1594
1616
  fullName: level.fullName,
1595
1617
  uniqueName: level.uniqueName,
1596
1618
  dimType: level.dimension.dimensionType,
@@ -1705,6 +1727,7 @@ function willDownloadQuery(format2) {
1705
1727
  return olapClient.getCube(params.cube).then((cube) => {
1706
1728
  const filename = `${cube.name}_${(/* @__PURE__ */ new Date()).toISOString()}`;
1707
1729
  const queryParams = { ...params, pagiLimit: 0, pagiOffset: 0 };
1730
+ console.log({ format: format2 });
1708
1731
  const query = applyQueryParams(cube.query, queryParams, { previewLimit }).setFormat(format2);
1709
1732
  const dataURL = query.toString("logiclayer").replace(olapClient.datasource.serverUrl, "");
1710
1733
  return Promise.all([
@@ -1753,7 +1776,7 @@ function willExecuteQuery({ limit, offset } = {}) {
1753
1776
  (result) => {
1754
1777
  const [aggregation] = result;
1755
1778
  const { data, headers, status } = aggregation;
1756
- !isPrefetch && dispatch(
1779
+ dispatch(
1757
1780
  queriesActions.updateResult({
1758
1781
  data: data == null ? void 0 : data.data,
1759
1782
  types: (data == null ? void 0 : data.data.length) ? describeData(cube.toJSON(), params, data == null ? void 0 : data.data) : currentResult.types,
@@ -1765,7 +1788,7 @@ function willExecuteQuery({ limit, offset } = {}) {
1765
1788
  );
1766
1789
  return {
1767
1790
  data,
1768
- types: (data == null ? void 0 : data.data.length) ? describeData(cube.toJSON(), params, data == null ? void 0 : data.data) : currentResult.types
1791
+ types: (data == null ? void 0 : data.data.length) ? describeData(cube.toJSON(), params, data == null ? void 0 : data.data) : {}
1769
1792
  };
1770
1793
  },
1771
1794
  (error) => {
@@ -1962,6 +1985,8 @@ function useSetup(serverConfig, locale, defaultCube) {
1962
1985
  actions2.updateLocaleList(cleanLocale);
1963
1986
  }, [cleanLocale]);
1964
1987
  useEffect(() => {
1988
+ actions2.resetServer({});
1989
+ actions2.resetAllParams({});
1965
1990
  actions2.setLoadingState("FETCHING");
1966
1991
  setDone(false);
1967
1992
  actions2.willSetupClient(serverConfig).then(() => actions2.willReloadCubes()).then((cubeMap) => {
@@ -2453,7 +2478,8 @@ function CubeSource() {
2453
2478
 
2454
2479
  // src/components/TableFooter.tsx
2455
2480
  function TableFooter(props) {
2456
- const { result, table } = props;
2481
+ const loading = useSelector$1(selectLoadingState);
2482
+ const { result, table, data = [], isLoading } = props;
2457
2483
  const { translate: t } = useTranslation();
2458
2484
  const { url } = result;
2459
2485
  const { copy, copied } = useClipboard({ timeout: 1e3 });
@@ -2473,11 +2499,11 @@ function TableFooter(props) {
2473
2499
  gap: "sm"
2474
2500
  },
2475
2501
  /* @__PURE__ */ React10__default.createElement(CubeSource, null),
2476
- /* @__PURE__ */ React10__default.createElement(Group, { position: "right", spacing: "sm" }, /* @__PURE__ */ React10__default.createElement(Text, { c: "dimmed" }, t("results.count_rows", { n: totalRowCount })), showPagination && /* @__PURE__ */ React10__default.createElement(MRT_TablePagination, { table }), /* @__PURE__ */ React10__default.createElement(ApiAndCsvButtons, { copied, copyHandler, url }))
2502
+ !loading.loading && !isLoading && /* @__PURE__ */ React10__default.createElement(Group, { position: "right", spacing: "sm" }, totalRowCount && /* @__PURE__ */ React10__default.createElement(Text, { c: "dimmed" }, t("results.count_rows", { n: totalRowCount })), showPagination && /* @__PURE__ */ React10__default.createElement(MRT_TablePagination, { table }), /* @__PURE__ */ React10__default.createElement(ApiAndCsvButtons, { copied, copyHandler, url, data }))
2477
2503
  ));
2478
2504
  }
2479
2505
  var ApiAndCsvButtons = (props) => {
2480
- const { copied, copyHandler, url } = props;
2506
+ const { copied, copyHandler, url, data } = props;
2481
2507
  const { translate: t } = useTranslation();
2482
2508
  return /* @__PURE__ */ React10__default.createElement(Box, { id: "query-results-debug-view" }, /* @__PURE__ */ React10__default.createElement(Group, { spacing: "xs" }, url && /* @__PURE__ */ React10__default.createElement(
2483
2509
  Button,
@@ -2490,12 +2516,11 @@ var ApiAndCsvButtons = (props) => {
2490
2516
  },
2491
2517
  copied ? t("action_copy_done") : t("action_copy"),
2492
2518
  " API"
2493
- ), /* @__PURE__ */ React10__default.createElement(DownloadQuery, null)));
2519
+ ), /* @__PURE__ */ React10__default.createElement(DownloadQuery, { data })));
2494
2520
  };
2495
- var DownloadQuery = () => {
2521
+ var DownloadQuery = ({ data }) => {
2496
2522
  const actions2 = useActions();
2497
2523
  const { translate: t } = useTranslation();
2498
- const { isDirty, result } = useSelector$1(selectCurrentQueryItem);
2499
2524
  const formats = useSelector$1(selectServerFormatsEnabled);
2500
2525
  const csv = formats.find((format2) => format2 === "csv");
2501
2526
  const components = [];
@@ -2515,7 +2540,7 @@ var DownloadQuery = () => {
2515
2540
  )
2516
2541
  );
2517
2542
  }
2518
- if (components.length === 0 || result.data.length === 0) {
2543
+ if (components.length === 0 || data.length === 0) {
2519
2544
  return null;
2520
2545
  }
2521
2546
  return /* @__PURE__ */ React10__default.createElement(Box, { id: "button-group-download-results" }, /* @__PURE__ */ React10__default.createElement(Group, { spacing: "xs" }, components, /* @__PURE__ */ React10__default.createElement(MenuOpts, { formats: formats.filter((f) => f !== "csv") })));
@@ -2689,7 +2714,7 @@ function AddColumnsDrawer() {
2689
2714
  opened,
2690
2715
  position: "right",
2691
2716
  onClose: close2,
2692
- title: /* @__PURE__ */ React10__default.createElement(Group, null, /* @__PURE__ */ React10__default.createElement(IconStack3, { size: "1rem" }), /* @__PURE__ */ React10__default.createElement(Text, { fw: 700 }, t("params.add_columns"))),
2717
+ title: /* @__PURE__ */ React10__default.createElement(Group, null, /* @__PURE__ */ React10__default.createElement(IconPlus, { size: "1.2rem" }), /* @__PURE__ */ React10__default.createElement(Text, { fw: 700 }, t("params.add_columns"))),
2693
2718
  styles: (t2) => ({
2694
2719
  inner: {
2695
2720
  position: "absolute",
@@ -2709,13 +2734,14 @@ function AddColumnsDrawer() {
2709
2734
  },
2710
2735
  /* @__PURE__ */ React10__default.createElement(MeasuresOptions, null),
2711
2736
  /* @__PURE__ */ React10__default.createElement(DrillDownOptions, null)
2712
- ), /* @__PURE__ */ React10__default.createElement(Group, { position: "center" }, smallerThanMd ? /* @__PURE__ */ React10__default.createElement(ActionIcon, { onClick: open, size: "md", variant: "filled", color: theme.primaryColor }, /* @__PURE__ */ React10__default.createElement(IconStack3, { size: "0.75rem" })) : /* @__PURE__ */ React10__default.createElement(Button, { leftIcon: /* @__PURE__ */ React10__default.createElement(IconStack3, { size: "1rem" }), onClick: open, m: "md", size: "xs" }, t("params.add_columns"))));
2737
+ ), /* @__PURE__ */ React10__default.createElement(Group, { position: "center", sx: { flexWrap: "nowrap" } }, smallerThanMd ? /* @__PURE__ */ React10__default.createElement(ActionIcon, { onClick: open, size: "md", variant: "filled", color: theme.primaryColor }, /* @__PURE__ */ React10__default.createElement(IconStack3, { size: "0.75rem" })) : /* @__PURE__ */ React10__default.createElement(Button, { leftIcon: /* @__PURE__ */ React10__default.createElement(IconPlus, { size: "1.2rem" }), onClick: open, m: "md", size: "sm" }, t("params.add_columns"))));
2713
2738
  }
2714
2739
  function DrillDownOptions() {
2715
2740
  const locale = useSelector$1(selectLocale);
2716
2741
  const selectedDimensions = useSelector$1(selectDrilldownItems);
2717
2742
  const dimensions = useSelector$1(selectOlapDimensionItems) || [];
2718
2743
  const activeItems = selectedDimensions.filter((i) => i.active);
2744
+ const activeCount = activeItems.length;
2719
2745
  const options = useMemo(
2720
2746
  () => dimensions.map((dimension) => /* @__PURE__ */ React10__default.createElement(
2721
2747
  DimensionItem,
@@ -2723,14 +2749,15 @@ function DrillDownOptions() {
2723
2749
  dimension,
2724
2750
  locale: locale.code,
2725
2751
  key: dimension.uri,
2726
- activeItems
2752
+ activeItems,
2753
+ activeCount
2727
2754
  }
2728
2755
  )),
2729
- [dimensions, activeItems]
2756
+ [dimensions, activeItems, activeCount]
2730
2757
  );
2731
2758
  return options;
2732
2759
  }
2733
- function DimensionItem({ dimension, locale, activeItems }) {
2760
+ function DimensionItem({ dimension, locale, activeItems, activeCount }) {
2734
2761
  const isChildSubMenu = dimension.hierarchies.length !== 1;
2735
2762
  const options = dimension.hierarchies.map((hie) => /* @__PURE__ */ React10__default.createElement(
2736
2763
  HierarchyItem,
@@ -2740,7 +2767,8 @@ function DimensionItem({ dimension, locale, activeItems }) {
2740
2767
  isSubMenu: isChildSubMenu,
2741
2768
  key: hie.uri,
2742
2769
  locale,
2743
- activeItems
2770
+ activeItems,
2771
+ activeCount
2744
2772
  }
2745
2773
  ));
2746
2774
  if (!isChildSubMenu) {
@@ -2748,7 +2776,7 @@ function DimensionItem({ dimension, locale, activeItems }) {
2748
2776
  }
2749
2777
  return options;
2750
2778
  }
2751
- function HierarchyItem({ dimension, hierarchy, isSubMenu, locale, activeItems }) {
2779
+ function HierarchyItem({ dimension, hierarchy, isSubMenu, locale, activeItems, activeCount }) {
2752
2780
  const { translate: t } = useTranslation();
2753
2781
  useMemo(() => {
2754
2782
  const captions = [getCaption(dimension, locale), getCaption(hierarchy, locale)];
@@ -2771,7 +2799,8 @@ function HierarchyItem({ dimension, hierarchy, isSubMenu, locale, activeItems })
2771
2799
  key: lvl.uri,
2772
2800
  level: lvl,
2773
2801
  locale,
2774
- activeItems
2802
+ activeItems,
2803
+ activeCount
2775
2804
  }
2776
2805
  ));
2777
2806
  if (!isChildSubMenu) {
@@ -2779,14 +2808,14 @@ function HierarchyItem({ dimension, hierarchy, isSubMenu, locale, activeItems })
2779
2808
  }
2780
2809
  return options;
2781
2810
  }
2782
- function LevelItem({ dimension, hierarchy, isSubMenu, level, locale, activeItems }) {
2811
+ function LevelItem({ dimension, hierarchy, isSubMenu, level, locale, activeItems, activeCount }) {
2783
2812
  const [activeFilter, setActiveFilter] = useState(false);
2784
2813
  const { translate: t } = useTranslation();
2785
2814
  const actions2 = useActions();
2786
2815
  const cutItems = useSelector$1(selectCutItems);
2787
- const dimensions = useSelector$1(selectOlapDimensionItems);
2788
2816
  const drilldowns = useSelector$1(selectDrilldownMap);
2789
2817
  const ditems = useSelector$1(selectDrilldownItems);
2818
+ const dimensions = useSelector$1(selectOlapDimensionItems);
2790
2819
  const label = useMemo(() => {
2791
2820
  const captions = [
2792
2821
  getCaption(dimension, locale),
@@ -2828,6 +2857,9 @@ function LevelItem({ dimension, hierarchy, isSubMenu, level, locale, activeItems
2828
2857
  return drilldown;
2829
2858
  }
2830
2859
  const currentDrilldown = drilldowns[stringifyName(level)];
2860
+ const isOtherHierarchySelected = activeItems.some(
2861
+ (activeItem) => activeItem.dimension === dimension.name && activeItem.hierarchy !== hierarchy.name
2862
+ );
2831
2863
  useLayoutEffect(() => {
2832
2864
  if (!drilldowns[stringifyName(level)] && !ditems.find((d) => d.uniqueName === buildDrilldown(level).uniqueName)) {
2833
2865
  createDrilldown(level, cutItems);
@@ -2840,10 +2872,13 @@ function LevelItem({ dimension, hierarchy, isSubMenu, level, locale, activeItems
2840
2872
  actions2.updateCut({ ...item, members });
2841
2873
  }, []);
2842
2874
  const checked = activeItems.map(stringifyName).includes(stringifyName(level));
2875
+ const disableUncheck = activeCount === 1 && checked;
2876
+ const isDisabled = isOtherHierarchySelected && !checked;
2843
2877
  if (!currentDrilldown) return;
2844
2878
  return currentDrilldown && /* @__PURE__ */ React10__default.createElement(React10__default.Fragment, null, /* @__PURE__ */ React10__default.createElement(Group, { mt: "sm", position: "apart", key: level.uri, noWrap: true }, /* @__PURE__ */ React10__default.createElement(
2845
2879
  Checkbox,
2846
2880
  {
2881
+ sx: { cursor: "pointer" },
2847
2882
  onChange: () => {
2848
2883
  if (cut) {
2849
2884
  const active = checked ? false : cut.members.length ? true : false;
@@ -2853,9 +2888,18 @@ function LevelItem({ dimension, hierarchy, isSubMenu, level, locale, activeItems
2853
2888
  },
2854
2889
  checked,
2855
2890
  label,
2856
- size: "xs"
2891
+ size: "xs",
2892
+ disabled: isDisabled || disableUncheck
2857
2893
  }
2858
- ), /* @__PURE__ */ React10__default.createElement(Group, null, /* @__PURE__ */ React10__default.createElement(ActionIcon, { size: "sm", onClick: () => setActiveFilter((value) => !value) }, activeFilter ? /* @__PURE__ */ React10__default.createElement(IconFilterOff, null) : /* @__PURE__ */ React10__default.createElement(IconFilter, null)), /* @__PURE__ */ React10__default.createElement(ThemeIcon, { size: "xs", color: "gray", variant: "light", bg: "transparent" }, /* @__PURE__ */ React10__default.createElement(StackSVG, null)))), activeFilter && /* @__PURE__ */ React10__default.createElement(Box, { pt: "md" }, /* @__PURE__ */ React10__default.createElement(
2894
+ ), /* @__PURE__ */ React10__default.createElement(Group, { sx: { flexWrap: "nowrap" } }, /* @__PURE__ */ React10__default.createElement(
2895
+ ActionIcon,
2896
+ {
2897
+ size: "sm",
2898
+ onClick: () => setActiveFilter((value) => !value),
2899
+ disabled: isDisabled
2900
+ },
2901
+ activeFilter ? /* @__PURE__ */ React10__default.createElement(IconFilterOff, null) : /* @__PURE__ */ React10__default.createElement(IconFilter, null)
2902
+ ), /* @__PURE__ */ React10__default.createElement(ThemeIcon, { size: "xs", color: "gray", variant: "light", bg: "transparent" }, /* @__PURE__ */ React10__default.createElement(StackSVG, null)))), activeFilter && /* @__PURE__ */ React10__default.createElement(Box, { pt: "md" }, /* @__PURE__ */ React10__default.createElement(
2859
2903
  MultiSelect,
2860
2904
  {
2861
2905
  sx: { flex: "1 1 100%" },
@@ -2876,7 +2920,8 @@ function LevelItem({ dimension, hierarchy, isSubMenu, level, locale, activeItems
2876
2920
  label: m.caption ? `${m.caption} ${m.key}` : m.name
2877
2921
  })),
2878
2922
  clearable: true,
2879
- nothingFound: "Nothing found"
2923
+ nothingFound: "Nothing found",
2924
+ disabled: isDisabled
2880
2925
  }
2881
2926
  )));
2882
2927
  }
@@ -2905,20 +2950,12 @@ function getFilterFn(filter) {
2905
2950
  return "lessThan";
2906
2951
  }
2907
2952
  }
2908
- function getFilterValue(filter) {
2909
- const filterFn = getFilterFn(filter);
2910
- const isBetween = filterFn === "between";
2911
- if (isBetween && filter.conditionTwo) {
2912
- return [filter.conditionOne[2], filter.conditionTwo[2]];
2913
- }
2914
- return filter.conditionOne[2];
2915
- }
2916
2953
  function isNotValid(value) {
2917
2954
  return value === null || value === void 0 || Number.isNaN(value);
2918
2955
  }
2919
2956
  function NumberInputComponent({ text, filter }) {
2920
2957
  const actions2 = useActions();
2921
- function getFilterValue2(filter2) {
2958
+ function getFilterValue(filter2) {
2922
2959
  return isNotValid(filter2.conditionOne[2]) || filter2.conditionOne[2] === 0 ? "" : filter2.conditionOne[2];
2923
2960
  }
2924
2961
  function onInputChange({ filter: filter2, value }) {
@@ -2932,7 +2969,7 @@ function NumberInputComponent({ text, filter }) {
2932
2969
  {
2933
2970
  description: text,
2934
2971
  placeholder: text,
2935
- value: getFilterValue2(filter),
2972
+ value: getFilterValue(filter),
2936
2973
  onChange: (value) => onInputChange({ filter, value }),
2937
2974
  sx: { flex: "1 1 auto" },
2938
2975
  size: "xs"
@@ -2947,14 +2984,14 @@ function MinMax({ filter, ...rest }) {
2947
2984
  const active = Boolean(min2) && Boolean(max2);
2948
2985
  actions2.updateFilter(buildFilter({ ...filter2, active, ...conditions }));
2949
2986
  }
2950
- function getFilterValue2(condition) {
2987
+ function getFilterValue(condition) {
2951
2988
  if (condition) {
2952
2989
  return isNotValid(condition[2]) || condition[2] === 0 ? "" : condition[2];
2953
2990
  }
2954
2991
  return "";
2955
2992
  }
2956
- const min = getFilterValue2(filter.conditionOne);
2957
- const max = getFilterValue2(filter.conditionTwo);
2993
+ const min = getFilterValue(filter.conditionOne);
2994
+ const max = getFilterValue(filter.conditionTwo);
2958
2995
  return /* @__PURE__ */ React10__default.createElement(Flex, { gap: "xs" }, /* @__PURE__ */ React10__default.createElement(
2959
2996
  NumberInput,
2960
2997
  {
@@ -3058,18 +3095,23 @@ function FilterItem4({
3058
3095
  const isBetween = filterFn === "between";
3059
3096
  const checked = activeItems.map((active) => active.measure.name).includes(measure.name);
3060
3097
  const actions2 = useActions();
3098
+ const isLastSelected = activeItems.length === 1 && checked;
3061
3099
  return /* @__PURE__ */ React10__default.createElement(Box, { key: measure.name }, /* @__PURE__ */ React10__default.createElement(Group, { mt: "sm", position: "apart" }, /* @__PURE__ */ React10__default.createElement(
3062
3100
  Checkbox,
3063
3101
  {
3102
+ sx: { cursor: "pointer" },
3064
3103
  onChange: () => {
3065
- actions2.updateMeasure({ ...measure, active: !measure.active });
3066
- actions2.updateFilter({ ...filter, active: checked ? false : true });
3104
+ if (!isLastSelected) {
3105
+ actions2.updateMeasure({ ...measure, active: !measure.active });
3106
+ actions2.updateFilter({ ...filter, active: checked ? false : true });
3107
+ }
3067
3108
  },
3068
3109
  checked,
3069
3110
  label: measure.name,
3070
- size: "xs"
3111
+ size: "xs",
3112
+ disabled: isLastSelected
3071
3113
  }
3072
- ), /* @__PURE__ */ React10__default.createElement(Group, null, activeFilter && /* @__PURE__ */ React10__default.createElement(FilterFnsMenu, { filter }), /* @__PURE__ */ React10__default.createElement(ActionIcon, { size: "xs", onClick: () => setActiveFilter((value) => !value) }, activeFilter ? /* @__PURE__ */ React10__default.createElement(IconFilterOff, null) : /* @__PURE__ */ React10__default.createElement(IconFilter, null)), /* @__PURE__ */ React10__default.createElement(ThemeIcon, { size: "xs", color: "gray", variant: "light", bg: "transparent" }, /* @__PURE__ */ React10__default.createElement(BarsSVG, null)))), activeFilter && /* @__PURE__ */ React10__default.createElement(Box, { pt: "md" }, isBetween ? /* @__PURE__ */ React10__default.createElement(MinMax, { filter }) : /* @__PURE__ */ React10__default.createElement(NumberInputComponent, { text, filter })));
3114
+ ), /* @__PURE__ */ React10__default.createElement(Group, { sx: { flexWrap: "nowrap" } }, activeFilter && /* @__PURE__ */ React10__default.createElement(FilterFnsMenu, { filter }), /* @__PURE__ */ React10__default.createElement(ActionIcon, { size: "xs", onClick: () => setActiveFilter((value) => !value) }, activeFilter ? /* @__PURE__ */ React10__default.createElement(IconFilterOff, null) : /* @__PURE__ */ React10__default.createElement(IconFilter, null)), /* @__PURE__ */ React10__default.createElement(ThemeIcon, { size: "xs", color: "gray", variant: "light", bg: "transparent" }, /* @__PURE__ */ React10__default.createElement(BarsSVG, null)))), activeFilter && /* @__PURE__ */ React10__default.createElement(Box, { pt: "md" }, isBetween ? /* @__PURE__ */ React10__default.createElement(MinMax, { filter }) : /* @__PURE__ */ React10__default.createElement(NumberInputComponent, { text, filter })));
3073
3115
  }
3074
3116
  var DrawerMenu_default = AddColumnsDrawer;
3075
3117
  var removeColumn = (actions2, entity, measures, drilldowns) => {
@@ -3152,31 +3194,28 @@ function getFiltersConditions(fn, value) {
3152
3194
  ]);
3153
3195
  return (_a = comparisonMap.get(fn)) == null ? void 0 : _a(value);
3154
3196
  }
3155
- function useTableData({ columns, filters, cuts, pagination }) {
3156
- const normalizedFilters = filters.map((filter) => ({
3157
- id: filter.measure,
3158
- value: getFilterValue(filter)
3159
- // fn: getFilterFn(filter)
3160
- }));
3161
- const normalizedCuts = cuts.map((cut) => ({ id: cut.uniqueName, members: cut.members }));
3162
- const filterKey = JSON.stringify(normalizedFilters);
3163
- const cutKey = JSON.stringify(normalizedCuts);
3197
+ function useTableData({ columns, pagination, cube }) {
3198
+ const { code: locale } = useSelector$1(selectLocale);
3199
+ const permaKey = useKey();
3200
+ const loadingState = useSelector$1(selectLoadingState);
3164
3201
  const actions2 = useActions();
3165
- const columnsStr = JSON.stringify(columns.sort());
3166
3202
  const page = pagination.pageIndex;
3167
- const enabled = Boolean(columns.length) || Boolean(filters.length) || Boolean(cuts.length);
3168
- const initialKey = enabled ? [columnsStr, filterKey, cutKey, page] : "";
3203
+ const enabled = Boolean(columns.length);
3204
+ const initialKey = permaKey ? [permaKey, page] : permaKey;
3169
3205
  const [filterKeydebouced, setDebouncedTerm] = useState(initialKey);
3170
3206
  useEffect(() => {
3171
- if (!enabled) return;
3172
- const handler = debounce(() => {
3173
- const term = [columnsStr, filterKey, cutKey, page];
3174
- setDebouncedTerm(term);
3175
- }, 700);
3207
+ if (!enabled && permaKey) return;
3208
+ const handler = debounce(
3209
+ () => {
3210
+ const term = [permaKey, page];
3211
+ setDebouncedTerm(term);
3212
+ },
3213
+ loadingState.loading ? 0 : 800
3214
+ );
3176
3215
  handler();
3177
3216
  return () => handler.cancel();
3178
- }, [columnsStr, filterKey, cutKey, page, enabled]);
3179
- return useQuery({
3217
+ }, [page, enabled, cube, locale, permaKey]);
3218
+ const query = useQuery({
3180
3219
  queryKey: ["table", filterKeydebouced],
3181
3220
  queryFn: () => {
3182
3221
  return actions2.willExecuteQuery().then((res) => {
@@ -3188,49 +3227,52 @@ function useTableData({ columns, filters, cuts, pagination }) {
3188
3227
  staleTime: 3e5,
3189
3228
  enabled: enabled && !!filterKeydebouced
3190
3229
  });
3230
+ const client = useQueryClient();
3231
+ const cachedData = client.getQueryData(["table", filterKeydebouced]);
3232
+ useUpdatePermaLink({ isFetched: Boolean(cachedData), cube, enabled, isLoading: query.isLoading });
3233
+ return query;
3191
3234
  }
3192
3235
  function usePrefetch({
3193
- data,
3194
3236
  isPlaceholderData,
3195
3237
  limit,
3196
- offset,
3197
3238
  totalRowCount,
3198
- columns,
3199
- cuts,
3200
- filters,
3201
3239
  pagination,
3202
3240
  isFetching
3203
3241
  }) {
3242
+ const { code: locale } = useSelector$1(selectLocale);
3204
3243
  const queryClient2 = useQueryClient();
3205
3244
  const actions2 = useActions();
3245
+ const paramKey = useKey();
3206
3246
  const page = pagination.pageIndex + 1;
3207
3247
  const hasMore = page * pagination.pageSize <= totalRowCount;
3208
3248
  const off = page * pagination.pageSize;
3209
- const normalizedFilters = filters.map((filter) => ({
3210
- id: filter.measure,
3211
- value: getFilterValue(filter)
3212
- // fn: getFilterFn(filter)
3213
- }));
3214
- const normalizedCuts = cuts.map((cut) => ({ id: cut.uniqueName, members: cut.members }));
3215
- const filterKey = JSON.stringify(normalizedFilters);
3216
- const cutKey = JSON.stringify(normalizedCuts);
3217
- const columnsStr = JSON.stringify(columns.sort());
3218
- const key = [columnsStr, filterKey, cutKey, page];
3249
+ const key = [paramKey, page];
3219
3250
  React10__default.useEffect(() => {
3220
3251
  if (!isPlaceholderData && hasMore && !isFetching) {
3221
3252
  queryClient2.prefetchQuery({
3222
3253
  queryKey: ["table", key],
3223
3254
  queryFn: () => {
3224
3255
  return actions2.willExecuteQuery({ offset: off, limit }).then((res) => {
3225
- const { data: data2, types } = res;
3226
- const { data: tableData, page: page2 } = data2;
3256
+ const { data, types } = res;
3257
+ const { data: tableData, page: page2 } = data;
3227
3258
  return { data: tableData != null ? tableData : [], types, page: page2 };
3228
3259
  });
3229
3260
  },
3230
3261
  staleTime: 3e5
3231
3262
  });
3232
3263
  }
3233
- }, [limit, page, isPlaceholderData, key, queryClient2, hasMore, off, isFetching]);
3264
+ }, [
3265
+ limit,
3266
+ page,
3267
+ isPlaceholderData,
3268
+ key,
3269
+ queryClient2,
3270
+ hasMore,
3271
+ off,
3272
+ isFetching,
3273
+ locale,
3274
+ paramKey
3275
+ ]);
3234
3276
  }
3235
3277
  function useTable({
3236
3278
  cube,
@@ -3239,16 +3281,16 @@ function useTable({
3239
3281
  columnSorting = () => 0,
3240
3282
  ...mantineTableProps
3241
3283
  }) {
3242
- const { types } = result;
3243
3284
  const filterItems = useSelector$1(selectFilterItems);
3244
3285
  const filtersMap = useSelector$1(selectFilterMap);
3245
3286
  const measuresOlap = useSelector$1(selectOlapMeasureItems);
3246
3287
  const measuresMap = useSelector$1(selectMeasureMap);
3247
3288
  const drilldowns = useSelector$1(selectDrilldownItems);
3248
3289
  const measures = useSelector$1(selectMeasureItems);
3290
+ useSelector$1(selectCutItems);
3249
3291
  const actions2 = useActions();
3250
- const itemsCuts = useSelector$1(selectCutItems);
3251
3292
  const { limit, offset } = useSelector$1(selectPaginationParams);
3293
+ useSelector$1(selectLoadingState);
3252
3294
  const [pagination, setPagination] = useState({
3253
3295
  pageIndex: offset,
3254
3296
  pageSize: limit
@@ -3282,25 +3324,19 @@ function useTable({
3282
3324
  return { measure, filter };
3283
3325
  });
3284
3326
  }, [measuresMap, measuresOlap, filtersMap, filterItems]);
3285
- const { isLoading, isFetching, isError, data, isPlaceholderData } = useTableData({
3327
+ const { isLoading, isFetching, isFetched, isError, data, isPlaceholderData, status, fetchStatus } = useTableData({
3286
3328
  columns: finalUniqueKeys,
3287
- filters: filterItems.filter(isActiveItem),
3288
- cuts: itemsCuts.filter(isActiveCut),
3289
- pagination
3329
+ pagination,
3330
+ cube: cube.name
3290
3331
  });
3291
3332
  const tableData = (data == null ? void 0 : data.data) || [];
3292
- const tableTypes = (data == null ? void 0 : data.types) || types;
3333
+ const tableTypes = (data == null ? void 0 : data.types) || {};
3293
3334
  const totalRowCount = data == null ? void 0 : data.page.total;
3294
3335
  const finalKeys = Object.values(tableTypes).filter((t2) => !t2.isId).filter(columnFilter).sort(columnSorting);
3295
3336
  usePrefetch({
3296
- data: tableData,
3297
3337
  isPlaceholderData,
3298
- offset,
3299
3338
  limit,
3300
3339
  totalRowCount,
3301
- columns: finalUniqueKeys,
3302
- filters: filterItems.filter(isActiveItem),
3303
- cuts: itemsCuts.filter(isActiveCut),
3304
3340
  pagination,
3305
3341
  isFetching: isFetching || isLoading
3306
3342
  });
@@ -3477,6 +3513,8 @@ function useTable({
3477
3513
  }),
3478
3514
  [isError]
3479
3515
  );
3516
+ const isTransitionState = status !== "success" && !isError;
3517
+ const isLoad = isLoading || data === void 0 || isTransitionState;
3480
3518
  const table = useMantineReactTable({
3481
3519
  columns,
3482
3520
  data: tableData,
@@ -3487,7 +3525,7 @@ function useTable({
3487
3525
  manualSorting: false,
3488
3526
  rowCount: totalRowCount,
3489
3527
  state: {
3490
- isLoading: isLoading || isFetching || data === void 0,
3528
+ isLoading: isLoading || data === void 0 || isTransitionState,
3491
3529
  pagination,
3492
3530
  showAlertBanner: isError,
3493
3531
  showProgressBars: isFetching || isLoading
@@ -3495,10 +3533,11 @@ function useTable({
3495
3533
  ...constTableProps,
3496
3534
  ...mantineTableProps
3497
3535
  });
3498
- return { table, isError, isLoading, data: tableData };
3536
+ return { table, isError, isLoading: isLoad, data: tableData, columns };
3499
3537
  }
3500
- function TableView({ table, result, isError, isLoading, data }) {
3538
+ function TableView({ table, result, isError, isLoading = false, data }) {
3501
3539
  const isData = Boolean(table.getRowModel().rows.length);
3540
+ const loadingState = useSelector$1(selectLoadingState);
3502
3541
  return /* @__PURE__ */ React10__default.createElement(Box, { sx: { height: "100%" } }, /* @__PURE__ */ React10__default.createElement(Flex, { direction: "column", justify: "space-between", sx: { height: "100%", flex: "1 1 auto" } }, /* @__PURE__ */ React10__default.createElement(MRT_ProgressBar, { isTopToolbar: false, table }), /* @__PURE__ */ React10__default.createElement(
3503
3542
  ScrollArea,
3504
3543
  {
@@ -3509,6 +3548,7 @@ function TableView({ table, result, isError, isLoading, data }) {
3509
3548
  overflow: "scroll"
3510
3549
  }
3511
3550
  },
3551
+ /* @__PURE__ */ React10__default.createElement(LoadingOverlay, { visible: isLoading || loadingState.loading }),
3512
3552
  /* @__PURE__ */ React10__default.createElement(
3513
3553
  Table,
3514
3554
  {
@@ -3582,7 +3622,7 @@ function TableView({ table, result, isError, isLoading, data }) {
3582
3622
  )))))
3583
3623
  ),
3584
3624
  !isData && !isError && !isLoading && /* @__PURE__ */ React10__default.createElement(NoRecords, null)
3585
- ), /* @__PURE__ */ React10__default.createElement(MRT_ToolbarAlertBanner, { stackAlertBanner: true, table }), /* @__PURE__ */ React10__default.createElement(TableFooter_default, { table, data, result })));
3625
+ ), /* @__PURE__ */ React10__default.createElement(MRT_ToolbarAlertBanner, { stackAlertBanner: true, table }), /* @__PURE__ */ React10__default.createElement(TableFooter_default, { table, data, result, isLoading })));
3586
3626
  }
3587
3627
  var ColumnFilterCell = ({
3588
3628
  header,
@@ -3871,7 +3911,7 @@ function SuccessResult(props) {
3871
3911
  const { previewLimit, actions: actions2 } = useSettings();
3872
3912
  const queryItem = useSelector$1(selectCurrentQueryItem);
3873
3913
  const isPreviewMode = useSelector$1(selectIsPreviewMode);
3874
- const { table, isError, isLoading, data } = useTable({ cube, result });
3914
+ const { table, isError, isLoading, data, columns } = useTable({ cube, result });
3875
3915
  const fullscreen = useFullscreen();
3876
3916
  const [CurrentComponent, panelKey, panelMeta] = useMemo(() => {
3877
3917
  const currentPanel = queryItem.panel || `${panels[0].key}-`;
@@ -3893,7 +3933,7 @@ function SuccessResult(props) {
3893
3933
  w: "100%"
3894
3934
  },
3895
3935
  /* @__PURE__ */ React10__default.createElement(ExplorerTabs, { panels, onChange: tabHandler, value: panelKey }),
3896
- (!queryItem.panel || queryItem.panel === "table") && /* @__PURE__ */ React10__default.createElement(Group, { sx: { display: "flex", flex: "0 1 auto" }, mr: "sm", noWrap: true }, /* @__PURE__ */ React10__default.createElement(DrawerMenu_default, null), /* @__PURE__ */ React10__default.createElement(Toolbar, { table, fullscreen }))
3936
+ (!queryItem.panel || queryItem.panel === "table") && /* @__PURE__ */ React10__default.createElement(Group, { sx: { display: "flex", flex: "0 1 auto", gap: "0.5rem" }, mr: "sm", noWrap: true }, /* @__PURE__ */ React10__default.createElement(Toolbar, { table, fullscreen }), /* @__PURE__ */ React10__default.createElement(DrawerMenu_default, null))
3897
3937
  ), isPreviewMode && /* @__PURE__ */ React10__default.createElement(Alert, { id: "alert-load-all-results", color: "yellow", radius: 0, sx: { flex: "0 0 auto" } }, /* @__PURE__ */ React10__default.createElement(Group, { position: "apart" }, /* @__PURE__ */ React10__default.createElement(Text, null, /* @__PURE__ */ React10__default.createElement(Text, { fw: 700, span: true }, t("previewMode.title_preview"), ":", " "), /* @__PURE__ */ React10__default.createElement(Text, { span: true }, t("previewMode.description_preview", { limit: previewLimit }))), /* @__PURE__ */ React10__default.createElement(PreviewModeSwitch, null))), /* @__PURE__ */ React10__default.createElement(Box, { id: "query-results-content", sx: { flex: "1 1", height: "calc(100% - 60px)" } }, /* @__PURE__ */ React10__default.createElement(Suspense, { fallback: props.children }, /* @__PURE__ */ React10__default.createElement(Flex, { h: "100%" }, /* @__PURE__ */ React10__default.createElement(Box, { sx: { flex: "1 1", overflowX: "scroll" } }, /* @__PURE__ */ React10__default.createElement(
3898
3938
  CurrentComponent,
3899
3939
  {
@@ -3904,7 +3944,8 @@ function SuccessResult(props) {
3904
3944
  table,
3905
3945
  isError,
3906
3946
  isLoading,
3907
- data
3947
+ data,
3948
+ columns
3908
3949
  }
3909
3950
  )))))));
3910
3951
  }
@@ -4186,7 +4227,7 @@ function LocaleSelector() {
4186
4227
  var [useSideBar, Provider] = createContext2("SideBar");
4187
4228
  function SideBarProvider(props) {
4188
4229
  const [input, setInput] = useState("");
4189
- const [expanded, setExpanded] = useState(false);
4230
+ const [expanded, setExpanded] = useState(true);
4190
4231
  const [results, setResults] = useState([]);
4191
4232
  const [map, setMap] = useState();
4192
4233
  const [graph, setGraph] = useState(new graph_default());
@@ -4382,31 +4423,17 @@ init_esm_shims();
4382
4423
  init_esm_shims();
4383
4424
  function useSelectCube(onSelectCube) {
4384
4425
  const { updateMeasure, updateCut, updateDrilldown, willFetchMembers: willFetchMembers2 } = useActions();
4385
- useCallback((level, dimensions) => {
4386
- const drilldownItem = buildDrilldown(level);
4387
- createCutHandler2(level);
4388
- updateDrilldown(drilldownItem);
4389
- return willFetchMembers2({ ...level, level: level.name }).then((members) => {
4390
- const dimension = dimensions.find((dim) => dim.name === level.dimension);
4391
- if (!dimension) return;
4392
- return updateDrilldown({
4393
- ...drilldownItem,
4394
- dimType: dimension.dimensionType,
4395
- memberCount: members.length,
4396
- members
4397
- });
4398
- });
4399
- }, []);
4426
+ const actions2 = useActions();
4400
4427
  const createCutHandler2 = React10__default.useCallback((level) => {
4401
4428
  const cutItem = buildCut({ ...level });
4402
4429
  cutItem.active = false;
4403
4430
  updateCut(cutItem);
4404
4431
  }, []);
4405
- function createDrilldown(level, dimensions) {
4432
+ async function createDrilldown(level, dimensions) {
4406
4433
  const drilldown = buildDrilldown({ ...level, key: stringifyName(level), active: true });
4407
4434
  updateDrilldown(drilldown);
4408
4435
  createCutHandler2({ ...level, key: stringifyName(level) });
4409
- willFetchMembers2({ ...level, level: level.name }).then((members) => {
4436
+ await willFetchMembers2({ ...level, level: level.name }).then((members) => {
4410
4437
  const dimension = dimensions.find((dim) => dim.name === level.dimension);
4411
4438
  if (!dimension) return;
4412
4439
  updateDrilldown({
@@ -4423,9 +4450,8 @@ function useSelectCube(onSelectCube) {
4423
4450
  const drilldowns = deriveDrilldowns(dimensions);
4424
4451
  if (measure && drilldowns.length > 0) {
4425
4452
  updateMeasure({ ...measure, active: true });
4426
- for (const level of drilldowns) {
4427
- createDrilldown(level, dimensions);
4428
- }
4453
+ const promises = drilldowns.map((level) => createDrilldown(level, dimensions));
4454
+ return Promise.all(promises).then(() => actions2.setLoadingState("SUCCESS"));
4429
4455
  }
4430
4456
  });
4431
4457
  }
@@ -4580,9 +4606,10 @@ function getCube(items, table, subtopic, locale) {
4580
4606
  return cube;
4581
4607
  }
4582
4608
  function useBuildGraph(items, locale, graph, setGraph) {
4609
+ const [filteredItems, setFilteredItems] = useState([]);
4583
4610
  useEffect(() => {
4584
4611
  const graph2 = new graph_default();
4585
- items.map((item) => {
4612
+ const filteredItems2 = items.map((item) => {
4586
4613
  const { name: name4 } = item;
4587
4614
  const topic = getAnnotation(item, "topic", locale);
4588
4615
  const subtopic = getAnnotation(item, "subtopic", locale);
@@ -4594,13 +4621,15 @@ function useBuildGraph(items, locale, graph, setGraph) {
4594
4621
  graph2.addNode(name4);
4595
4622
  graph2.addEdge(topic, subtopic);
4596
4623
  graph2.addEdge(subtopic, name4);
4624
+ return item;
4597
4625
  }
4598
- return item;
4599
- });
4600
- graph2.items = items;
4626
+ return null;
4627
+ }).filter(Boolean);
4628
+ setFilteredItems(filteredItems2);
4629
+ graph2.items = filteredItems2;
4601
4630
  setGraph(graph2);
4602
4631
  }, [items, locale, setGraph]);
4603
- return { graph };
4632
+ return { graph, filteredItems };
4604
4633
  }
4605
4634
  function CubeTree({
4606
4635
  items,
@@ -4609,20 +4638,26 @@ function CubeTree({
4609
4638
  }) {
4610
4639
  const { graph, setGraph, map, input } = useSideBar();
4611
4640
  const { translate: t } = useTranslation();
4612
- useBuildGraph(items, locale, graph, setGraph);
4641
+ const { filteredItems } = useBuildGraph(items, locale, graph, setGraph);
4613
4642
  const actions2 = useActions();
4643
+ const query = useSelector$1(selectCurrentQueryParams);
4614
4644
  const onSelectCube = (table, subtopic) => {
4615
4645
  const cube = items.find(
4616
4646
  (item) => item.name === table && getAnnotation(item, "subtopic", locale) === subtopic
4617
4647
  );
4618
4648
  if (cube) {
4619
- actions2.resetDrilldowns({});
4620
- actions2.resetCuts({});
4621
- actions2.resetMeasures({});
4649
+ const { drilldowns, cuts, filters, measures, ...newQuery } = query;
4650
+ actions2.setLoadingState("FETCHING");
4651
+ actions2.resetAllParams(newQuery);
4652
+ actions2.updateResult({ data: [], types: {}, url: "", status: 200 });
4622
4653
  return actions2.willSetCube(cube.name);
4623
4654
  }
4624
4655
  };
4625
- const topics = useMemo(() => getKeys2(items, "topic", locale), [items, locale]);
4656
+ let topics = useMemo(
4657
+ () => getKeys2(filteredItems, "topic", locale),
4658
+ [filteredItems, locale]
4659
+ );
4660
+ topics = [topics[0], topics[1]];
4626
4661
  if (input.length > 0 && map && !(map.size > 0)) {
4627
4662
  return /* @__PURE__ */ React10__default.createElement(Text, { ta: "center", fz: "xs", my: "sm", italic: true }, t("params.label_no_results"));
4628
4663
  }
@@ -4832,10 +4867,14 @@ var useStyles4 = createStyles((theme, params) => ({
4832
4867
  }
4833
4868
  }));
4834
4869
  function ExplorerContent(props) {
4835
- useMantineTheme();
4836
- useState(false);
4870
+ const { setSource } = props;
4837
4871
  const translation = useTranslation();
4838
- useSetup(props.source, props.dataLocale, props.defaultCube);
4872
+ const done = useSetup(props.source, props.dataLocale, props.defaultCube);
4873
+ useEffect(() => {
4874
+ if (setSource) {
4875
+ setSource({ loading: !done });
4876
+ }
4877
+ }, [setSource, done]);
4839
4878
  const { classes } = useStyles4({ height: props.height });
4840
4879
  useEffect(() => {
4841
4880
  if (props.uiLocale) translation.setLocale(props.uiLocale);
@@ -5516,7 +5555,9 @@ function ExplorerComponent(props) {
5516
5555
  previewLimit = 50,
5517
5556
  withinMantineProvider = true,
5518
5557
  withinReduxProvider = false,
5519
- withMultiQuery = false
5558
+ withMultiQuery = false,
5559
+ setSource,
5560
+ source
5520
5561
  } = props;
5521
5562
  const locale = useMemo(() => dataLocale.toString().split(","), [dataLocale]);
5522
5563
  const panels = useMemo(
@@ -5550,11 +5591,12 @@ function ExplorerComponent(props) {
5550
5591
  /* @__PURE__ */ React10__default.createElement(TranslationProvider, { defaultLocale: props.uiLocale, translations: props.translations }, /* @__PURE__ */ React10__default.createElement(
5551
5592
  ExplorerContent,
5552
5593
  {
5594
+ setSource,
5553
5595
  dataLocale: locale,
5554
5596
  defaultOpenParams,
5555
5597
  height,
5556
5598
  panels,
5557
- source: props.source,
5599
+ source,
5558
5600
  splash: props.splash,
5559
5601
  uiLocale: props.uiLocale,
5560
5602
  defaultCube: props.defaultCube,
@@ -6627,7 +6669,6 @@ function createVizbuilderView(settings) {
6627
6669
  return VizbuilderView;
6628
6670
  function VizbuilderView(props) {
6629
6671
  const { cube, panelKey, params, result } = props;
6630
- console.log(result);
6631
6672
  const { actions: actions2, formatters } = useSettings();
6632
6673
  const [panelName, currentChart] = useMemo(() => `${panelKey || ""}-`.split("-"), [panelKey]);
6633
6674
  const resetCurrentPanel = useCallback(() => {
@@ -6638,7 +6679,7 @@ function createVizbuilderView(settings) {
6638
6679
  [
6639
6680
  {
6640
6681
  cube,
6641
- dataset: result.data.data,
6682
+ dataset: result.data,
6642
6683
  params: {
6643
6684
  locale: params.locale || defaultLocale,
6644
6685
  booleans: params.booleans,
@@ -6671,7 +6712,7 @@ function createVizbuilderView(settings) {
6671
6712
  ],
6672
6713
  chartGenOptions
6673
6714
  ),
6674
- [cube, result.data.data, params]
6715
+ [cube, result.data, params]
6675
6716
  );
6676
6717
  const content = useMemo(() => {
6677
6718
  const isSingleChart = charts.length === 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datawheel/data-explorer",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "exports": {
5
5
  ".": {
6
6
  "import": "./dist/main.js"