From fdb18e8b522019d22679c9ea4435e5979a5dd60e Mon Sep 17 00:00:00 2001 From: Walter Buczacka Date: Wed, 16 Oct 2024 12:53:56 -0300 Subject: [PATCH 1/4] add properties --- src/components/DrawerMenu.tsx | 98 ++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 6 deletions(-) diff --git a/src/components/DrawerMenu.tsx b/src/components/DrawerMenu.tsx index 155a1ab..fbe1efb 100644 --- a/src/components/DrawerMenu.tsx +++ b/src/components/DrawerMenu.tsx @@ -17,6 +17,7 @@ import { } from "@mantine/core"; import {useDisclosure, useMediaQuery} from "@mantine/hooks"; import { + IconAdjustments, IconArrowsLeftRight, IconBox, IconClock, @@ -29,7 +30,7 @@ import { IconStack3, IconWorld } from "@tabler/icons-react"; -import React, {useCallback, useLayoutEffect, useMemo, useState} from "react"; +import React, {PropsWithChildren, useCallback, useLayoutEffect, useMemo, useState} from "react"; import {useSelector} from "react-redux"; import {Comparison} from "../api"; import type {TesseractDimension, TesseractHierarchy, TesseractLevel} from "../api/tesseract/schema"; @@ -44,7 +45,11 @@ import { selectLocale, selectMeasureMap } from "../state/queries"; -import {selectOlapDimensionItems, selectOlapMeasureItems} from "../state/selectors"; +import { + selectLevelTriadMap, + selectOlapDimensionItems, + selectOlapMeasureItems +} from "../state/selectors"; import {filterMap} from "../utils/array"; import {abbreviateFullName} from "../utils/format"; import {getCaption} from "../utils/string"; @@ -56,11 +61,13 @@ import { buildCut, buildDrilldown, buildFilter, - buildMeasure + buildMeasure, + buildProperty } from "../utils/structs"; import {isActiveItem} from "../utils/validation"; import {getFiltersConditions} from "./TableView"; import {BarsSVG, StackSVG} from "./icons"; +import {keyBy} from "../utils/transform"; const styles = (t: MantineTheme) => ({ header: { @@ -106,7 +113,13 @@ function AddColumnsDrawer() { ) : ( - )} @@ -172,7 +185,11 @@ function DimensionItem({ // return options[0]; // } return ( -
+
@@ -359,7 +378,11 @@ function LevelItem({ > {activeFilter ? : } - + {properities && ( + setActiveProperties(value => !value)}> + + + )} @@ -391,11 +414,74 @@ function LevelItem({ /> )} + {activePropertiesFilter && } ) ); } +type PropertiesMultiSelectType = { + item: DrilldownItem; +}; +function PropertiesMultiSelect({item}: PropsWithChildren) { + const levelTriadMap = useSelector(selectLevelTriadMap); + const locale = useSelector(selectLocale); + const actions = useActions(); + const {translate: t} = useTranslation(); + + const propertiesUpdateHandler = useCallback( + (activeProps: string[]) => { + const properties = item.properties.map(prop => + buildProperty({ + ...prop, + active: activeProps.includes(prop.key) + }) + ); + actions.updateDrilldown({...item, properties}); + }, + [item] + ); + + const propertyRecords = useMemo( + () => keyBy(item.properties, item => item.key), + [item.properties] + ); + + const activeProperties = filterMap(item.properties, item => + isActiveItem(item) ? item.key : null + ); + + const label = useMemo(() => { + const triad = levelTriadMap[`${item.level}`]; + const triadCaptions = triad.map(item => getCaption(item, locale.code)); + return t("params.tag_drilldowns", { + abbr: abbreviateFullName(triadCaptions, t("params.tag_drilldowns_abbrjoint")), + dimension: triadCaptions[0], + hierarchy: triadCaptions[1], + level: triadCaptions[2], + propCount: activeProperties.length + }); + }, [activeProperties.join("-"), item, locale.code]); + + return ( + + ({ + value: String(property.key), + label: property.name + }))} + clearable + nothingFound="Nothing found" + /> + + ); +} + export function getFilterfnKey(type) { switch (type) { case "greaterThan": From 89c3dcec726316cb49475d7c8a409217415fa578 Mon Sep 17 00:00:00 2001 From: Walter Buczacka Date: Wed, 16 Oct 2024 13:07:20 -0300 Subject: [PATCH 2/4] update translations & add tooltip --- src/components/DrawerMenu.tsx | 11 +++++++---- src/hooks/translation.ts | 17 +++++++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/components/DrawerMenu.tsx b/src/components/DrawerMenu.tsx index fbe1efb..7138b8f 100644 --- a/src/components/DrawerMenu.tsx +++ b/src/components/DrawerMenu.tsx @@ -13,7 +13,8 @@ import { Text, ThemeIcon, useMantineTheme, - MantineTheme + MantineTheme, + Tooltip } from "@mantine/core"; import {useDisclosure, useMediaQuery} from "@mantine/hooks"; import { @@ -379,9 +380,11 @@ function LevelItem({ {activeFilter ? : } {properities && ( - setActiveProperties(value => !value)}> - - + + setActiveProperties(value => !value)}> + + + )} diff --git a/src/hooks/translation.ts b/src/hooks/translation.ts index 78ac3d9..dccc12a 100644 --- a/src/hooks/translation.ts +++ b/src/hooks/translation.ts @@ -47,6 +47,7 @@ export const defaultTranslation = { message_default: "Please wait..." }, params: { + add_metadata: "Add metadata", action_clear: "Clear query", action_clear_description: "Clear all parameters from your current query", action_execute: "Execute query", @@ -193,13 +194,14 @@ export const defaultTranslation = { controls: { prev: "Previous", next: "Next", - help: "Help", + help: "Help" }, steps: { welcome: { title: "Welcome to the Data Explorer", text1: "This tutorial will guide you through the steps on how to use the Data Explorer", - text2: "By following this tutorial, you will be able to find data of interest and generate your own data tables and visualizations." + text2: + "By following this tutorial, you will be able to find data of interest and generate your own data tables and visualizations." }, locale: { title: "Multilingual", @@ -214,7 +216,7 @@ export const defaultTranslation = { search: { title: "Searching for a Dataset", text1: "You can also explore the list of topics and datasets.", - text2: "Start typing to filter the list of datasets with your search", + text2: "Start typing to filter the list of datasets with your search" }, table: { title: "Data Table", @@ -224,12 +226,15 @@ export const defaultTranslation = { columns: { title: "Columns", text1: "Select the columns that you are interested in viewing.", - text2: "When you toggle any column checkbox, the data table will automatically update to reflect your selection." + text2: + "When you toggle any column checkbox, the data table will automatically update to reflect your selection." }, filters: { title: "Filters", - text1: "You can filter the elements of each column that you want to display in the data table and visualization.", - text2: "If you want all available elements to be displayed, you don't need to apply filters." + text1: + "You can filter the elements of each column that you want to display in the data table and visualization.", + text2: + "If you want all available elements to be displayed, you don't need to apply filters." }, download: { title: "Downloading the Data", From 1ac25261b901586c9c03200c0a58ee22d0b80122 Mon Sep 17 00:00:00 2001 From: Walter Buczacka Date: Thu, 17 Oct 2024 11:57:12 -0300 Subject: [PATCH 3/4] add remove property logic --- src/components/TableView.tsx | 41 +++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/components/TableView.tsx b/src/components/TableView.tsx index 4e205ee..d014b52 100644 --- a/src/components/TableView.tsx +++ b/src/components/TableView.tsx @@ -57,7 +57,7 @@ import { import {selectOlapMeasureItems} from "../state/selectors"; import {filterMap} from "../utils/array"; import type {CutItem, DrilldownItem, FilterItem, MeasureItem, QueryResult} from "../utils/structs"; -import {type AnyResultColumn, buildFilter, buildMeasure} from "../utils/structs"; +import {type AnyResultColumn, buildFilter, buildMeasure, buildProperty} from "../utils/structs"; import type {ViewProps} from "../utils/types"; import CustomActionIcon from "./CustomActionIcon"; import { @@ -78,11 +78,22 @@ function isColumnSorted(column: string, key: string) { return column == key; } +const propertiesUpdateHandler = (actions, item: DrilldownItem, activeProps: string[]) => { + const properties = item.properties.map(prop => + buildProperty({ + ...prop, + active: activeProps.includes(prop.key) + }) + ); + actions.updateDrilldown({...item, properties}); +}; + const removeColumn = ( actions: ExplorerBoundActionMap, entity: TesseractMeasure | TesseractProperty | TesseractLevel, measures: MeasureItem[], - drilldowns: DrilldownItem[] + drilldowns: DrilldownItem[], + type: EntityTypes ) => { if ("aggregator" in entity) { const measure = measures.find(d => d.name === entity.name); @@ -92,12 +103,30 @@ const removeColumn = ( const drilldown = drilldowns.find(d => d.level === entity.name); drilldown && actions.updateDrilldown({...drilldown, active: false}); } - // maybe need to handle case for property columns. + + if (isProperty(type)) { + const activeDrilldowns = drilldowns.filter(d => d.active); + const drilldown = activeDrilldowns.find(dd => + dd.properties.some(property => property.name === entity.name) + ); + + const activeProperties = drilldown?.properties + .filter(p => p.active) + .filter(p => p.name !== entity.name) + .filter(p => p.active) + .map(p => p.name); + + if (drilldown && activeProperties) { + propertiesUpdateHandler(actions, drilldown, activeProperties); + } + } }; +const isProperty = (entity: EntityTypes) => entity === "property"; + function showTrashIcon(columns: AnyResultColumn[], type: EntityTypes) { const result = columns.filter(c => c.entityType === type); - return result.length > 1; + return result.length > 1 || isProperty(type); } const getActionIcon = (entityType: EntityTypes) => { @@ -122,6 +151,8 @@ const getEntityText = (entityType: EntityTypes) => { return "Metric"; case "level": return "Dimension"; + case "property": + return "Property"; default: return ""; } @@ -499,7 +530,7 @@ export function useTable({ label={`At least one ${getEntityText(entityType)} is required.`} key={`remove-${column.columnDef.header}`} disabled={!showTrashIcon(finalKeys, entityType)} - onClick={() => removeColumn(actions, entity, measures, drilldowns)} + onClick={() => removeColumn(actions, entity, measures, drilldowns, entityType)} showTooltip={!showTrashIcon(finalKeys, entityType)} size={25} ml={rem(5)} From 39b67a5f6a43570d1225e533c44c04049626d574 Mon Sep 17 00:00:00 2001 From: Walter Buczacka Date: Thu, 17 Oct 2024 11:57:38 -0300 Subject: [PATCH 4/4] remove not used function --- src/components/DrawerMenu.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/components/DrawerMenu.tsx b/src/components/DrawerMenu.tsx index 7138b8f..d7a4fbe 100644 --- a/src/components/DrawerMenu.tsx +++ b/src/components/DrawerMenu.tsx @@ -445,11 +445,6 @@ function PropertiesMultiSelect({item}: PropsWithChildren keyBy(item.properties, item => item.key), - [item.properties] - ); - const activeProperties = filterMap(item.properties, item => isActiveItem(item) ? item.key : null );