Skip to content

Commit

Permalink
Add absolute change option in context column (#2957)
Browse files Browse the repository at this point in the history
* add enum variant for DELTA_ABSOLUTE

* fix arrow flipping on SearchableFilterButton

* change leaderboard context column controls

* slightly tighten spacing on SelectButton

* remove deprecated component

* add absolute change to menu and leaderboard header

* move context column value to own component,
render with color and "no data"

* update DELTA_CHANGE to DELTA_PERCENT

* merge cleanups

* remove logging

* adjustment to leaderboard column widths

* fix dimension table sort arrow

* cleanup

* cleanups

* cleanups

* remove redeclaration

* add default prop

* add plus to abs change in leaderboard

* code review cleanups
  • Loading branch information
bcolloran authored Sep 12, 2023
1 parent ee1dc87 commit 4f22baf
Show file tree
Hide file tree
Showing 13 changed files with 164 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,20 @@
export let enableResize = true;
export let isSelected = false;
export let bgClass = "";
// set this prop to control sorting arrow externally.
// if undefined, sorting arrow is toggled within the component.
export let sortAscending: boolean | undefined = undefined;
const config: VirtualizedTableConfig = getContext("config");
const dispatch = createEventDispatcher();
const { shiftClickAction } = createShiftClickAction();
let showMore = false;
$: isSortingDesc = true;
// if sorting is controlled externally, use that prop value
// otherwise, default to true
$: isSortingDesc = sortAscending !== undefined ? !sortAscending : true;
$: isDimensionTable = config.table === "DimensionTable";
$: isDimensionColumn = isDimensionTable && type === "VARCHAR";
Expand Down Expand Up @@ -68,8 +74,12 @@
showMore = false;
}}
on:click={() => {
if (isSelected) isSortingDesc = !isSortingDesc;
else isSortingDesc = true;
// only toggle `isSortingDesc` within the component if
// sorting is not controlled externally
if (sortAscending === undefined) {
if (isSelected) isSortingDesc = !isSortingDesc;
else isSortingDesc = true;
}
dispatch("click-column");
}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
export let selectedColumn: string = null;
export let fallbackBGClass = "";
// set this prop to control sorting arrow externally.
// if undefined, sorting arrow is toggled within the
// cell header component.
export let sortAscending: boolean = undefined;
const getColumnHeaderProps = (header) => {
const name = columns[header.index]?.label || columns[header.index]?.name;
const isEnableResizeDefined = "enableResize" in columns[header.index];
Expand Down Expand Up @@ -61,6 +66,7 @@
{header}
{noPin}
{showDataIcon}
{sortAscending}
on:pin={() => {
dispatch("pin", columns[header.index]);
}}
Expand Down
32 changes: 12 additions & 20 deletions web-common/src/features/dashboards/dashboard-stores.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,27 +490,19 @@ const metricViewReducers = {
});
},

