diff --git a/packages/client/components/ActivityLibrary/ActivityDetails/ActivityDetails.tsx b/packages/client/components/ActivityLibrary/ActivityDetails/ActivityDetails.tsx index aafbb30bda8..9f2b0114815 100644 --- a/packages/client/components/ActivityLibrary/ActivityDetails/ActivityDetails.tsx +++ b/packages/client/components/ActivityLibrary/ActivityDetails/ActivityDetails.tsx @@ -1,6 +1,6 @@ import graphql from 'babel-plugin-relay/macro' import clsx from 'clsx' -import React, {useState} from 'react' +import React, {useEffect, useState} from 'react' import {PreloadedQuery, usePreloadedQuery} from 'react-relay' import {Redirect, useHistory} from 'react-router' import {Link} from 'react-router-dom' @@ -11,6 +11,8 @@ import {ActivityCard, ActivityCardImage} from '../ActivityCard' import ActivityDetailsSidebar from '../ActivityDetailsSidebar' import {CategoryID, CATEGORY_THEMES, QUICK_START_CATEGORY_ID} from '../Categories' import {TemplateDetails} from './TemplateDetails' +import SendClientSideEvent from '../../../utils/SendClientSideEvent' +import useAtmosphere from '../../../hooks/useAtmosphere' graphql` fragment ActivityDetails_template on MeetingTemplate { @@ -37,6 +39,7 @@ export const query = graphql` query ActivityDetailsQuery($activityId: ID!) { viewer { ...ActivityDetailsSidebar_viewer + activityLibrarySearch preferredTeamId tier activity(activityId: $activityId) { @@ -61,16 +64,27 @@ interface Props { } const ActivityDetails = (props: Props) => { + const atmosphere = useAtmosphere() const {queryRef} = props const data = usePreloadedQuery(query, queryRef) const {viewer} = data - const {activity, preferredTeamId, teams} = viewer + const {activity, activityLibrarySearch, preferredTeamId, teams} = viewer const history = useHistory<{prevCategory?: string}>() const [isEditing, setIsEditing] = useState(false) if (!activity) { return } + useEffect(() => { + SendClientSideEvent(atmosphere, 'Viewed Template', { + meetingType: activity.type, + scope: activity.scope, + templateName: activity.name, + isFree: activity.isFree, + queryString: activityLibrarySearch + }) + }, []) + const {category, illustrationUrl, viewerLowestScope} = activity const prevCategory = history.location.state?.prevCategory const categoryLink = `/activity-library/category/${ diff --git a/packages/client/components/ActivityLibrary/ActivityLibrary.tsx b/packages/client/components/ActivityLibrary/ActivityLibrary.tsx index fef35dfe33d..c11bb1822a5 100644 --- a/packages/client/components/ActivityLibrary/ActivityLibrary.tsx +++ b/packages/client/components/ActivityLibrary/ActivityLibrary.tsx @@ -1,8 +1,8 @@ import * as ScrollArea from '@radix-ui/react-scroll-area' import graphql from 'babel-plugin-relay/macro' import clsx from 'clsx' -import React, {useMemo} from 'react' -import {PreloadedQuery, usePreloadedQuery} from 'react-relay' +import React, {useEffect, useMemo} from 'react' +import {PreloadedQuery, commitLocalUpdate, usePreloadedQuery} from 'react-relay' import {Redirect} from 'react-router' import {Link} from 'react-router-dom' import {ActivityLibraryQuery} from '~/__generated__/ActivityLibraryQuery.graphql' @@ -25,6 +25,9 @@ import { } from './Categories' import CreateActivityCard from './CreateActivityCard' import SearchBar from './SearchBar' +import useAtmosphere from '../../hooks/useAtmosphere' +import SendClientSideEvent from '../../utils/SendClientSideEvent' +import {useDebounce} from 'use-debounce' graphql` fragment ActivityLibrary_templateSearchDocument on MeetingTemplate { @@ -189,12 +192,21 @@ const ActivityGrid = ({templates, selectedCategory}: ActivityGridProps) => { const MAX_PER_SUBCATEGORY = 6 export const ActivityLibrary = (props: Props) => { + const atmosphere = useAtmosphere() const {queryRef} = props const data = usePreloadedQuery(query, queryRef) const {viewer} = data const {featureFlags, availableTemplates, organizations} = viewer const hasOneOnOneFeatureFlag = !!organizations.find((org) => org.featureFlags.oneOnOne) + const setSearch = (value: string) => { + commitLocalUpdate(atmosphere, (store) => { + const viewer = store.getRoot().getLinkedRecord('viewer') + if (!viewer) return + viewer.setValue(value, 'activityLibrarySearch') + }) + } + const templates = useMemo(() => { const templatesMap = availableTemplates.edges.map((edge) => edge.node) if (!hasOneOnOneFeatureFlag) { @@ -211,6 +223,15 @@ export const ActivityLibrary = (props: Props) => { onQueryChange, resetQuery } = useSearchFilter(templates, getTemplateDocumentValue) + const [debouncedSearchQuery] = useDebounce(searchQuery, 500) + + useEffect(() => { + if (debouncedSearchQuery) { + SendClientSideEvent(atmosphere, 'Activity Library Searched', { + debouncedSearchQuery + }) + } + }, [debouncedSearchQuery]) const {match} = useRouter<{categoryId?: string}>() const { @@ -279,7 +300,13 @@ export const ActivityLibrary = (props: Props) => {
- + { + onQueryChange(e) + setSearch(e.target.value) + }} + />
{
- + { + onQueryChange(e) + setSearch(e.target.value) + }} + />
diff --git a/packages/client/package.json b/packages/client/package.json index 03bdf735627..996c001ec16 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -145,6 +145,7 @@ "tayden-clusterfck": "^0.7.0", "tlds": "^1.192.0", "tslib": "^2.4.0", - "unicode-substring": "^1.0.0" + "unicode-substring": "^1.0.0", + "use-debounce": "^10.0.0" } } diff --git a/packages/client/schemaExtensions/clientSchema.graphql b/packages/client/schemaExtensions/clientSchema.graphql index e97c41c53d8..915fbf7685a 100644 --- a/packages/client/schemaExtensions/clientSchema.graphql +++ b/packages/client/schemaExtensions/clientSchema.graphql @@ -69,6 +69,7 @@ extend type User { # If positive, client clock is ahead of server clock by this many ms clientClockOffset: Int dashSearch: String + activityLibrarySearch: String pageName: String # The team we should default to in team pickers, etc. preferredTeamId: ID diff --git a/yarn.lock b/yarn.lock index 0f5a51d2d7e..a8809b5d326 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23289,6 +23289,11 @@ use-composed-ref@^1.3.0: resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.3.0.tgz#3d8104db34b7b264030a9d916c5e94fbe280dbda" integrity sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ== +use-debounce@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-10.0.0.tgz#5091b18d6c16292605f588bae3c0d2cfae756ff2" + integrity sha512-XRjvlvCB46bah9IBXVnq/ACP2lxqXyZj0D9hj4K5OzNroMDpTEBg8Anuh1/UfRTRs7pLhQ+RiNxxwZu9+MVl1A== + use-isomorphic-layout-effect@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb"