@datawheel/data-explorer 0.1.2 → 0.2.0

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 +293 -239
  2. package/package.json +3 -1
package/dist/main.js CHANGED
@@ -1,4 +1,4 @@
1
- import { keyframes, createStyles, Select, rem, Flex, Title, Text, Group, Button, Box, Anchor, Input, Stack, SimpleGrid, Table, MultiSelect, Center, Alert, Loader, Modal, NumberInput, Menu, ActionIcon, useMantineTheme, Header, MantineProvider, Paper, useComponentDefaultProps, Switch, ThemeIcon, Tooltip, Tabs, ScrollArea, 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, 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';
2
2
  import { useClipboard, useClickOutside, useFullscreen, useMediaQuery, useDebouncedValue, useDisclosure } from '@mantine/hooks';
3
3
  import { Prism } from '@mantine/prism';
4
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';
@@ -14,7 +14,7 @@ import formUrlEncode from 'form-urlencoded';
14
14
  import formUrlDecode from 'form-urldecoded';
15
15
  import { MRT_ProgressBar, flexRender, MRT_TableBodyCell, MRT_ToolbarAlertBanner, useMantineReactTable, MantineReactTable, MRT_TablePagination } from 'mantine-react-table';
16
16
  import { formatAbbreviate, format } from 'd3plus-format';
17
- import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query';
17
+ import { QueryClient, QueryClientProvider, useQuery, useQueryClient } from '@tanstack/react-query';
18
18
  import debounce from 'lodash.debounce';
19
19
  import { matchSorter } from 'match-sorter';
20
20
  import yn from 'yn';
@@ -203,6 +203,7 @@ var defaultTranslation = {
203
203
  dataset: "Select Dataset"
204
204
  },
205
205
  comparison: {
206
+ BT: "Between",
206
207
  EQ: "Equal to",
207
208
  GT: "Greater than",
208
209
  GTE: "Equal or greater than",
@@ -238,12 +239,15 @@ var defaultTranslation = {
238
239
  action_clear: "Clear query",
239
240
  action_clear_description: "Clear all parameters from your current query",
240
241
  action_execute: "Execute query",
242
+ add_columns: "Add columns",
241
243
  column_title: "Parameters",
242
244
  current_endpoint: "Current endpoint: {{label}}",
243
245
  dimmenu_abbrjoint: ": ",
244
246
  dimmenu_dimension: "{{dimension}}",
245
247
  dimmenu_hierarchy: "{{abbr}}",
246
248
  dimmenu_level: "{{abbr}}",
249
+ filter_mode: "Filter Mode",
250
+ filter_by: "Filter by {{name}}",
247
251
  error_no_cut_selected_detail: "You can add data filters based on selected drilldowns.",
248
252
  error_no_cut_selected_title: "No cuts added",
249
253
  error_no_dimension_selected_detail: "You must add at least one drilldown.",
@@ -1362,7 +1366,6 @@ function parseStateFromSearchParams(query) {
1362
1366
  const comparison = cond[0];
1363
1367
  const inputtedValue = cond[1];
1364
1368
  const interpretedValue = Number.parseFloat(cond[1]);
1365
- console.log("Entro parse", comparison, inputtedValue, interpretedValue);
1366
1369
  return [comparison, inputtedValue, interpretedValue];
1367
1370
  }
1368
1371
  }
@@ -1560,24 +1563,7 @@ function calcMaxMemberCount(query, params, dispatch) {
1560
1563
  });
1561
1564
  const memberLengths = query.getParam("drilldowns").map(
1562
1565
  (level) => Level.isLevel(level) ? drills[level.uniqueName] || ds.fetchMembers(level).then(async (members) => {
1563
- const { cube, name: name4, dimension, fullName, depth, properties, hierarchy, annotations, key } = level;
1564
- ({
1565
- cube: cube.name,
1566
- dimension: dimension.name,
1567
- fullName,
1568
- depth,
1569
- _type: "level",
1570
- name: name4,
1571
- uri: level._source.uri,
1572
- properties: properties.map((p) => ({
1573
- name: p.name,
1574
- annotations: p.annotations,
1575
- uri: p._source.uri,
1576
- _type: "property"
1577
- })),
1578
- hierarchy: hierarchy.name,
1579
- annotations
1580
- });
1566
+ const { dimension } = level;
1581
1567
  const drilldown = Object.values(params.drilldowns).find(
1582
1568
  (d) => d.uniqueName === level.uniqueName
1583
1569
  );
@@ -1717,7 +1703,7 @@ function willDownloadQuery(format2) {
1717
1703
  const dataURL = query.toString("logiclayer").replace(olapClient.datasource.serverUrl, "");
1718
1704
  return Promise.all([
1719
1705
  axios({ url: dataURL, responseType: "blob" }).then((response) => response.data),
1720
- calcMaxMemberCount(query, params).then((maxRows) => {
1706
+ calcMaxMemberCount(query, params, dispatch).then((maxRows) => {
1721
1707
  if (maxRows > 5e4) {
1722
1708
  dispatch(loadingActions.setLoadingMessage({ type: "HEAVY_QUERY", rows: maxRows }));
1723
1709
  }
@@ -1739,10 +1725,19 @@ function willExecuteQuery({ limit, offset } = {}) {
1739
1725
  const allParams = isPrefetch ? { ...params, pagiLimit: limit, pagiOffset: offset } : params;
1740
1726
  const { result: currentResult } = selectCurrentQueryItem(state);
1741
1727
  if (!isValidQuery(params)) return Promise.resolve();
1742
- return olapClient.getCube(params.cube).then((cube) => {
1728
+ return olapClient.getCube(params.cube).then(async (cube) => {
1743
1729
  const query = applyQueryParams(cube.query, allParams, { previewLimit });
1730
+ const axios = olapClient.datasource.axiosInstance;
1731
+ const dataURL = query.toString("logiclayer").replace(olapClient.datasource.serverUrl, "");
1744
1732
  return Promise.all([
1745
- olapClient.execQuery(query, endpoint),
1733
+ axios({ url: dataURL }).then((response) => {
1734
+ return {
1735
+ data: response.data,
1736
+ headers: { ...response.headers },
1737
+ query,
1738
+ status: response.status
1739
+ };
1740
+ }),
1746
1741
  calcMaxMemberCount(query, allParams, dispatch).then((maxRows) => {
1747
1742
  if (maxRows > 5e4) {
1748
1743
  dispatch(loadingActions.setLoadingMessage({ type: "HEAVY_QUERY", rows: maxRows }));
@@ -1751,19 +1746,20 @@ function willExecuteQuery({ limit, offset } = {}) {
1751
1746
  ]).then(
1752
1747
  (result) => {
1753
1748
  const [aggregation] = result;
1749
+ const { data, headers, status } = aggregation;
1754
1750
  !isPrefetch && dispatch(
1755
1751
  queriesActions.updateResult({
1756
- data: aggregation.data,
1757
- types: aggregation.data.length ? describeData(cube.toJSON(), params, aggregation.data) : currentResult.types,
1758
- headers: { ...aggregation.headers },
1752
+ data,
1753
+ types: (data == null ? void 0 : data.data.length) ? describeData(cube.toJSON(), params, data == null ? void 0 : data.data) : currentResult.types,
1754
+ headers: { ...headers },
1759
1755
  sourceCall: query.toSource(),
1760
- status: aggregation.status || 500,
1756
+ status: status || 500,
1761
1757
  url: query.toString(endpoint)
1762
1758
  })
1763
1759
  );
1764
1760
  return {
1765
- data: aggregation.data,
1766
- types: aggregation.data.length ? describeData(cube.toJSON(), params, aggregation.data) : currentResult.types
1761
+ data,
1762
+ types: (data == null ? void 0 : data.data.length) ? describeData(cube.toJSON(), params, data == null ? void 0 : data.data) : currentResult.types
1767
1763
  };
1768
1764
  },
1769
1765
  (error) => {
@@ -2183,40 +2179,41 @@ function IconChevronRight() {
2183
2179
  return /* @__PURE__ */ React10__default.createElement("svg", { width: "9", height: "13", viewBox: "0 0 7 11", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React10__default.createElement("path", { d: "M1 10L5.5 5.5L1 1", stroke: "black", strokeLinecap: "round" }));
2184
2180
  }
2185
2181
  function DataSetSVG() {
2186
- return /* @__PURE__ */ React10__default.createElement("svg", { width: "25", height: "25", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React10__default.createElement(
2187
- "path",
2188
- {
2189
- d: "M3.33325 5C3.33325 5.66304 4.03563 6.29893 5.28587 6.76777C6.53612 7.23661 8.23181 7.5 9.99992 7.5C11.768 7.5 13.4637 7.23661 14.714 6.76777C15.9642 6.29893 16.6666 5.66304 16.6666 5C16.6666 4.33696 15.9642 3.70107 14.714 3.23223C13.4637 2.76339 11.768 2.5 9.99992 2.5C8.23181 2.5 6.53612 2.76339 5.28587 3.23223C4.03563 3.70107 3.33325 4.33696 3.33325 5Z",
2190
- stroke: "#212529",
2191
- strokeLinecap: "round",
2192
- strokeLinejoin: "round"
2193
- }
2194
- ), /* @__PURE__ */ React10__default.createElement(
2195
- "path",
2196
- {
2197
- d: "M3.33325 5V10C3.33325 10.663 4.03563 11.2989 5.28587 11.7678C6.53612 12.2366 8.23181 12.5 9.99992 12.5C11.768 12.5 13.4637 12.2366 14.714 11.7678C15.9642 11.2989 16.6666 10.663 16.6666 10V5",
2198
- stroke: "#212529",
2199
- strokeLinecap: "round",
2200
- strokeLinejoin: "round"
2201
- }
2202
- ), /* @__PURE__ */ React10__default.createElement(
2203
- "path",
2204
- {
2205
- d: "M3.33325 10V15C3.33325 15.663 4.03563 16.2989 5.28587 16.7678C6.53612 17.2366 8.23181 17.5 9.99992 17.5C11.768 17.5 13.4637 17.2366 14.714 16.7678C15.9642 16.2989 16.6666 15.663 16.6666 15V10",
2206
- stroke: "#212529",
2207
- strokeLinecap: "round",
2208
- strokeLinejoin: "round"
2209
- }
2210
- ));
2211
- }
2212
- function HomeSVG() {
2213
- return /* @__PURE__ */ React10__default.createElement("svg", { width: "22", height: "24", viewBox: "0 0 16 18", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React10__default.createElement(
2214
- "path",
2182
+ return /* @__PURE__ */ React10__default.createElement(
2183
+ "svg",
2215
2184
  {
2216
- d: "M2 16H5V10H11V16H14V7L8 2.5L2 7V16ZM0 18V6L8 0L16 6V18H9V12H7V18H0Z",
2217
- fill: "#545454"
2218
- }
2219
- ));
2185
+ width: "25",
2186
+ height: "25",
2187
+ viewBox: "0 0 20 20",
2188
+ fill: "none",
2189
+ stroke: "currentColor",
2190
+ xmlns: "http://www.w3.org/2000/svg"
2191
+ },
2192
+ /* @__PURE__ */ React10__default.createElement(
2193
+ "path",
2194
+ {
2195
+ d: "M3.33325 5C3.33325 5.66304 4.03563 6.29893 5.28587 6.76777C6.53612 7.23661 8.23181 7.5 9.99992 7.5C11.768 7.5 13.4637 7.23661 14.714 6.76777C15.9642 6.29893 16.6666 5.66304 16.6666 5C16.6666 4.33696 15.9642 3.70107 14.714 3.23223C13.4637 2.76339 11.768 2.5 9.99992 2.5C8.23181 2.5 6.53612 2.76339 5.28587 3.23223C4.03563 3.70107 3.33325 4.33696 3.33325 5Z",
2196
+ strokeLinecap: "round",
2197
+ strokeLinejoin: "round"
2198
+ }
2199
+ ),
2200
+ /* @__PURE__ */ React10__default.createElement(
2201
+ "path",
2202
+ {
2203
+ d: "M3.33325 5V10C3.33325 10.663 4.03563 11.2989 5.28587 11.7678C6.53612 12.2366 8.23181 12.5 9.99992 12.5C11.768 12.5 13.4637 12.2366 14.714 11.7678C15.9642 11.2989 16.6666 10.663 16.6666 10V5",
2204
+ strokeLinecap: "round",
2205
+ strokeLinejoin: "round"
2206
+ }
2207
+ ),
2208
+ /* @__PURE__ */ React10__default.createElement(
2209
+ "path",
2210
+ {
2211
+ d: "M3.33325 10V15C3.33325 15.663 4.03563 16.2989 5.28587 16.7678C6.53612 17.2366 8.23181 17.5 9.99992 17.5C11.768 17.5 13.4637 17.2366 14.714 16.7678C15.9642 16.2989 16.6666 15.663 16.6666 15V10",
2212
+ strokeLinecap: "round",
2213
+ strokeLinejoin: "round"
2214
+ }
2215
+ )
2216
+ );
2220
2217
  }
2221
2218
  function StackSVG() {
2222
2219
  return /* @__PURE__ */ React10__default.createElement(
@@ -2455,6 +2452,11 @@ function TableFooter(props) {
2455
2452
  const { url } = result;
2456
2453
  const { copy, copied } = useClipboard({ timeout: 1e3 });
2457
2454
  const copyHandler = useCallback(() => copy(url), [url]);
2455
+ const totalRowCount = table.options.rowCount;
2456
+ const {
2457
+ pagination: { pageSize }
2458
+ } = table.getState();
2459
+ const showPagination = totalRowCount && Boolean(totalRowCount > pageSize);
2458
2460
  return /* @__PURE__ */ React10__default.createElement(Box, { w: "100%", sx: { flex: "0 0 70px" } }, /* @__PURE__ */ React10__default.createElement(
2459
2461
  Flex,
2460
2462
  {
@@ -2465,7 +2467,7 @@ function TableFooter(props) {
2465
2467
  gap: "sm"
2466
2468
  },
2467
2469
  /* @__PURE__ */ React10__default.createElement(CubeSource, null),
2468
- /* @__PURE__ */ React10__default.createElement(Group, { position: "right", spacing: "sm" }, /* @__PURE__ */ React10__default.createElement(Text, { c: "dimmed" }, t("results.count_rows", { n: result.data.length })), /* @__PURE__ */ React10__default.createElement(MRT_TablePagination, { table }), /* @__PURE__ */ React10__default.createElement(ApiAndCsvButtons, { copied, copyHandler, url }))
2470
+ /* @__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 }))
2469
2471
  ));
2470
2472
  }
2471
2473
  var ApiAndCsvButtons = (props) => {
@@ -2672,6 +2674,7 @@ function abbreviateFullName(nameParts, joint = "/") {
2672
2674
  }
2673
2675
  function AddColumnsDrawer() {
2674
2676
  const [opened, { open, close: close2 }] = useDisclosure(false);
2677
+ const { translate: t } = useTranslation();
2675
2678
  const theme = useMantineTheme();
2676
2679
  const smallerThanMd = useMediaQuery(`(max-width: ${theme.breakpoints.md})`);
2677
2680
  return /* @__PURE__ */ React10__default.createElement(React10__default.Fragment, null, /* @__PURE__ */ React10__default.createElement(
@@ -2680,8 +2683,8 @@ function AddColumnsDrawer() {
2680
2683
  opened,
2681
2684
  position: "right",
2682
2685
  onClose: close2,
2683
- title: /* @__PURE__ */ React10__default.createElement(Group, null, /* @__PURE__ */ React10__default.createElement(IconStack3, { size: "0.75rem" }), /* @__PURE__ */ React10__default.createElement(Text, { fw: 700 }, "Add Columns")),
2684
- styles: (t) => ({
2686
+ 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"))),
2687
+ styles: (t2) => ({
2685
2688
  inner: {
2686
2689
  position: "absolute",
2687
2690
  inset: 0
@@ -2690,7 +2693,7 @@ function AddColumnsDrawer() {
2690
2693
  background: "transparent"
2691
2694
  },
2692
2695
  content: {
2693
- backgroundColor: t.colorScheme === "dark" ? t.colors.dark[8] : t.colors.gray[1]
2696
+ backgroundColor: t2.colorScheme === "dark" ? t2.colors.dark[8] : t2.colors.gray[1]
2694
2697
  }
2695
2698
  }),
2696
2699
  overlayProps: {
@@ -2700,7 +2703,7 @@ function AddColumnsDrawer() {
2700
2703
  },
2701
2704
  /* @__PURE__ */ React10__default.createElement(MeasuresOptions, null),
2702
2705
  /* @__PURE__ */ React10__default.createElement(DrillDownOptions, null)
2703
- ), /* @__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: "0.75rem" }), onClick: open, m: "md", size: "xs" }, "Add Columns")));
2706
+ ), /* @__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"))));
2704
2707
  }
2705
2708
  function DrillDownOptions() {
2706
2709
  const locale = useSelector$1(selectLocale);
@@ -2712,7 +2715,7 @@ function DrillDownOptions() {
2712
2715
  cutItem.active = false;
2713
2716
  actions2.updateCut(cutItem);
2714
2717
  }, []);
2715
- const createHandler = useCallback(
2718
+ useCallback(
2716
2719
  (level) => {
2717
2720
  var _a;
2718
2721
  const drilldownItem = (_a = selectedDimensions.find((item) => item.uniqueName === level.uniqueName)) != null ? _a : buildDrilldown({ ...level });
@@ -2739,7 +2742,6 @@ function DrillDownOptions() {
2739
2742
  dimension,
2740
2743
  locale: locale.code,
2741
2744
  key: dimension.uri,
2742
- onItemSelect: createHandler,
2743
2745
  activeItems
2744
2746
  }
2745
2747
  )),
@@ -2862,9 +2864,10 @@ function LevelItem({ dimension, hierarchy, isSubMenu, level, locale, activeItems
2862
2864
  actions2.updateDrilldown({ ...currentDrilldown, active: !currentDrilldown.active });
2863
2865
  },
2864
2866
  checked,
2865
- label
2867
+ label,
2868
+ size: "xs"
2866
2869
  }
2867
- ), /* @__PURE__ */ React10__default.createElement(Group, null, /* @__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(StackSVG, null)))), activeFilter && /* @__PURE__ */ React10__default.createElement(Box, { pt: "md" }, /* @__PURE__ */ React10__default.createElement(
2870
+ ), /* @__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(
2868
2871
  MultiSelect,
2869
2872
  {
2870
2873
  sx: { flex: "1 1 100%" },
@@ -2889,14 +2892,14 @@ function LevelItem({ dimension, hierarchy, isSubMenu, level, locale, activeItems
2889
2892
  }
2890
2893
  )));
2891
2894
  }
2892
- function getFilterfnText(type) {
2895
+ function getFilterfnKey(type) {
2893
2896
  switch (type) {
2894
2897
  case "greaterThan":
2895
- return "Greater Than";
2898
+ return "GT";
2896
2899
  case "lessThan":
2897
- return "Less Than";
2900
+ return "LT";
2898
2901
  case "between":
2899
- return "Between";
2902
+ return "BT";
2900
2903
  default:
2901
2904
  return "Not Found";
2902
2905
  }
@@ -2986,7 +2989,8 @@ function MinMax({ filter, ...rest }) {
2986
2989
  }
2987
2990
  function FilterFnsMenu({ filter }) {
2988
2991
  const actions2 = useActions();
2989
- return /* @__PURE__ */ React10__default.createElement(React10__default.Fragment, null, /* @__PURE__ */ React10__default.createElement(Menu, { shadow: "md", width: 200 }, /* @__PURE__ */ React10__default.createElement(Menu.Target, null, /* @__PURE__ */ React10__default.createElement(ActionIcon, { size: "xs" }, /* @__PURE__ */ React10__default.createElement(IconSettings, null))), /* @__PURE__ */ React10__default.createElement(Menu.Dropdown, null, /* @__PURE__ */ React10__default.createElement(Menu.Label, null, "Filter Mode"), /* @__PURE__ */ React10__default.createElement(
2992
+ const { translate: t } = useTranslation();
2993
+ return /* @__PURE__ */ React10__default.createElement(React10__default.Fragment, null, /* @__PURE__ */ React10__default.createElement(Menu, { shadow: "md", width: 200 }, /* @__PURE__ */ React10__default.createElement(Menu.Target, null, /* @__PURE__ */ React10__default.createElement(ActionIcon, { size: "xs" }, /* @__PURE__ */ React10__default.createElement(IconSettings, null))), /* @__PURE__ */ React10__default.createElement(Menu.Dropdown, null, /* @__PURE__ */ React10__default.createElement(Menu.Label, null, t("params.filter_mode")), /* @__PURE__ */ React10__default.createElement(
2990
2994
  Menu.Item,
2991
2995
  {
2992
2996
  icon: /* @__PURE__ */ React10__default.createElement(IconMathGreater, { size: 14 }),
@@ -2995,7 +2999,7 @@ function FilterFnsMenu({ filter }) {
2995
2999
  actions2.updateFilter(buildFilter({ ...filter, ...conditions, active: false }));
2996
3000
  }
2997
3001
  },
2998
- "Greater Than"
3002
+ t("comparison.GT")
2999
3003
  ), /* @__PURE__ */ React10__default.createElement(
3000
3004
  Menu.Item,
3001
3005
  {
@@ -3005,7 +3009,7 @@ function FilterFnsMenu({ filter }) {
3005
3009
  actions2.updateFilter(buildFilter({ ...filter, ...conditions, active: false }));
3006
3010
  }
3007
3011
  },
3008
- "Less Than"
3012
+ t("comparison.LT")
3009
3013
  ), /* @__PURE__ */ React10__default.createElement(
3010
3014
  Menu.Item,
3011
3015
  {
@@ -3015,16 +3019,15 @@ function FilterFnsMenu({ filter }) {
3015
3019
  actions2.updateFilter(buildFilter({ ...filter, ...conditions, active: false }));
3016
3020
  }
3017
3021
  },
3018
- "Between"
3022
+ t("comparison.BT")
3019
3023
  ))));
3020
3024
  }
3021
3025
  function MeasuresOptions() {
3022
- const [activeFilter, setActiveFilter] = useState(false);
3023
- const { code: locale } = useSelector$1(selectLocale);
3026
+ useSelector$1(selectLocale);
3027
+ useTranslation();
3024
3028
  const itemMap = useSelector$1(selectMeasureMap);
3025
3029
  const filtersMap = useSelector$1(selectFilterMap);
3026
3030
  const filtersItems = useSelector$1(selectFilterItems);
3027
- useSelector$1(selectOlapMeasureMap);
3028
3031
  const measures = useSelector$1(selectOlapMeasureItems);
3029
3032
  const actions2 = useActions();
3030
3033
  function handlerCreateMeasure(data) {
@@ -3048,40 +3051,49 @@ function MeasuresOptions() {
3048
3051
  });
3049
3052
  return { measure, filter };
3050
3053
  });
3051
- }, [itemMap, measures, filtersMap, filtersItems, locale]);
3054
+ }, [itemMap, measures, filtersMap, filtersItems]);
3052
3055
  const activeItems = filteredItems.filter((f) => isActiveItem(f.measure));
3053
3056
  const options = filteredItems.map(({ measure, filter }) => {
3054
- const filterFn = getFilterFn(filter);
3055
- const text = getFilterfnText(filterFn);
3056
- const isBetween = filterFn === "between";
3057
- const checked = activeItems.map((active) => active.measure.name).includes(measure.name);
3058
- return /* @__PURE__ */ React10__default.createElement(Box, { key: measure.name }, /* @__PURE__ */ React10__default.createElement(Group, { mt: "sm", position: "apart" }, /* @__PURE__ */ React10__default.createElement(
3059
- Checkbox,
3060
- {
3061
- onChange: () => {
3062
- actions2.updateMeasure({ ...measure, active: !measure.active });
3063
- actions2.updateFilter({ ...filter, active: checked ? false : true });
3064
- },
3065
- checked,
3066
- label: measure.name
3067
- }
3068
- ), /* @__PURE__ */ React10__default.createElement(Group, null, /* @__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 })));
3057
+ return /* @__PURE__ */ React10__default.createElement(FilterItem4, { measure, filter, activeItems });
3069
3058
  });
3070
3059
  return options;
3071
3060
  }
3061
+ function FilterItem4({
3062
+ measure,
3063
+ filter,
3064
+ activeItems
3065
+ }) {
3066
+ const [activeFilter, setActiveFilter] = useState(false);
3067
+ const { translate: t } = useTranslation();
3068
+ const filterFn = getFilterFn(filter);
3069
+ const text = t(`comparison.${getFilterfnKey(filterFn)}`);
3070
+ const isBetween = filterFn === "between";
3071
+ const checked = activeItems.map((active) => active.measure.name).includes(measure.name);
3072
+ const actions2 = useActions();
3073
+ return /* @__PURE__ */ React10__default.createElement(Box, { key: measure.name }, /* @__PURE__ */ React10__default.createElement(Group, { mt: "sm", position: "apart" }, /* @__PURE__ */ React10__default.createElement(
3074
+ Checkbox,
3075
+ {
3076
+ onChange: () => {
3077
+ actions2.updateMeasure({ ...measure, active: !measure.active });
3078
+ actions2.updateFilter({ ...filter, active: checked ? false : true });
3079
+ },
3080
+ checked,
3081
+ label: measure.name,
3082
+ size: "xs"
3083
+ }
3084
+ ), /* @__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 })));
3085
+ }
3072
3086
  var DrawerMenu_default = AddColumnsDrawer;
3073
3087
  var removeColumn = (actions2, entity, measures, drilldowns) => {
3074
3088
  if (entity._type === "measure") {
3075
3089
  if (entity.name) {
3076
- const measure = Object.values(measures).find((d) => d.name === entity.name);
3090
+ const measure = measures.find((d) => d.name === entity.name);
3077
3091
  measure && actions2.updateMeasure({ ...measure, active: false });
3078
- actions2.willRequestQuery();
3079
3092
  }
3080
3093
  }
3081
3094
  if (entity._type === "level") {
3082
- const drilldown = Object.values(drilldowns).find((d) => d.uniqueName === (entity == null ? void 0 : entity.uniqueName));
3095
+ const drilldown = drilldowns.find((d) => d.uniqueName === (entity == null ? void 0 : entity.uniqueName));
3083
3096
  drilldown && actions2.updateDrilldown({ ...drilldown, active: false });
3084
- actions2.willRequestQuery();
3085
3097
  }
3086
3098
  };
3087
3099
  function showTrashIcon(columns, type) {
@@ -3105,45 +3117,10 @@ var getEntityText = (entityType) => {
3105
3117
  return "";
3106
3118
  }
3107
3119
  };
3108
- var getColumnFilterOption = (entityType) => {
3109
- switch (entityType) {
3110
- case "measure":
3111
- return {
3112
- columnFilterModeOptions: ["between", "greaterThan", "lessThan"]
3113
- };
3114
- case "level":
3115
- return { columnFilterModeOptions: true };
3116
- default:
3117
- return { columnFilterModeOptions: true };
3118
- }
3119
- };
3120
- function getMemberFilterFnTypes(member) {
3121
- return {
3122
- value: String(member.key),
3123
- label: member.caption ? `${member.caption} ${member.key}` : member.name
3124
- };
3125
- }
3126
- function getMantineFilterMultiSelectProps(isId, isNumeric2, range, entity, drilldowns, columnKey, types) {
3120
+ function getMantineFilterMultiSelectProps(isId, isNumeric, range) {
3127
3121
  let result = {};
3128
- const filterVariant = !isId && !isNumeric2 && (!range || range && range[1] - range[0] <= 100) ? "multi-select" : "text";
3122
+ const filterVariant = !isId && !isNumeric && (!range || range && range[1] - range[0] <= 100) ? "multi-select" : "text";
3129
3123
  result = Object.assign({}, result, { filterVariant });
3130
- if (result.filterVariant === "multi-select") {
3131
- if (entity._type === "level") {
3132
- const dd = Object.keys(drilldowns).reduce(
3133
- (prev, key) => ({ ...prev, [drilldowns[key].uniqueName]: drilldowns[key] }),
3134
- {}
3135
- );
3136
- const drilldwonData = dd[entity.uniqueName];
3137
- if (drilldwonData && drilldwonData.members) {
3138
- result = Object.assign({}, result, {
3139
- mantineFilterMultiSelectProps: {
3140
- data: drilldwonData.members.map(getMemberFilterFnTypes),
3141
- placeholder: columnKey
3142
- }
3143
- });
3144
- }
3145
- }
3146
- }
3147
3124
  return result;
3148
3125
  }
3149
3126
  function getSortIcon(value, entityType) {
@@ -3187,41 +3164,87 @@ function getFiltersConditions(fn, value) {
3187
3164
  ]);
3188
3165
  return (_a = comparisonMap.get(fn)) == null ? void 0 : _a(value);
3189
3166
  }
3190
- function useTableData({ offset, limit, columns, filters, cuts }) {
3167
+ function useTableData({ offset, limit, columns, filters, cuts, pagination }) {
3191
3168
  const normalizedFilters = filters.map((filter) => ({
3192
3169
  id: filter.measure,
3193
- value: getFilterValue(filter),
3194
- fn: getFilterFn(filter)
3170
+ value: getFilterValue(filter)
3171
+ // fn: getFilterFn(filter)
3195
3172
  }));
3196
3173
  const normalizedCuts = cuts.map((cut) => ({ id: cut.uniqueName, members: cut.members }));
3197
3174
  const filterKey = JSON.stringify(normalizedFilters);
3198
3175
  const cutKey = JSON.stringify(normalizedCuts);
3199
3176
  const actions2 = useActions();
3200
- const [filterKeydebouced, setDebouncedTerm] = useState("");
3201
- const page = offset;
3177
+ const columnsStr = JSON.stringify(columns.sort());
3178
+ const page = pagination.pageIndex;
3179
+ const [filterKeydebouced, setDebouncedTerm] = useState([
3180
+ columnsStr,
3181
+ filterKey,
3182
+ cutKey,
3183
+ page
3184
+ ]);
3202
3185
  useEffect(() => {
3203
3186
  const handler = debounce(() => {
3204
- const term = [limit, offset, ...columns.sort(), filterKey, cutKey, page];
3187
+ const term = [columnsStr, filterKey, cutKey, page];
3205
3188
  setDebouncedTerm(term);
3206
3189
  }, 700);
3207
3190
  handler();
3208
- return () => {
3209
- handler.cancel();
3210
- };
3211
- }, [...columns, offset, filterKey, cutKey, page]);
3191
+ return () => handler.cancel();
3192
+ }, [columnsStr, offset, filterKey, cutKey, page]);
3212
3193
  return useQuery({
3213
3194
  queryKey: ["table", filterKeydebouced],
3214
3195
  queryFn: () => {
3215
3196
  return actions2.willExecuteQuery().then((res) => {
3216
3197
  const { data, types } = res;
3217
- return { data: data != null ? data : [], types };
3198
+ const { data: tableData, page: page2 } = data;
3199
+ return { data: tableData != null ? tableData : [], types, page: page2 };
3218
3200
  });
3219
3201
  },
3220
3202
  staleTime: 3e5,
3221
3203
  enabled: !!filterKeydebouced
3222
- // placeholderData: keepPreviousData
3223
3204
  });
3224
3205
  }
3206
+ function usePrefetch({
3207
+ data,
3208
+ isPlaceholderData,
3209
+ limit,
3210
+ offset,
3211
+ totalRowCount,
3212
+ columns,
3213
+ cuts,
3214
+ filters,
3215
+ pagination
3216
+ }) {
3217
+ const queryClient2 = useQueryClient();
3218
+ const actions2 = useActions();
3219
+ const page = pagination.pageIndex + 1;
3220
+ const hasMore = page * pagination.pageSize <= totalRowCount;
3221
+ const off = page * pagination.pageSize;
3222
+ const normalizedFilters = filters.map((filter) => ({
3223
+ id: filter.measure,
3224
+ value: getFilterValue(filter)
3225
+ // fn: getFilterFn(filter)
3226
+ }));
3227
+ const normalizedCuts = cuts.map((cut) => ({ id: cut.uniqueName, members: cut.members }));
3228
+ const filterKey = JSON.stringify(normalizedFilters);
3229
+ const cutKey = JSON.stringify(normalizedCuts);
3230
+ const columnsStr = JSON.stringify(columns.sort());
3231
+ const key = [columnsStr, filterKey, cutKey, page];
3232
+ React10__default.useEffect(() => {
3233
+ if (!isPlaceholderData && hasMore) {
3234
+ queryClient2.prefetchQuery({
3235
+ queryKey: ["table", key],
3236
+ queryFn: () => {
3237
+ return actions2.willExecuteQuery({ offset: off, limit }).then((res) => {
3238
+ const { data: data2, types } = res;
3239
+ const { data: tableData, page: page2 } = data2;
3240
+ return { data: tableData != null ? tableData : [], types, page: page2 };
3241
+ });
3242
+ },
3243
+ staleTime: 3e5
3244
+ });
3245
+ }
3246
+ }, [data, limit, offset, page, isPlaceholderData, key, queryClient2, hasMore, off]);
3247
+ }
3225
3248
  function useTable({
3226
3249
  cube,
3227
3250
  result,
@@ -3230,24 +3253,12 @@ function useTable({
3230
3253
  ...mantineTableProps
3231
3254
  }) {
3232
3255
  const { types } = result;
3233
- const { measures, drilldowns } = useSelector$1(selectCurrentQueryParams);
3234
3256
  const filterItems = useSelector$1(selectFilterItems);
3235
- const finalUniqueKeys = [
3236
- ...Object.keys(measures).reduce((prev, curr) => {
3237
- const measure = measures[curr];
3238
- if (measure.active) {
3239
- return [...prev, curr];
3240
- }
3241
- return prev;
3242
- }, []),
3243
- ...Object.keys(drilldowns).reduce((prev, curr) => {
3244
- const dd = drilldowns[curr];
3245
- if (dd.active) {
3246
- return [...prev, curr];
3247
- }
3248
- return prev;
3249
- }, [])
3250
- ];
3257
+ const filtersMap = useSelector$1(selectFilterMap);
3258
+ const measuresOlap = useSelector$1(selectOlapMeasureItems);
3259
+ const measuresMap = useSelector$1(selectMeasureMap);
3260
+ const drilldowns = useSelector$1(selectDrilldownItems);
3261
+ const measures = useSelector$1(selectMeasureItems);
3251
3262
  const actions2 = useActions();
3252
3263
  const itemsCuts = useSelector$1(selectCutItems);
3253
3264
  const { limit, offset } = useSelector$1(selectPaginationParams);
@@ -3255,18 +3266,58 @@ function useTable({
3255
3266
  pageIndex: offset,
3256
3267
  pageSize: limit
3257
3268
  });
3269
+ const finalUniqueKeys = useMemo(
3270
+ () => [
3271
+ ...measures.map((m) => m.active ? m.name : null),
3272
+ ...drilldowns.map((d) => d.active ? d.uniqueName : null)
3273
+ ].filter((a) => a !== null),
3274
+ [measures, drilldowns]
3275
+ );
3276
+ function handlerCreateMeasure(data2) {
3277
+ const measure = buildMeasure(data2);
3278
+ actions2.updateMeasure(measure);
3279
+ return measure;
3280
+ }
3281
+ function handlerCreateFilter(data2) {
3282
+ const filter = buildFilter(data2);
3283
+ actions2.updateFilter(filter);
3284
+ return filter;
3285
+ }
3286
+ useMemo(() => {
3287
+ return filterMap(measuresOlap, (m) => {
3288
+ const measure = measuresMap[m.name] || handlerCreateMeasure({ ...m, active: false });
3289
+ const foundFilter = filtersMap[m.name] || filterItems.find((f) => f.measure === measure.name);
3290
+ const filter = foundFilter || handlerCreateFilter({
3291
+ measure: measure.name,
3292
+ active: false,
3293
+ key: measure.name
3294
+ });
3295
+ return { measure, filter };
3296
+ });
3297
+ }, [measuresMap, measuresOlap, filtersMap, filterItems]);
3258
3298
  const { isLoading, isFetching, isError, data, isPlaceholderData } = useTableData({
3259
3299
  offset,
3260
3300
  limit,
3261
3301
  columns: finalUniqueKeys,
3262
3302
  filters: filterItems.filter(isActiveItem),
3263
- cuts: itemsCuts.filter(isActiveCut)
3303
+ cuts: itemsCuts.filter(isActiveCut),
3304
+ pagination
3264
3305
  });
3265
3306
  const tableData = (data == null ? void 0 : data.data) || [];
3266
3307
  const tableTypes = (data == null ? void 0 : data.types) || types;
3308
+ const totalRowCount = data == null ? void 0 : data.page.total;
3267
3309
  const finalKeys = Object.values(tableTypes).filter((t2) => !t2.isId).filter(columnFilter).sort(columnSorting);
3268
- const totalRowCount = result.data.length === limit ? limit * 10 : result.data.length;
3269
- const fetchedTableData = tableData != null ? tableData : [];
3310
+ usePrefetch({
3311
+ data: tableData,
3312
+ isPlaceholderData,
3313
+ offset,
3314
+ limit,
3315
+ totalRowCount,
3316
+ columns: finalUniqueKeys,
3317
+ filters: filterItems.filter(isActiveItem),
3318
+ cuts: itemsCuts.filter(isActiveCut),
3319
+ pagination
3320
+ });
3270
3321
  useEffect(() => {
3271
3322
  actions2.updatePagination({
3272
3323
  limit: pagination.pageSize,
@@ -3299,19 +3350,11 @@ function useTable({
3299
3350
  range,
3300
3351
  isId
3301
3352
  } = column;
3302
- const isNumeric2 = valueType === "number" && columnKey !== "Year";
3303
- const formatterKey = getFormatterKey(columnKey) || (isNumeric2 ? "Decimal" : "identity");
3353
+ const isNumeric = valueType === "number" && columnKey !== "Year";
3354
+ const formatterKey = getFormatterKey(columnKey) || (isNumeric ? "Decimal" : "identity");
3304
3355
  const formatter = getFormatter(formatterKey);
3305
- const filterOption = getColumnFilterOption(entityType);
3306
- const mantineFilterVariantObject = getMantineFilterMultiSelectProps(
3307
- isId,
3308
- isNumeric2,
3309
- range,
3310
- entity,
3311
- drilldowns,
3312
- columnKey);
3356
+ const mantineFilterVariantObject = getMantineFilterMultiSelectProps(isId, isNumeric, range);
3313
3357
  return {
3314
- ...filterOption,
3315
3358
  ...mantineFilterVariantObject,
3316
3359
  entityType,
3317
3360
  header,
@@ -3335,7 +3378,7 @@ function useTable({
3335
3378
  onClick: column2.getToggleSortingHandler()
3336
3379
  },
3337
3380
  getSortIcon(column2.getIsSorted(), entityType)
3338
- )), /* @__PURE__ */ React10__default.createElement(Text, { ml: rem(30), size: "sm", color: "dimmed", fw: "normal" }, getEntityText(entityType))), /* @__PURE__ */ React10__default.createElement(
3381
+ ))), /* @__PURE__ */ React10__default.createElement(
3339
3382
  CustomActionIcon_default,
3340
3383
  {
3341
3384
  label: `At least one ${getEntityText(entityType)} is required.`,
@@ -3351,10 +3394,10 @@ function useTable({
3351
3394
  },
3352
3395
  formatter,
3353
3396
  formatterKey,
3354
- id: (_a = entity.fullName) != null ? _a : entity.name,
3397
+ id: (_a = entity.uniqueName) != null ? _a : entity.name,
3355
3398
  dataType: valueType,
3356
3399
  accessorFn: (item) => item[columnKey],
3357
- Cell: isNumeric2 ? ({ cell }) => formatter(cell.getValue()) : ({ cell, renderedCellValue, row }) => {
3400
+ Cell: isNumeric ? ({ cell }) => formatter(cell.getValue()) : ({ cell, renderedCellValue, row }) => {
3358
3401
  const cellId = row.original[`${cell.column.id} ID`];
3359
3402
  return /* @__PURE__ */ React10__default.createElement(Flex, { justify: "space-between", sx: { width: "100%", maxWidth: 400 }, gap: "sm" }, /* @__PURE__ */ React10__default.createElement(
3360
3403
  Text,
@@ -3450,7 +3493,7 @@ function useTable({
3450
3493
  );
3451
3494
  const table = useMantineReactTable({
3452
3495
  columns,
3453
- data: fetchedTableData,
3496
+ data: tableData,
3454
3497
  onPaginationChange: setPagination,
3455
3498
  enableHiding: false,
3456
3499
  manualFiltering: true,
@@ -3466,16 +3509,16 @@ function useTable({
3466
3509
  ...constTableProps,
3467
3510
  ...mantineTableProps
3468
3511
  });
3469
- return { table, isError, isLoading };
3512
+ return { table, isError, isLoading, data: tableData };
3470
3513
  }
3471
- function TableView({ table, result, isError, isLoading }) {
3514
+ function TableView({ table, result, isError, isLoading, data }) {
3472
3515
  const isData = Boolean(table.getRowModel().rows.length);
3473
3516
  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(
3474
- Box,
3517
+ ScrollArea,
3475
3518
  {
3519
+ h: isData ? "100%" : "auto",
3476
3520
  sx: {
3477
3521
  flex: "1 1 auto",
3478
- height: isData ? "100%" : "auto",
3479
3522
  position: "relative",
3480
3523
  overflow: "scroll"
3481
3524
  }
@@ -3505,11 +3548,11 @@ function TableView({ table, result, isError, isLoading }) {
3505
3548
  table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ React10__default.createElement(Box, { component: "tr", key: headerGroup.id, sx: { fontWeight: "normal" } }, headerGroup.headers.map((header) => {
3506
3549
  var _a;
3507
3550
  const column = table.getColumn(header.id);
3508
- const isNumeric2 = column.columnDef.dataType === "number";
3551
+ const isNumeric = column.columnDef.dataType === "number";
3509
3552
  const isRowIndex = column.id === "#";
3510
3553
  const base = (theme) => ({
3511
3554
  backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[7] : theme.colors.gray[0],
3512
- align: isNumeric2 ? "right" : "left",
3555
+ align: isNumeric ? "right" : "left",
3513
3556
  height: 60,
3514
3557
  paddingBottom: 10,
3515
3558
  minWidth: 210,
@@ -3538,7 +3581,7 @@ function TableView({ table, result, isError, isLoading }) {
3538
3581
  (_a = header.column.columnDef.Header) != null ? _a : header.column.columnDef.header,
3539
3582
  header.getContext()
3540
3583
  ),
3541
- !isRowIndex && /* @__PURE__ */ React10__default.createElement(ColumnFilterCell, { isNumeric: isNumeric2, header, table })
3584
+ !isRowIndex && /* @__PURE__ */ React10__default.createElement(ColumnFilterCell, { isNumeric, header, table })
3542
3585
  );
3543
3586
  })))
3544
3587
  ),
@@ -3553,33 +3596,34 @@ function TableView({ table, result, isError, isLoading }) {
3553
3596
  )))))
3554
3597
  ),
3555
3598
  !isData && !isError && !isLoading && /* @__PURE__ */ React10__default.createElement(NoRecords, null)
3556
- ), /* @__PURE__ */ React10__default.createElement(MRT_ToolbarAlertBanner, { stackAlertBanner: true, table }), /* @__PURE__ */ React10__default.createElement(TableFooter_default, { table, result })));
3599
+ ), /* @__PURE__ */ React10__default.createElement(MRT_ToolbarAlertBanner, { stackAlertBanner: true, table }), /* @__PURE__ */ React10__default.createElement(TableFooter_default, { table, data, result })));
3557
3600
  }
3558
3601
  var ColumnFilterCell = ({
3559
3602
  header,
3560
- table,
3561
- isNumeric: isNumeric2
3603
+ isNumeric
3562
3604
  }) => {
3563
3605
  const filterVariant = header.column.columnDef.filterVariant;
3564
3606
  const isMulti = filterVariant === "multi-select";
3565
3607
  if (isMulti) {
3566
3608
  return /* @__PURE__ */ React10__default.createElement(MultiFilter, { header });
3567
3609
  }
3568
- if (isNumeric2) {
3610
+ if (isNumeric) {
3569
3611
  return /* @__PURE__ */ React10__default.createElement(NumericFilter, { header });
3570
3612
  }
3571
3613
  };
3572
3614
  function NumericFilter({ header }) {
3573
3615
  const filters = useSelector$1(selectFilterItems);
3616
+ const { translate: t } = useTranslation();
3574
3617
  const filter = filters.find((f) => f.measure === header.column.id);
3575
3618
  if (filter) {
3576
3619
  const filterFn = getFilterFn(filter);
3577
- const text = getFilterfnText(filterFn);
3620
+ const text = t(`comparison.${getFilterfnKey(filterFn)}`);
3578
3621
  const isBetween = filterFn === "between";
3579
3622
  return /* @__PURE__ */ React10__default.createElement(Flex, { gap: "xs", style: { fontWeight: "normal" } }, /* @__PURE__ */ React10__default.createElement(Box, { sx: { flex: "1 1 auto" } }, isBetween ? /* @__PURE__ */ React10__default.createElement(MinMax, { filter, hideControls: true }) : /* @__PURE__ */ React10__default.createElement(NumberInputComponent, { text, filter })), /* @__PURE__ */ React10__default.createElement(Box, { sx: { alignSelf: "flex-end" } }, /* @__PURE__ */ React10__default.createElement(FilterFnsMenu, { filter })));
3580
3623
  }
3581
3624
  }
3582
3625
  function MultiFilter({ header }) {
3626
+ const { translate: t } = useTranslation();
3583
3627
  const cutItems = useSelector$1(selectCutItems);
3584
3628
  const drilldownItems = useSelector$1(selectDrilldownItems);
3585
3629
  const label = header.column.id;
@@ -3599,11 +3643,11 @@ function MultiFilter({ header }) {
3599
3643
  onChange: (value) => {
3600
3644
  updatecutHandler({ ...cut, active: true }, value);
3601
3645
  },
3602
- placeholder: `Filter by ${label}`,
3646
+ placeholder: t("params.filter_by", { name: label }),
3603
3647
  value: cut.members || [],
3604
3648
  data: drilldown.members.map((m) => ({
3605
3649
  value: String(m.key),
3606
- label: m.caption ? `${m.caption} ${m.key}` : m.name
3650
+ label: m.caption ? `${m.caption} (${m.key})` : m.name
3607
3651
  })),
3608
3652
  clearButtonProps: { "aria-label": "Clear selection" },
3609
3653
  clearable: true,
@@ -3841,7 +3885,7 @@ function SuccessResult(props) {
3841
3885
  const { previewLimit, actions: actions2 } = useSettings();
3842
3886
  const queryItem = useSelector$1(selectCurrentQueryItem);
3843
3887
  const isPreviewMode = useSelector$1(selectIsPreviewMode);
3844
- const { table, isError, isLoading } = useTable({ cube, result });
3888
+ const { table, isError, isLoading, data } = useTable({ cube, result });
3845
3889
  const fullscreen = useFullscreen();
3846
3890
  const [CurrentComponent, panelKey, panelMeta] = useMemo(() => {
3847
3891
  const currentPanel = queryItem.panel || `${panels[0].key}-`;
@@ -3873,7 +3917,8 @@ function SuccessResult(props) {
3873
3917
  result,
3874
3918
  table,
3875
3919
  isError,
3876
- isLoading
3920
+ isLoading,
3921
+ data
3877
3922
  }
3878
3923
  )))))));
3879
3924
  }
@@ -4177,12 +4222,13 @@ function SideBar(props) {
4177
4222
  id: "dex-sidebar",
4178
4223
  py: "md",
4179
4224
  sx: (t2) => ({
4180
- height: "calc(100vh - 75px)",
4225
+ height: "calc(100vh - 50px)",
4181
4226
  backgroundColor: t2.colorScheme === "dark" ? t2.colors.dark[8] : t2.colors.gray[1],
4182
4227
  boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
4183
4228
  maxWidth: expanded ? 300 : 54,
4184
4229
  padding: 0,
4185
4230
  zIndex: 99,
4231
+ boxSizing: "border-box",
4186
4232
  [t2.fn.smallerThan("md")]: {
4187
4233
  position: "absolute",
4188
4234
  width: expanded ? 300 : 54,
@@ -4333,10 +4379,49 @@ init_esm_shims();
4333
4379
 
4334
4380
  // src/components/Results.tsx
4335
4381
  init_esm_shims();
4382
+
4383
+ // src/hooks/useSelectCube.tsx
4384
+ init_esm_shims();
4385
+ function useSelectCube(onSelectCube) {
4386
+ const { updateMeasure, updateCut, updateDrilldown, willFetchMembers: willFetchMembers2 } = useActions();
4387
+ const createCutHandler2 = React10__default.useCallback((level) => {
4388
+ const cutItem = buildCut({ ...level });
4389
+ cutItem.active = false;
4390
+ updateCut(cutItem);
4391
+ }, []);
4392
+ const addDrilldown = useCallback((level, dimensions) => {
4393
+ const drilldownItem = buildDrilldown(level);
4394
+ createCutHandler2(level);
4395
+ updateDrilldown(drilldownItem);
4396
+ return willFetchMembers2({ ...level, level: level.name }).then((members) => {
4397
+ const dimension = dimensions.find((dim) => dim.name === level.dimension);
4398
+ if (!dimension) return;
4399
+ return updateDrilldown({
4400
+ ...drilldownItem,
4401
+ dimType: dimension.dimensionType,
4402
+ memberCount: members.length,
4403
+ members
4404
+ });
4405
+ });
4406
+ }, []);
4407
+ return (item, subtopic) => () => onSelectCube(item, subtopic).then(({ cube, measures, dimensions }) => {
4408
+ const [measure] = Object.values(measures);
4409
+ const drilldowns = deriveDrilldowns(dimensions);
4410
+ if (measure && drilldowns.length > 0) {
4411
+ updateMeasure({ ...measure, active: true });
4412
+ for (const level of drilldowns) {
4413
+ addDrilldown(level, dimensions);
4414
+ }
4415
+ }
4416
+ });
4417
+ }
4418
+
4419
+ // src/components/Results.tsx
4336
4420
  function Results(props) {
4337
4421
  const { onSelectCube, graph, selectedItem, locale, getCube: getCube2, isSelected: isSelected2 } = props;
4338
4422
  const { classes } = useStyles3();
4339
4423
  const { setExpanded, setInput, map } = useSideBar();
4424
+ const callback = useSelectCube(onSelectCube);
4340
4425
  const result = [];
4341
4426
  if (map) {
4342
4427
  for (let [key, items] of map) {
@@ -4351,7 +4436,7 @@ function Results(props) {
4351
4436
  fz: "xs",
4352
4437
  className: isSelected2(selectedItem, cube) ? `${classes.link} ${classes.linkActive}` : classes.link,
4353
4438
  onClick: () => {
4354
- onSelectCube(item, subtopic);
4439
+ callback(item, subtopic)();
4355
4440
  setExpanded(false);
4356
4441
  setInput("");
4357
4442
  }
@@ -4604,28 +4689,8 @@ function CubeButton({
4604
4689
  locale,
4605
4690
  parent
4606
4691
  }) {
4607
- const { updateMeasure, updateCut, updateDrilldown, willFetchMembers: willFetchMembers2 } = useActions();
4692
+ const callback = useSelectCube(onSelectCube);
4608
4693
  const { classes } = useStyles3();
4609
- const createCutHandler2 = React10__default.useCallback((level) => {
4610
- const cutItem = buildCut({ ...level });
4611
- cutItem.active = false;
4612
- updateCut(cutItem);
4613
- }, []);
4614
- const addDrilldown = useCallback((level, dimensions) => {
4615
- const drilldownItem = buildDrilldown(level);
4616
- createCutHandler2(level);
4617
- updateDrilldown(drilldownItem);
4618
- return willFetchMembers2({ ...level, level: level.name }).then((members) => {
4619
- const dimension = dimensions.find((dim) => dim.name === level.dimension);
4620
- if (!dimension) return;
4621
- return updateDrilldown({
4622
- ...drilldownItem,
4623
- dimType: dimension.dimensionType,
4624
- memberCount: members.length,
4625
- members
4626
- });
4627
- });
4628
- }, []);
4629
4694
  const table = item;
4630
4695
  const subtopic = parent != null ? parent : "";
4631
4696
  return /* @__PURE__ */ React10__default.createElement(
@@ -4642,18 +4707,7 @@ function CubeButton({
4642
4707
  background: isSelected(selectedItem, getCube(graph.items, table, subtopic, locale)) ? t.fn.primaryColor() : t.colorScheme === "dark" ? t.colors.dark[6] : t.colors.gray[3],
4643
4708
  overflow: "hidden"
4644
4709
  }),
4645
- onClick: () => {
4646
- onSelectCube(item, subtopic).then(({ cube, measures, dimensions }) => {
4647
- const [measure] = Object.values(measures);
4648
- const drilldowns = deriveDrilldowns(dimensions);
4649
- if (measure && drilldowns.length > 0) {
4650
- updateMeasure({ ...measure, active: true });
4651
- for (const level of drilldowns) {
4652
- addDrilldown(level, dimensions);
4653
- }
4654
- }
4655
- });
4656
- }
4710
+ onClick: callback(item, subtopic)
4657
4711
  },
4658
4712
  item
4659
4713
  );
@@ -4765,7 +4819,7 @@ function ExplorerContent(props) {
4765
4819
  const SplashComponent = props.splash;
4766
4820
  return SplashComponent ? /* @__PURE__ */ React10__default.createElement(SplashComponent, { translation }) : /* @__PURE__ */ React10__default.createElement(Center, { h: "100%", sx: { flex: 1 } }, /* @__PURE__ */ React10__default.createElement(AnimatedCube, null));
4767
4821
  }, [props.splash]);
4768
- return /* @__PURE__ */ React10__default.createElement("div", { className: classes.container }, /* @__PURE__ */ React10__default.createElement(Header, { height: { base: 50 }, p: "md" }, /* @__PURE__ */ React10__default.createElement("div", { style: { display: "flex", alignItems: "center", height: "100%", padding: 5 } }, /* @__PURE__ */ React10__default.createElement(HomeSVG, null))), /* @__PURE__ */ React10__default.createElement("div", { className: classes.root }, /* @__PURE__ */ React10__default.createElement(AppProviders, null, /* @__PURE__ */ React10__default.createElement(SideBarProvider, null, /* @__PURE__ */ React10__default.createElement(SideBar_default, null, /* @__PURE__ */ React10__default.createElement(SideBarItem, null, /* @__PURE__ */ React10__default.createElement(ParamsExplorer_default, null)))), /* @__PURE__ */ React10__default.createElement(ExplorerResults, { className: classes.flexCol, panels: props.panels, splash }))));
4822
+ return /* @__PURE__ */ React10__default.createElement("div", { className: classes.container }, /* @__PURE__ */ React10__default.createElement("div", { className: classes.root }, /* @__PURE__ */ React10__default.createElement(AppProviders, null, /* @__PURE__ */ React10__default.createElement(SideBarProvider, null, /* @__PURE__ */ React10__default.createElement(SideBar_default, null, /* @__PURE__ */ React10__default.createElement(SideBarItem, null, /* @__PURE__ */ React10__default.createElement(ParamsExplorer_default, null)))), /* @__PURE__ */ React10__default.createElement(ExplorerResults, { className: classes.flexCol, panels: props.panels, splash }))));
4769
4823
  }
4770
4824
 
4771
4825
  // src/components/PivotView.tsx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datawheel/data-explorer",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "exports": {
5
5
  ".": {
6
6
  "import": "./dist/main.js"
@@ -37,6 +37,8 @@
37
37
  "postcss-modules": "^6.0.0",
38
38
  "react-redux": "^7.0.0",
39
39
  "react-viewport-list": "^3.0.0",
40
+ "stylis": "^4.3.4",
41
+ "stylis-plugin-rtl": "^2.1.1",
40
42
  "yn": "^5.0.0"
41
43
  },
42
44
  "peerDependencies": {