@datawheel/data-explorer 0.2.9 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +130 -18
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { keyframes, createStyles, Select, rem, Flex, Title, Text, Group, Button, Input, Box, Stack, SimpleGrid, ScrollArea, LoadingOverlay, Table, MultiSelect, Center, NumberInput, Menu, ActionIcon, UnstyledButton, Alert, Loader, Container, Modal, useMantineTheme, MantineProvider, Paper, useComponentDefaultProps, Anchor, Tabs, Switch, ThemeIcon, Tooltip, CloseButton, Drawer, Divider, Checkbox, packSx, Affix, Accordion, Popover } from '@mantine/core';
|
|
2
2
|
import { useClipboard, useClickOutside, useFullscreen, useDebouncedState, useMediaQuery, useDisclosure } from '@mantine/hooks';
|
|
3
|
-
import { IconWorld, IconExternalLink, IconClipboard, IconSettings, IconMathGreater, IconMathLower, IconArrowsLeftRight, IconAlertCircle, IconAlertTriangle, IconCopy, IconDownload, IconDotsVertical, IconArrowRight, IconArrowLeft, IconArrowsMinimize, IconArrowsMaximize, IconTrash, IconInfoCircleFilled, IconSearch, IconPhotoDown, IconVectorTriangle, IconArrowsSort, IconSortDescendingNumbers, IconSortDescendingLetters, IconSortAscendingNumbers, IconSortAscendingLetters, IconPlus, IconStack3, IconFilterOff, IconFilter, IconBox, IconClock, IconHelpCircle, IconLanguage } from '@tabler/icons-react';
|
|
3
|
+
import { IconWorld, IconExternalLink, IconClipboard, IconSettings, IconMathGreater, IconMathLower, IconArrowsLeftRight, IconAlertCircle, IconAlertTriangle, IconCopy, IconDownload, IconDotsVertical, IconArrowRight, IconArrowLeft, IconArrowsMinimize, IconArrowsMaximize, IconTrash, IconInfoCircleFilled, IconSearch, IconPhotoDown, IconVectorTriangle, IconArrowsSort, IconSortDescendingNumbers, IconSortDescendingLetters, IconSortAscendingNumbers, IconSortAscendingLetters, IconPlus, IconStack3, IconFilterOff, IconFilter, IconAdjustments, IconBox, IconClock, IconHelpCircle, IconLanguage } from '@tabler/icons-react';
|
|
4
4
|
import * as React13 from 'react';
|
|
5
5
|
import React13__default, { createContext, forwardRef, useMemo, useCallback, useContext, useRef, useEffect, useState, Suspense, useLayoutEffect } from 'react';
|
|
6
6
|
import { translationFactory } from '@datawheel/use-translation';
|
|
@@ -235,6 +235,7 @@ var defaultTranslation = {
|
|
|
235
235
|
message_default: "Please wait..."
|
|
236
236
|
},
|
|
237
237
|
params: {
|
|
238
|
+
add_metadata: "Add metadata",
|
|
238
239
|
action_clear: "Clear query",
|
|
239
240
|
action_clear_description: "Clear all parameters from your current query",
|
|
240
241
|
action_execute: "Execute query",
|
|
@@ -1265,6 +1266,10 @@ var queriesSlice = createSlice({
|
|
|
1265
1266
|
query.params.sortDir = payload.dir;
|
|
1266
1267
|
query.params.sortKey = payload.key;
|
|
1267
1268
|
},
|
|
1269
|
+
clearSorting(state) {
|
|
1270
|
+
const query = taintCurrentQuery(state);
|
|
1271
|
+
query.params.sortKey = void 0;
|
|
1272
|
+
},
|
|
1268
1273
|
/**
|
|
1269
1274
|
* Registers the result of the current QueryItem in the store.
|
|
1270
1275
|
*/
|
|
@@ -1334,7 +1339,7 @@ var selectPaginationParams = createSelector(selectCurrentQueryParams, (params) =
|
|
|
1334
1339
|
limit: params.pagiLimit || 0,
|
|
1335
1340
|
offset: params.pagiOffset || 0
|
|
1336
1341
|
}));
|
|
1337
|
-
createSelector(selectCurrentQueryParams, (params) => ({
|
|
1342
|
+
var selectSortingParams = createSelector(selectCurrentQueryParams, (params) => ({
|
|
1338
1343
|
sortKey: params.sortKey || "",
|
|
1339
1344
|
sortDir: params.sortDir
|
|
1340
1345
|
}));
|
|
@@ -2193,7 +2198,7 @@ createSelector(
|
|
|
2193
2198
|
selectOlapDimensionItems,
|
|
2194
2199
|
(dimensions) => Object.fromEntries(dimensions.map((item) => [item.name, item]))
|
|
2195
2200
|
);
|
|
2196
|
-
createSelector(
|
|
2201
|
+
var selectLevelTriadMap = createSelector(
|
|
2197
2202
|
selectOlapCube,
|
|
2198
2203
|
(cube) => cube ? mapDimensionHierarchyLevels(cube) : {}
|
|
2199
2204
|
);
|
|
@@ -2797,7 +2802,19 @@ function FullScreenSVG() {
|
|
|
2797
2802
|
}
|
|
2798
2803
|
|
|
2799
2804
|
// src/components/TableView.tsx
|
|
2800
|
-
|
|
2805
|
+
function isColumnSorted(column, key) {
|
|
2806
|
+
return column == key;
|
|
2807
|
+
}
|
|
2808
|
+
var propertiesUpdateHandler = (actions2, item, activeProps) => {
|
|
2809
|
+
const properties = item.properties.map(
|
|
2810
|
+
(prop) => buildProperty({
|
|
2811
|
+
...prop,
|
|
2812
|
+
active: activeProps.includes(prop.key)
|
|
2813
|
+
})
|
|
2814
|
+
);
|
|
2815
|
+
actions2.updateDrilldown({ ...item, properties });
|
|
2816
|
+
};
|
|
2817
|
+
var removeColumn = (actions2, entity, measures, drilldowns, type) => {
|
|
2801
2818
|
if ("aggregator" in entity) {
|
|
2802
2819
|
const measure = measures.find((d) => d.name === entity.name);
|
|
2803
2820
|
measure && actions2.updateMeasure({ ...measure, active: false });
|
|
@@ -2806,10 +2823,21 @@ var removeColumn = (actions2, entity, measures, drilldowns) => {
|
|
|
2806
2823
|
const drilldown = drilldowns.find((d) => d.level === entity.name);
|
|
2807
2824
|
drilldown && actions2.updateDrilldown({ ...drilldown, active: false });
|
|
2808
2825
|
}
|
|
2826
|
+
if (isProperty(type)) {
|
|
2827
|
+
const activeDrilldowns = drilldowns.filter((d) => d.active);
|
|
2828
|
+
const drilldown = activeDrilldowns.find(
|
|
2829
|
+
(dd) => dd.properties.some((property) => property.name === entity.name)
|
|
2830
|
+
);
|
|
2831
|
+
const activeProperties = drilldown == null ? void 0 : drilldown.properties.filter((p) => p.active).filter((p) => p.name !== entity.name).filter((p) => p.active).map((p) => p.name);
|
|
2832
|
+
if (drilldown && activeProperties) {
|
|
2833
|
+
propertiesUpdateHandler(actions2, drilldown, activeProperties);
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2809
2836
|
};
|
|
2837
|
+
var isProperty = (entity) => entity === "property";
|
|
2810
2838
|
function showTrashIcon(columns, type) {
|
|
2811
2839
|
const result = columns.filter((c) => c.entityType === type);
|
|
2812
|
-
return result.length > 1;
|
|
2840
|
+
return result.length > 1 || isProperty(type);
|
|
2813
2841
|
}
|
|
2814
2842
|
var getActionIcon = (entityType) => {
|
|
2815
2843
|
if (entityType === "measure") {
|
|
@@ -2824,6 +2852,8 @@ var getEntityText = (entityType) => {
|
|
|
2824
2852
|
return "Metric";
|
|
2825
2853
|
case "level":
|
|
2826
2854
|
return "Dimension";
|
|
2855
|
+
case "property":
|
|
2856
|
+
return "Property";
|
|
2827
2857
|
default:
|
|
2828
2858
|
return "";
|
|
2829
2859
|
}
|
|
@@ -3026,6 +3056,7 @@ function useTable({
|
|
|
3026
3056
|
const { currentFormats, getAvailableKeys, getFormatter, getFormatterKey, setFormat } = useFormatter(
|
|
3027
3057
|
cube.measures
|
|
3028
3058
|
);
|
|
3059
|
+
const { sortKey, sortDir } = useSelector$1(selectSortingParams);
|
|
3029
3060
|
const columns = useMemo(() => {
|
|
3030
3061
|
const indexColumn = {
|
|
3031
3062
|
id: "#",
|
|
@@ -3066,22 +3097,33 @@ function useTable({
|
|
|
3066
3097
|
return 0;
|
|
3067
3098
|
},
|
|
3068
3099
|
Header: ({ column: column2 }) => {
|
|
3100
|
+
const isSorted = isColumnSorted(entity.name, sortKey);
|
|
3069
3101
|
return /* @__PURE__ */ React13__default.createElement(Box, { mb: rem(5), key: "header" }, /* @__PURE__ */ React13__default.createElement(Flex, { justify: "center", align: "center" }, /* @__PURE__ */ React13__default.createElement(Box, { sx: { flexGrow: 1 } }, /* @__PURE__ */ React13__default.createElement(Flex, { gap: "xs", align: "center" }, getActionIcon(entityType), /* @__PURE__ */ React13__default.createElement(Text, { size: "sm" }, header), /* @__PURE__ */ React13__default.createElement(
|
|
3070
3102
|
ActionIcon,
|
|
3071
3103
|
{
|
|
3072
3104
|
key: `sort-${header}`,
|
|
3073
3105
|
size: 22,
|
|
3074
3106
|
ml: rem(5),
|
|
3075
|
-
onClick:
|
|
3107
|
+
onClick: () => {
|
|
3108
|
+
if (!isSorted) {
|
|
3109
|
+
actions2.updateSorting({ key: entity.name, dir: "desc" });
|
|
3110
|
+
}
|
|
3111
|
+
if (isSorted && sortDir === "desc") {
|
|
3112
|
+
actions2.updateSorting({ key: entity.name, dir: "asc" });
|
|
3113
|
+
}
|
|
3114
|
+
if (isSorted && sortDir === "asc") {
|
|
3115
|
+
actions2.clearSorting();
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3076
3118
|
},
|
|
3077
|
-
getSortIcon(
|
|
3119
|
+
getSortIcon(isSorted ? sortDir : false, entityType)
|
|
3078
3120
|
))), /* @__PURE__ */ React13__default.createElement(
|
|
3079
3121
|
CustomActionIcon_default,
|
|
3080
3122
|
{
|
|
3081
3123
|
label: `At least one ${getEntityText(entityType)} is required.`,
|
|
3082
3124
|
key: `remove-${column2.columnDef.header}`,
|
|
3083
3125
|
disabled: !showTrashIcon(finalKeys, entityType),
|
|
3084
|
-
onClick: () => removeColumn(actions2, entity, measures, drilldowns),
|
|
3126
|
+
onClick: () => removeColumn(actions2, entity, measures, drilldowns, entityType),
|
|
3085
3127
|
showTooltip: !showTrashIcon(finalKeys, entityType),
|
|
3086
3128
|
size: 25,
|
|
3087
3129
|
ml: rem(5)
|
|
@@ -3197,7 +3239,7 @@ function useTable({
|
|
|
3197
3239
|
enableHiding: false,
|
|
3198
3240
|
manualFiltering: true,
|
|
3199
3241
|
manualPagination: true,
|
|
3200
|
-
manualSorting:
|
|
3242
|
+
manualSorting: true,
|
|
3201
3243
|
rowCount: totalRowCount,
|
|
3202
3244
|
state: {
|
|
3203
3245
|
isLoading: isLoading || data === void 0 || isTransitionState,
|
|
@@ -3430,7 +3472,17 @@ function AddColumnsDrawer() {
|
|
|
3430
3472
|
},
|
|
3431
3473
|
/* @__PURE__ */ React13__default.createElement(MeasuresOptions, null),
|
|
3432
3474
|
/* @__PURE__ */ React13__default.createElement(DrillDownOptions, null)
|
|
3433
|
-
), /* @__PURE__ */ React13__default.createElement(Group, { position: "center", sx: { flexWrap: "nowrap" } }, smallerThanMd ? /* @__PURE__ */ React13__default.createElement(ActionIcon, { onClick: open, size: "md", variant: "filled", color: theme.primaryColor }, /* @__PURE__ */ React13__default.createElement(IconStack3, { size: "0.75rem" })) : /* @__PURE__ */ React13__default.createElement(
|
|
3475
|
+
), /* @__PURE__ */ React13__default.createElement(Group, { position: "center", sx: { flexWrap: "nowrap" } }, smallerThanMd ? /* @__PURE__ */ React13__default.createElement(ActionIcon, { onClick: open, size: "md", variant: "filled", color: theme.primaryColor }, /* @__PURE__ */ React13__default.createElement(IconStack3, { size: "0.75rem" })) : /* @__PURE__ */ React13__default.createElement(
|
|
3476
|
+
Button,
|
|
3477
|
+
{
|
|
3478
|
+
id: "dex-column-btn",
|
|
3479
|
+
leftIcon: /* @__PURE__ */ React13__default.createElement(IconPlus, { size: "1.2rem" }),
|
|
3480
|
+
onClick: open,
|
|
3481
|
+
m: "md",
|
|
3482
|
+
size: "sm"
|
|
3483
|
+
},
|
|
3484
|
+
t("params.add_columns")
|
|
3485
|
+
)));
|
|
3434
3486
|
}
|
|
3435
3487
|
function DrillDownOptions() {
|
|
3436
3488
|
const locale = useSelector$1(selectLocale);
|
|
@@ -3468,13 +3520,22 @@ function DimensionItem({
|
|
|
3468
3520
|
activeItems
|
|
3469
3521
|
}
|
|
3470
3522
|
));
|
|
3471
|
-
return /* @__PURE__ */ React13__default.createElement(
|
|
3472
|
-
|
|
3523
|
+
return /* @__PURE__ */ React13__default.createElement(
|
|
3524
|
+
"div",
|
|
3473
3525
|
{
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3526
|
+
key: dimension.name,
|
|
3527
|
+
className: "dex-dimension-control",
|
|
3528
|
+
id: `dex-dimension-${dimension.name}`
|
|
3529
|
+
},
|
|
3530
|
+
/* @__PURE__ */ React13__default.createElement(
|
|
3531
|
+
Divider,
|
|
3532
|
+
{
|
|
3533
|
+
my: "md",
|
|
3534
|
+
label: /* @__PURE__ */ React13__default.createElement(Group, null, getIconForDimensionType(dimension.type), /* @__PURE__ */ React13__default.createElement(Text, { italic: true }, getCaption(dimension, locale)))
|
|
3535
|
+
}
|
|
3536
|
+
),
|
|
3537
|
+
options
|
|
3538
|
+
);
|
|
3478
3539
|
}
|
|
3479
3540
|
function HierarchyItem({
|
|
3480
3541
|
dimension,
|
|
@@ -3524,6 +3585,7 @@ function LevelItem({
|
|
|
3524
3585
|
depth = 0
|
|
3525
3586
|
}) {
|
|
3526
3587
|
const [activeFilter, setActiveFilter] = useState(false);
|
|
3588
|
+
const [activePropertiesFilter, setActiveProperties] = useState(false);
|
|
3527
3589
|
const { translate: t } = useTranslation();
|
|
3528
3590
|
const actions2 = useActions();
|
|
3529
3591
|
const cutItems = useSelector$1(selectCutItems);
|
|
@@ -3584,6 +3646,7 @@ function LevelItem({
|
|
|
3584
3646
|
const isDisabled = isOtherHierarchySelected && !checked;
|
|
3585
3647
|
if (!currentDrilldown) return;
|
|
3586
3648
|
const paddingLeft = `${5 * depth + 5}px`;
|
|
3649
|
+
const properities = currentDrilldown.properties.length ? currentDrilldown.properties : null;
|
|
3587
3650
|
return currentDrilldown && /* @__PURE__ */ React13__default.createElement(React13__default.Fragment, null, /* @__PURE__ */ React13__default.createElement(Group, { className: "dex-level-control", mt: "sm", position: "apart", key: level.name, noWrap: true }, /* @__PURE__ */ React13__default.createElement(
|
|
3588
3651
|
Checkbox,
|
|
3589
3652
|
{
|
|
@@ -3612,7 +3675,7 @@ function LevelItem({
|
|
|
3612
3675
|
disabled: isDisabled
|
|
3613
3676
|
},
|
|
3614
3677
|
activeFilter ? /* @__PURE__ */ React13__default.createElement(IconFilterOff, null) : /* @__PURE__ */ React13__default.createElement(IconFilter, null)
|
|
3615
|
-
), /* @__PURE__ */ React13__default.createElement(ThemeIcon, { size: "xs", color: "gray", variant: "light", bg: "transparent" }, /* @__PURE__ */ React13__default.createElement(StackSVG, null)))), activeFilter && /* @__PURE__ */ React13__default.createElement(Box, { pt: "md" }, /* @__PURE__ */ React13__default.createElement(
|
|
3678
|
+
), properities && /* @__PURE__ */ React13__default.createElement(Tooltip, { label: t("params.add_metadata") }, /* @__PURE__ */ React13__default.createElement(ActionIcon, { onClick: () => setActiveProperties((value) => !value) }, /* @__PURE__ */ React13__default.createElement(IconAdjustments, null))), /* @__PURE__ */ React13__default.createElement(ThemeIcon, { size: "xs", color: "gray", variant: "light", bg: "transparent" }, /* @__PURE__ */ React13__default.createElement(StackSVG, null)))), activeFilter && /* @__PURE__ */ React13__default.createElement(Box, { pt: "md" }, /* @__PURE__ */ React13__default.createElement(
|
|
3616
3679
|
MultiSelect,
|
|
3617
3680
|
{
|
|
3618
3681
|
sx: { flex: "1 1 100%" },
|
|
@@ -3636,7 +3699,56 @@ function LevelItem({
|
|
|
3636
3699
|
nothingFound: "Nothing found",
|
|
3637
3700
|
disabled: isDisabled
|
|
3638
3701
|
}
|
|
3639
|
-
)));
|
|
3702
|
+
)), activePropertiesFilter && /* @__PURE__ */ React13__default.createElement(PropertiesMultiSelect, { item: currentDrilldown }));
|
|
3703
|
+
}
|
|
3704
|
+
function PropertiesMultiSelect({ item }) {
|
|
3705
|
+
const levelTriadMap = useSelector$1(selectLevelTriadMap);
|
|
3706
|
+
const locale = useSelector$1(selectLocale);
|
|
3707
|
+
const actions2 = useActions();
|
|
3708
|
+
const { translate: t } = useTranslation();
|
|
3709
|
+
const propertiesUpdateHandler2 = useCallback(
|
|
3710
|
+
(activeProps) => {
|
|
3711
|
+
const properties = item.properties.map(
|
|
3712
|
+
(prop) => buildProperty({
|
|
3713
|
+
...prop,
|
|
3714
|
+
active: activeProps.includes(prop.key)
|
|
3715
|
+
})
|
|
3716
|
+
);
|
|
3717
|
+
actions2.updateDrilldown({ ...item, properties });
|
|
3718
|
+
},
|
|
3719
|
+
[item]
|
|
3720
|
+
);
|
|
3721
|
+
const activeProperties = filterMap(
|
|
3722
|
+
item.properties,
|
|
3723
|
+
(item2) => isActiveItem(item2) ? item2.key : null
|
|
3724
|
+
);
|
|
3725
|
+
const label = useMemo(() => {
|
|
3726
|
+
const triad = levelTriadMap[`${item.level}`];
|
|
3727
|
+
const triadCaptions = triad.map((item2) => getCaption(item2, locale.code));
|
|
3728
|
+
return t("params.tag_drilldowns", {
|
|
3729
|
+
abbr: abbreviateFullName(triadCaptions, t("params.tag_drilldowns_abbrjoint")),
|
|
3730
|
+
dimension: triadCaptions[0],
|
|
3731
|
+
hierarchy: triadCaptions[1],
|
|
3732
|
+
level: triadCaptions[2],
|
|
3733
|
+
propCount: activeProperties.length
|
|
3734
|
+
});
|
|
3735
|
+
}, [activeProperties.join("-"), item, locale.code]);
|
|
3736
|
+
return /* @__PURE__ */ React13__default.createElement(Box, { pt: "md" }, /* @__PURE__ */ React13__default.createElement(
|
|
3737
|
+
MultiSelect,
|
|
3738
|
+
{
|
|
3739
|
+
sx: { flex: "1 1 100%" },
|
|
3740
|
+
searchable: true,
|
|
3741
|
+
onChange: propertiesUpdateHandler2,
|
|
3742
|
+
value: activeProperties || [],
|
|
3743
|
+
placeholder: `Filter by ${label}`,
|
|
3744
|
+
data: item.properties.map((property) => ({
|
|
3745
|
+
value: String(property.key),
|
|
3746
|
+
label: property.name
|
|
3747
|
+
})),
|
|
3748
|
+
clearable: true,
|
|
3749
|
+
nothingFound: "Nothing found"
|
|
3750
|
+
}
|
|
3751
|
+
));
|
|
3640
3752
|
}
|
|
3641
3753
|
function getFilterfnKey(type) {
|
|
3642
3754
|
switch (type) {
|