Skip to content

Commit

Permalink
feat: add tracking config (altos-labs/data-browser#344)
Browse files Browse the repository at this point in the history
  • Loading branch information
hunterckx committed Dec 5, 2023
1 parent 3c209ee commit e00b535
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 88 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { CloseRounded } from "@mui/icons-material";
import { Grow, PopoverPosition, PopoverProps } from "@mui/material";
import { TrackFilterOpenedFunction } from "config/entities";
import React, { MouseEvent, ReactNode, useState } from "react";
import { SelectCategoryView } from "../../../../common/entities";
import {
OnFilterFn,
OnFilterOpenedFn,
} from "../../../../hooks/useCategoryFilter";
import { OnFilterFn } from "../../../../hooks/useCategoryFilter";
import { CloseDrawerIconButton } from "../../../common/IconButton/iconButton.styles";
import { FilterLabel } from "../FilterLabel/filterLabel";
import { FilterMenu } from "../FilterMenu/filterMenu";
Expand All @@ -26,8 +24,8 @@ export interface FilterProps {
closeAncestor?: () => void;
isFilterDrawer: boolean;
onFilter: OnFilterFn;
onFilterOpened?: OnFilterOpenedFn;
tags?: ReactNode; // e.g. filter tags
trackFilterOpened?: TrackFilterOpenedFunction;
}

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

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
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 {
BREAKPOINT_FN_NAME,
useBreakpointHelper,
} from "../../../../hooks/useBreakpointHelper";
import {
OnFilterFn,
OnFilterOpenedFn,
} from "../../../../hooks/useCategoryFilter";
import { OnFilterFn } from "../../../../hooks/useCategoryFilter";
import { useWindowResize } from "../../../../hooks/useWindowResize";
import { DESKTOP_SM } from "../../../../theme/common/breakpoints";
import { Filter } from "../Filter/filter";
Expand All @@ -25,7 +23,7 @@ export interface FiltersProps {
closeAncestor?: () => void;
disabled: boolean; // Global disabling of filters; typically in "related" entity view.
onFilter: OnFilterFn;
onFilterOpened?: OnFilterOpenedFn;
trackFilterOpened?: TrackFilterOpenedFunction;
}

/**
Expand Down Expand Up @@ -69,7 +67,7 @@ export const Filters = ({
closeAncestor,
disabled = false,
onFilter,
onFilterOpened,
trackFilterOpened,
}: FiltersProps): JSX.Element => {
const isFilterDrawer = useBreakpointHelper(
BREAKPOINT_FN_NAME.DOWN,
Expand All @@ -96,7 +94,7 @@ export const Filters = ({
closeAncestor={closeAncestor}
isFilterDrawer={isFilterDrawer}
onFilter={onFilter}
onFilterOpened={onFilterOpened}
trackFilterOpened={trackFilterOpened}
tags={renderFilterTags(categoryView, onFilter)}
/>
))}
Expand Down
36 changes: 18 additions & 18 deletions packages/data-explorer-ui/src/config/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,21 +278,26 @@ type RelatedSearchFunction = (
) => Promise<RelatedSearchResult | undefined>;

/**
* Category clicked callback function
* Filter applied tracking function
*/
type CategoryClickedFunction = (
key: string,
value: string,
section: string,
selected: boolean,
fromSearchAll: boolean,
searchTerm: string
) => void;
export type TrackFilterAppliedFunction = (payload: {
category: string;
fromSearchAll: boolean;
searchTerm: string;
section: string;
selected: boolean;
value: string;
}) => void;

/**
* Category opened callback function
* Filter opened tracking function
*/
type CategoryOpenedFunction = (key: string) => void;
export type TrackFilterOpenedFunction = (payload: { category: string }) => void;

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

/**
* Product of the related search function.
Expand All @@ -312,12 +317,6 @@ export interface RelatedViewConfig {
searchKey: CategoryKey; // The related search function search parameters' category key.
}

export interface CategorySiteConfig {
categoryGroupConfigs?: CategoryGroupConfig[];
onCategoryClicked?: CategoryClickedFunction;
onCategoryOpened?: CategoryOpenedFunction;
}

/**
* Interface that will hold the whole configuration for a given site.
*/
Expand All @@ -326,7 +325,7 @@ export interface SiteConfig {
appTitle: string;
authentication?: AuthenticationConfig;
browserURL: string;
categorySiteConfig?: CategorySiteConfig;
categoryGroupConfigs?: CategoryGroupConfig[];
contentDir?: string;
contentThemeOptionsFn?: ThemeOptionsFn;
dataSource: DataSourceConfig;
Expand All @@ -342,6 +341,7 @@ export interface SiteConfig {
redirectRootToPath: string;
summaryConfig?: SummaryConfig;
themeOptions?: ThemeOptions;
trackingConfig?: TrackingConfig;
}

/**
Expand Down
6 changes: 3 additions & 3 deletions packages/data-explorer-ui/src/hooks/useCategoryConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import { useConfig } from "./useConfig";
*/
export const useCategoryConfigs = (): CategoryConfig[] | undefined => {
const { config } = useConfig();
const { categorySiteConfig } = config;
const { categoryGroupConfigs } = config;
return useMemo(() => {
return categorySiteConfig?.categoryGroupConfigs?.flatMap(
return categoryGroupConfigs?.flatMap(
({ categoryConfigs }) => categoryConfigs
);
}, [categorySiteConfig?.categoryGroupConfigs]);
}, [categoryGroupConfigs]);
};
5 changes: 0 additions & 5 deletions packages/data-explorer-ui/src/hooks/useCategoryFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ export type OnFilterFn = (
searchTerm?: string
) => void;

/**
* Callback function invoked when a filter menu is opened
*/
export type OnFilterOpenedFn = (key: CategoryKey) => void;

/**
* Build the view-specific model of the given category value.
* @param categoryValue - The category value to build a view model of.
Expand Down
94 changes: 46 additions & 48 deletions packages/data-explorer-ui/src/views/ExploreView/exploreView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,13 @@ export const ExploreView = (props: ExploreViewProps): JSX.Element => {
const tabletDown = useBreakpointHelper(BREAKPOINT_FN_NAME.DOWN, DESKTOP_SM);
const { config, entityConfig } = useConfig(); // Get app level config.
const { exploreDispatch, exploreState } = useExploreState(); // Get the useReducer state and dispatch for "Explore".
const { categorySiteConfig, entities, explorerTitle, summaryConfig } = config;
const {
categoryGroupConfigs,
entities,
explorerTitle,
summaryConfig,
trackingConfig,
} = config;
const { listView } = entityConfig;
const { listHero, subTitleHero } = listView || {};
const { categoryViews, isRelatedView, tabValue } = exploreState;
Expand All @@ -78,12 +84,8 @@ export const ExploreView = (props: ExploreViewProps): JSX.Element => {
useEntityListRelatedView(); // Fetch related entities.
const { entityListType } = props;
const categoryFilters = useMemo(
() =>
buildCategoryFilters(
categoryViews,
categorySiteConfig?.categoryGroupConfigs
),
[categoryViews, categorySiteConfig?.categoryGroupConfigs]
() => buildCategoryFilters(categoryViews, categoryGroupConfigs),
[categoryViews, categoryGroupConfigs]
);

/**
Expand All @@ -96,49 +98,45 @@ export const ExploreView = (props: ExploreViewProps): JSX.Element => {
/**
* Callback fired when selected state of a category value is toggled.
* @param fromSearchAll - Infication if the filter was originated from the search all field
* @returns - a function to be used as filter change callback.
* * @param categoryKey - The category being filtered.
* * @param selectedCategoryValue - The value to set or clear.
* * @param selected - Indication of whether the selected value is being set or cleared.
* @param categoryKey - The category being filtered.
* @param selectedCategoryValue - The value to set or clear.
* @param selected - Indication of whether the selected value is being set or cleared.
* @param categorySection -
* @param searchTerm -
*/
const onFilterChange =
(fromSearchAll: boolean) =>
(
categoryKey: CategoryKey,
selectedCategoryValue: CategoryValueKey,
selected: boolean,
categorySection?: string,
searchTerm?: string
): void => {
exploreDispatch({
payload: {
categoryKey,
selected,
selectedValue: selectedCategoryValue,
},
type: ExploreActionKind.UpdateFilter,
});

categorySiteConfig?.onCategoryClicked?.(
const onFilterChange = (
fromSearchAll: boolean,
categoryKey: CategoryKey,
selectedCategoryValue: CategoryValueKey,
selected: boolean,
categorySection?: string,
searchTerm?: string
): void => {
exploreDispatch({
payload: {
categoryKey,
selectedCategoryValue,
categorySection ?? "",
selected,
fromSearchAll,
searchTerm ?? ""
);
selectedValue: selectedCategoryValue,
},
type: ExploreActionKind.UpdateFilter,
});

// Execute GTM tracking.
if (selected) {
track(EVENT_NAME.FILTER_SELECTED, {
[EVENT_PARAM.FILTER_NAME]: categoryKey,
[EVENT_PARAM.FILTER_VALUE]: selectedCategoryValue,
});
}
};
trackingConfig?.trackFilterApplied({
category: categoryKey,
fromSearchAll,
searchTerm: searchTerm ?? "",
section: categorySection ?? "",
selected,
value: selectedCategoryValue,
});

const onFilterOpened = (key: string): void => {
categorySiteConfig?.onCategoryOpened?.(key);
// Execute GTM tracking.
if (selected) {
track(EVENT_NAME.FILTER_SELECTED, {
[EVENT_PARAM.FILTER_NAME]: categoryKey,
[EVENT_PARAM.FILTER_VALUE]: selectedCategoryValue,
});
}
};

/**
Expand Down Expand Up @@ -183,15 +181,15 @@ export const ExploreView = (props: ExploreViewProps): JSX.Element => {
<SearchAllFilters
categoryViews={categoryViews}
drawerOpen={isDrawerOpen}
onFilter={onFilterChange(true)}
onFilter={onFilterChange.bind(null, true)}
/>
</SidebarTools>
<Filters
categoryFilters={categoryFilters}
closeAncestor={onCloseDrawer}
disabled={isRelatedView}
onFilter={onFilterChange(false)}
onFilterOpened={onFilterOpened}
onFilter={onFilterChange.bind(null, false)}
trackFilterOpened={trackingConfig?.trackFilterOpened}
/>
</Sidebar>
)}
Expand Down

0 comments on commit e00b535

Please sign in to comment.