Skip to content

Commit

Permalink
feat: tracking the usage of filters #344 (#493)
Browse files Browse the repository at this point in the history
* feat: tracking the usage of filters #344

* feat: add tracking config (altos-labs/data-browser#344)

* feat: make tracking config properties optional (altos-labs/data-browser#344)

* chore: update parameter descriptions (altos-labs/data-browser#344)

* refactor: use relative import path (altos-labs/data-browser#344)

* refactor: create interfaces for filter tracking payloads (altos-labs/data-browser#344)

---------

Co-authored-by: hunterckx <[email protected]>
  • Loading branch information
BruceRodrigues and hunterckx authored Dec 5, 2023
1 parent 02115fe commit b5944dc
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CloseRounded } from "@mui/icons-material";
import { Grow, PopoverPosition, PopoverProps } from "@mui/material";
import React, { MouseEvent, ReactNode, useState } from "react";
import { SelectCategoryView } from "../../../../common/entities";
import { TrackFilterOpenedFunction } from "../../../../config/entities";
import { OnFilterFn } from "../../../../hooks/useCategoryFilter";
import { CloseDrawerIconButton } from "../../../common/IconButton/iconButton.styles";
import { FilterLabel } from "../FilterLabel/filterLabel";
Expand All @@ -18,19 +19,23 @@ const DRAWER_SLOT_PROPS: PopoverProps["slotProps"] = {
};

export interface FilterProps {
categorySection?: string;
categoryView: SelectCategoryView;
closeAncestor?: () => void;
isFilterDrawer: boolean;
onFilter: OnFilterFn;
tags?: ReactNode; // e.g. filter tags
trackFilterOpened?: TrackFilterOpenedFunction;
}

export const Filter = ({
categorySection,
categoryView,
closeAncestor,
isFilterDrawer,
onFilter,
tags,
trackFilterOpened,
}: FilterProps): JSX.Element => {
const [isOpen, setIsOpen] = useState<boolean>(false);
const [position, setPosition] = useState<PopoverPosition>(DEFAULT_POSITION);
Expand Down Expand Up @@ -67,6 +72,7 @@ export const Filter = ({
// Set popover position and open state.
setPosition({ left: popoverLeftPos, top: popoverTopPos });
setIsOpen(true);
trackFilterOpened?.({ category: categoryView.key });
};

return (
Expand Down Expand Up @@ -95,6 +101,7 @@ export const Filter = ({
/>
)}
<FilterMenu
categorySection={categorySection}
categoryKey={categoryView.key}
categoryLabel={categoryView.label}
isFilterDrawer={isFilterDrawer}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Button, FilterView, FilterViewTools } from "./filterMenu.styles";
export interface FilterMenuProps {
categoryKey: CategoryKey;
categoryLabel: string;
categorySection?: string;
isFilterDrawer: boolean;
menuWidth?: number;
onCloseFilter: () => void;
Expand All @@ -25,6 +26,7 @@ export interface FilterMenuProps {
export const FilterMenu = ({
categoryKey,
categoryLabel,
categorySection,
isFilterDrawer,
menuWidth = 312,
onCloseFilter,
Expand Down Expand Up @@ -55,6 +57,7 @@ export const FilterMenu = ({
</FilterViewTools>
{filteredValues.length > 0 ? (
<VariableSizeList
categorySection={categorySection}
categoryKey={categoryKey}
isFilterDrawer={isFilterDrawer}
onFilter={onFilter}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Divider } from "@mui/material";
import { TrackFilterOpenedFunction } from "config/entities";
import React, { Fragment, useEffect, useRef, useState } from "react";
import { CategoryTag, SelectCategoryView } from "../../../../common/entities";
import {
Expand All @@ -22,6 +23,7 @@ export interface FiltersProps {
closeAncestor?: () => void;
disabled: boolean; // Global disabling of filters; typically in "related" entity view.
onFilter: OnFilterFn;
trackFilterOpened?: TrackFilterOpenedFunction;
}

/**
Expand Down Expand Up @@ -65,6 +67,7 @@ export const Filters = ({
closeAncestor,
disabled = false,
onFilter,
trackFilterOpened,
}: FiltersProps): JSX.Element => {
const isFilterDrawer = useBreakpointHelper(
BREAKPOINT_FN_NAME.DOWN,
Expand All @@ -80,16 +83,18 @@ export const Filters = ({

return (
<FilterList disabled={disabled} height={height} ref={filterListRef}>
{categoryFilters.map(({ categoryViews }, i) => (
{categoryFilters.map(({ categoryViews, label }, i) => (
<Fragment key={i}>
{i !== 0 && <Divider />}
{categoryViews.map((categoryView) => (
<Filter
key={categoryView.key}
categorySection={label}
categoryView={categoryView}
closeAncestor={closeAncestor}
isFilterDrawer={isFilterDrawer}
onFilter={onFilter}
trackFilterOpened={trackFilterOpened}
tags={renderFilterTags(categoryView, onFilter)}
/>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
VariableSizeListProps as ListProps,
} from "react-window";
import { SelectCategoryView } from "../../../../../../common/entities";
import { escapeRegExp } from "../../../../../../common/utils";
import {
BREAKPOINT_FN_NAME,
useBreakpointHelper,
Expand Down Expand Up @@ -59,7 +58,7 @@ interface VariableSizeListData {
filteredItems: SearchAllFiltersItem[];
onFilter: OnFilterFn;
onUpdateItemSizeByItemKey: (key: string, size: number) => void;
searchTermRegExp: RegExp | null;
searchTerm?: string;
}

interface OuterElementContextValue {
Expand All @@ -75,12 +74,8 @@ interface OuterElementContextValue {
function renderListItem(props: ListChildComponentProps): JSX.Element {
const { data, index, style } = props;
delete style.height; // Remove height style to allow variable size list to set item height.
const {
filteredItems,
onFilter,
onUpdateItemSizeByItemKey,
searchTermRegExp,
} = data as VariableSizeListData;
const { filteredItems, onFilter, onUpdateItemSizeByItemKey, searchTerm } =
data as VariableSizeListData;
const item = filteredItems[index];
if (item.type === ITEM_TYPE.DIVIDER) return <Divider style={style} />;
else
Expand All @@ -89,7 +84,7 @@ function renderListItem(props: ListChildComponentProps): JSX.Element {
item={item}
onFilter={onFilter}
onUpdateItemSizeByItemKey={onUpdateItemSizeByItemKey}
searchTermRegExp={searchTermRegExp}
searchTerm={searchTerm}
style={style}
/>
);
Expand Down Expand Up @@ -135,9 +130,6 @@ export const VariableSizeList = forwardRef<
autocompleteListRef
): JSX.Element {
const filteredItems = applyMenuFilter(categoryViews, searchTerm);
const searchTermRegExp = searchTerm
? new RegExp(escapeRegExp(searchTerm), "ig")
: null;
let resizeRequired = true;
const desktopSmDown = useBreakpointHelper(
BREAKPOINT_FN_NAME.DOWN,
Expand Down Expand Up @@ -188,7 +180,7 @@ export const VariableSizeList = forwardRef<
filteredItems,
onFilter,
onUpdateItemSizeByItemKey,
searchTermRegExp,
searchTerm,
}}
itemSize={(index): number => {
const item = filteredItems[index];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Typography,
} from "@mui/material";
import React, { useEffect, useRef } from "react";
import { escapeRegExp } from "../../../../../../common/utils";
import { OnFilterFn } from "../../../../../../hooks/useCategoryFilter";
import { TEXT_BODY_SMALL_400 } from "../../../../../../theme/common/typography";
import { CheckedIcon } from "../../../../../common/CustomIcon/components/CheckedIcon/checkedIcon";
Expand All @@ -18,18 +19,21 @@ interface Props {
item: SearchAllFiltersDynamicItem;
onFilter: OnFilterFn;
onUpdateItemSizeByItemKey: (key: string, size: number) => void;
searchTermRegExp: RegExp | null;
searchTerm?: string;
style: React.CSSProperties;
}

export default function VariableSizeListItem({
item,
onFilter,
onUpdateItemSizeByItemKey,
searchTermRegExp,
searchTerm,
style,
}: Props): JSX.Element {
const { key } = item;
const searchTermRegExp = searchTerm
? new RegExp(escapeRegExp(searchTerm), "ig")
: null;
const listItemRef = useRef<HTMLElement>();

const setRef = (e: HTMLElement | null): void => {
Expand All @@ -50,7 +54,9 @@ export default function VariableSizeListItem({
<ListItemButton
ref={setRef}
key={key}
onClick={(): void => onFilter(categoryKey, valueKey, !selected)}
onClick={(): void =>
onFilter(categoryKey, valueKey, !selected, undefined, searchTerm)
}
selected={selected}
style={style}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type ItemSizeByItemKey = Map<string, number>;

export interface VariableSizeListProps {
categoryKey: CategoryKey;
categorySection?: string;
height?: number; // Height of list; vertical list must be a number.
isFilterDrawer: boolean;
itemSize?: number; // Default item size.
Expand All @@ -39,9 +40,16 @@ export interface VariableSizeListProps {
*/
function renderListItem(props: ListChildComponentProps): JSX.Element {
const { data, index, style } = props;
const { categoryKey, onFilter, onUpdateItemSizeByItemKey, values } = data;
const {
categoryKey,
categorySection,
onFilter,
onUpdateItemSizeByItemKey,
values,
} = data;
return (
<VariableSizeListItem
categorySection={categorySection}
categoryKey={categoryKey}
listItem={values[index]}
onFilter={onFilter}
Expand All @@ -53,6 +61,7 @@ function renderListItem(props: ListChildComponentProps): JSX.Element {

export const VariableSizeList = ({
categoryKey,
categorySection,
height: initHeight = MAX_LIST_HEIGHT_PX,
isFilterDrawer,
itemSize = LIST_ITEM_HEIGHT,
Expand Down Expand Up @@ -101,6 +110,7 @@ export const VariableSizeList = ({
itemCount={values.length}
itemData={{
categoryKey,
categorySection,
onFilter,
onUpdateItemSizeByItemKey,
values,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { UncheckedIcon } from "../../../common/CustomIcon/components/UncheckedIc

interface Props {
categoryKey: CategoryKey;
categorySection?: string;
listItem: SelectCategoryValueView;
onFilter: OnFilterFn;
onUpdateItemSizeByItemKey: (itemKey: string, itemSize: number) => void;
Expand All @@ -24,6 +25,7 @@ interface Props {

export default function VariableSizeListItem({
categoryKey,
categorySection,
listItem,
onFilter,
onUpdateItemSizeByItemKey,
Expand All @@ -38,10 +40,14 @@ export default function VariableSizeListItem({
onUpdateItemSizeByItemKey(key, listItemRef.current?.clientHeight || 0);
}, [key, onUpdateItemSizeByItemKey]);

const handleItemClicked = (): void => {
onFilter(categoryKey, key, !selected, categorySection);
};

return (
<ListItemButton
ref={listItemRef}
onClick={(): void => onFilter(categoryKey, key, !selected)}
onClick={handleItemClicked}
selected={selected}
style={style}
>
Expand Down
39 changes: 39 additions & 0 deletions packages/data-explorer-ui/src/config/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,44 @@ type RelatedSearchFunction = (
selectedCategoryValues: SelectedFilterValue | undefined
) => Promise<RelatedSearchResult | undefined>;

/**
* Filter applied tracking payload
*/
export interface TrackFilterAppliedPayload {
category: string;
fromSearchAll: boolean;
searchTerm: string;
section: string;
selected: boolean;
value: string;
}

/**
* Filter applied tracking function
*/
export type TrackFilterAppliedFunction = (
payload: TrackFilterAppliedPayload
) => void;

/**
* Filter opened tracking payload
*/
export interface TrackFilterOpenedPayload {
category: string;
}

/**
* Filter opened tracking function
*/
export type TrackFilterOpenedFunction = (
payload: TrackFilterOpenedPayload
) => void;

interface TrackingConfig {
trackFilterApplied?: TrackFilterAppliedFunction;
trackFilterOpened?: TrackFilterOpenedFunction;
}

/**
* Product of the related search function.
*/
Expand Down Expand Up @@ -321,6 +359,7 @@ export interface SiteConfig {
redirectRootToPath: string;
summaryConfig?: SummaryConfig;
themeOptions?: ThemeOptions;
trackingConfig?: TrackingConfig;
}

/**
Expand Down
4 changes: 3 additions & 1 deletion packages/data-explorer-ui/src/hooks/useCategoryFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ export interface FilterInstance {
export type OnFilterFn = (
categoryKey: CategoryKey,
selectedCategoryValue: CategoryValueKey,
selected: boolean
selected: boolean,
categorySection?: string,
searchTerm?: string
) => void;

/**
Expand Down
Loading

0 comments on commit b5944dc

Please sign in to comment.