displayDeltaChange(name: string) {
setContextColumn(name: string, contextColumn: LeaderboardContextColumn) {
updateMetricsExplorerByName(name, (metricsExplorer) => {
// NOTE: only show delta change if comparison is enabled
if (metricsExplorer.showComparison === false) return;

metricsExplorer.leaderboardContextColumn =
LeaderboardContextColumn.DELTA_PERCENT;
});
},

displayPercentOfTotal(name: string) {
updateMetricsExplorerByName(name, (metricsExplorer) => {
metricsExplorer.leaderboardContextColumn =
LeaderboardContextColumn.PERCENT;
});
},

hideContextColumn(name: string) {
updateMetricsExplorerByName(name, (metricsExplorer) => {
metricsExplorer.leaderboardContextColumn =
LeaderboardContextColumn.HIDDEN;
switch (contextColumn) {
case LeaderboardContextColumn.DELTA_ABSOLUTE:
case LeaderboardContextColumn.DELTA_PERCENT: {
if (metricsExplorer.showComparison === false) return;
metricsExplorer.leaderboardContextColumn = contextColumn;
return;
}
default:
metricsExplorer.leaderboardContextColumn = contextColumn;
return;
}
});
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@
<DimensionTable
on:select-item={(event) => onSelectItem(event)}
on:sort={(event) => onSortByColumn(event)}
{sortAscending}
dimensionName={dimensionColumn}
{columns}
{selectedValues}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ TableCells – the cell contents.
export let columns: VirtualizedTableColumns[];
export let selectedValues: Array<unknown> = [];
export let sortByColumn: string;
export let sortAscending: boolean;
export let dimensionName: string;
export let excludeMode = false;
Expand Down Expand Up @@ -203,6 +204,7 @@ TableCells – the cell contents.
selectedColumn={sortByColumn}
columns={measureColumns}
fallbackBGClass="bg-white"
{sortAscending}
on:click-column={handleColumnHeaderClick}
/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export enum LeaderboardContextColumn {
PERCENT = "percent",
// show percent change of the value compared to the previous time range
DELTA_PERCENT = "delta_change",
// show absolute change of the value compared to the previous time range
DELTA_ABSOLUTE = "delta_absolute",
// Do not show the context column
HIDDEN = "hidden",
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<script lang="ts">
import { LeaderboardContextColumn } from "@rilldata/web-common/features/dashboards/leaderboard-context-column";
import PercentageChange from "../../../components/data-types/PercentageChange.svelte";
import { FormattedDataType } from "@rilldata/web-common/components/data-types";
export let formattedValue: string;
export let showContext: LeaderboardContextColumn;
$: neg = formattedValue[0] === "-";
$: noData = formattedValue === "" || !formattedValue;
$: customStyle = neg ? "text-red-500" : noData ? "opacity-50 italic" : "";
</script>

{#if showContext === LeaderboardContextColumn.DELTA_PERCENT || showContext === LeaderboardContextColumn.PERCENT}
<div style:width="44px">
<PercentageChange value={formattedValue} />
</div>
{:else if showContext === LeaderboardContextColumn.DELTA_ABSOLUTE}
<div style:width="54px">
{#if noData}
<span class="opacity-50 italic" style:font-size=".925em">no data</span>
{:else}
<FormattedDataType type="INTEGER" value={formattedValue} {customStyle} />
{/if}
</div>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,13 @@
return b.value - a.value;
});
$: contextColumn = $dashboardStore?.leaderboardContextColumn;
// Compose the comparison /toplist query
$: showTimeComparison =
$dashboardStore?.leaderboardContextColumn ===
LeaderboardContextColumn.DELTA_PERCENT &&
(contextColumn === LeaderboardContextColumn.DELTA_PERCENT ||
contextColumn === LeaderboardContextColumn.DELTA_ABSOLUTE) &&
$timeControlsStore?.showComparison;
$: showPercentOfTotal =
$dashboardStore?.leaderboardContextColumn ===
LeaderboardContextColumn.PERCENT;
Expand Down Expand Up @@ -237,8 +239,7 @@
on:mouseleave={() => (hovered = false)}
>
<LeaderboardHeader
{showTimeComparison}
{showPercentOfTotal}
{contextColumn}
isFetching={$topListQuery.isFetching}
{displayName}
on:toggle-filter-mode={toggleFilterMode}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@
const handleContextValueButtonGroupClick = (evt) => {
const value: SelectMenuItem = evt.detail;
const key = value.key;
metricsExplorerStore.setContextColumn(metricViewName, key);
if (key === LeaderboardContextColumn.HIDDEN) {
metricsExplorerStore.hideContextColumn(metricViewName);
} else if (key === LeaderboardContextColumn.DELTA_PERCENT) {
metricsExplorerStore.displayDeltaChange(metricViewName);
} else if (key === LeaderboardContextColumn.PERCENT) {
metricsExplorerStore.displayPercentOfTotal(metricViewName);
}
// if (key === LeaderboardContextColumn.HIDDEN) {
// metricsExplorerStore.hideContextColumn(metricViewName);
// } else if (key === LeaderboardContextColumn.DELTA_PERCENT) {
// metricsExplorerStore.displayDeltaChange(metricViewName);
// } else if (key === LeaderboardContextColumn.PERCENT) {
// metricsExplorerStore.displayPercentOfTotal(metricViewName);
// } else if (key === LeaderboardContextColumn.DELTA_ABSOLUTE) {
// metricsExplorerStore.displayDeltaAbsolute(metricViewName);
// }
};
let options: SelectMenuItem[];
Expand All @@ -41,6 +44,11 @@
key: LeaderboardContextColumn.DELTA_PERCENT,
disabled: !$timeControlsStore.showComparison,
},
{
main: "Absolute change",
key: LeaderboardContextColumn.DELTA_ABSOLUTE,
disabled: !$timeControlsStore.showComparison,
},
{
main: "No context column",
key: LeaderboardContextColumn.HIDDEN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@
metricsExplorer?.leaderboardContextColumn ===
LeaderboardContextColumn.PERCENT
) {
metricsExplorerStore.hideContextColumn(metricViewName);
metricsExplorerStore.setContextColumn(
metricViewName,
LeaderboardContextColumn.HIDDEN
);
}
$: showHideDimensions = createShowHideDimensionsStore(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,36 @@
import Delta from "@rilldata/web-common/components/icons/Delta.svelte";
import PieChart from "@rilldata/web-common/components/icons/PieChart.svelte";
import ArrowDown from "@rilldata/web-common/components/icons/ArrowDown.svelte";
import { CONTEXT_COLUMN_WIDTH } from "./leaderboard-utils";
import { createEventDispatcher } from "svelte";
import { LeaderboardContextColumn } from "../leaderboard-context-column";
export let displayName: string;
export let isFetching: boolean;
export let dimensionDescription: string;
export let hovered: boolean;
export let showTimeComparison: boolean;
export let showPercentOfTotal: boolean;
export let contextColumn: LeaderboardContextColumn;
export let sortAscending: boolean;
export let filterExcludeMode: boolean;
let optionsMenuActive = false;
const dispatch = createEventDispatcher();
$: contextColumnWidth = (contextColumn: LeaderboardContextColumn) => {
switch (contextColumn) {
case LeaderboardContextColumn.DELTA_ABSOLUTE:
return "54px";
case LeaderboardContextColumn.DELTA_PERCENT:
case LeaderboardContextColumn.PERCENT:
return "44px";
case LeaderboardContextColumn.HIDDEN:
return "0px";
default:
throw new Error("Invalid context column, all cases must be handled");
}
};
$: arrowTransform = sortAscending ? "scale(1 -1)" : "scale(1 1)";
$: iconShown = showTimeComparison
? "delta"
: showPercentOfTotal
? "pie"
: null;
</script>

<div class="flex flex-row items-center">
Expand Down Expand Up @@ -110,14 +118,16 @@
# <ArrowDown transform={arrowTransform} />
</button>

{#if iconShown}
{#if contextColumn !== LeaderboardContextColumn.HIDDEN}
<div
class="shrink flex flex-row items-center justify-end"
style:width={CONTEXT_COLUMN_WIDTH + "px"}
style:width={contextColumnWidth(contextColumn)}
>
{#if iconShown === "delta"}
{#if contextColumn === LeaderboardContextColumn.DELTA_PERCENT}
<Delta /> %
{:else if iconShown === "pie"}
{:else if contextColumn === LeaderboardContextColumn.DELTA_ABSOLUTE}
<Delta />
{:else if contextColumn === LeaderboardContextColumn.PERCENT}
<PieChart /> %
{/if}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,14 @@
import LeaderboardTooltipContent from "./LeaderboardTooltipContent.svelte";
import PercentageChange from "../../../components/data-types/PercentageChange.svelte";
import LeaderboardItemFilterIcon from "./LeaderboardItemFilterIcon.svelte";
import { humanizeDataType } from "../humanize-numbers";
import LongBarZigZag from "./LongBarZigZag.svelte";
import {
CONTEXT_COLUMN_WIDTH,
LeaderboardItemData,
getFormatterValueForPercDiff,
formatContextColumnValue,
} from "./leaderboard-utils";
import ContextColumnValue from "./ContextColumnValue.svelte";
export let itemData: LeaderboardItemData;
$: label = itemData.label;
Expand All @@ -52,17 +51,12 @@
$: formattedValue = humanizeDataType(measureValue, formatPreset);
$: percentChangeFormatted =
showContext === LeaderboardContextColumn.DELTA_PERCENT
? getFormatterValueForPercDiff(
measureValue && comparisonValue
? measureValue - comparisonValue
: null,
comparisonValue
)
: showContext === LeaderboardContextColumn.PERCENT
? getFormatterValueForPercDiff(measureValue, unfilteredTotal)
: undefined;
$: contextColumnFormattedValue = formatContextColumnValue(
itemData,
unfilteredTotal,
showContext,
formatPreset
);
$: previousValueString =
comparisonValue !== undefined && comparisonValue !== null
Expand Down Expand Up @@ -178,14 +172,10 @@
value={formattedValue || measureValue}
/>
</div>
{#if percentChangeFormatted !== undefined}
<div
class="text-xs text-gray-500 dark:text-gray-400"
style:width={CONTEXT_COLUMN_WIDTH + "px"}
>
<PercentageChange value={percentChangeFormatted} />
</div>
{/if}
<ContextColumnValue
formattedValue={contextColumnFormattedValue}
{showContext}
/>
</div>
</div>
</BarAndLabel>
Expand Down
Loading

1 comment on commit 4f22baf

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.