feat: search activities (#972)
This commit is contained in:
@ -2522,7 +2522,7 @@ export type SearchPeopleQueryVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type SearchPeopleQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Person', id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, createdAt: string }> };
|
export type SearchPeopleQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Person', id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, createdAt: string }> };
|
||||||
|
|
||||||
export type SearchUserQueryVariables = Exact<{
|
export type SearchUserQueryVariables = Exact<{
|
||||||
where?: InputMaybe<UserWhereInput>;
|
where?: InputMaybe<UserWhereInput>;
|
||||||
@ -2547,6 +2547,15 @@ export type SearchCompanyQueryVariables = Exact<{
|
|||||||
|
|
||||||
export type SearchCompanyQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> };
|
export type SearchCompanyQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> };
|
||||||
|
|
||||||
|
export type SearchActivityQueryVariables = Exact<{
|
||||||
|
where?: InputMaybe<ActivityWhereInput>;
|
||||||
|
limit?: InputMaybe<Scalars['Int']>;
|
||||||
|
orderBy?: InputMaybe<Array<ActivityOrderByWithRelationInput> | ActivityOrderByWithRelationInput>;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type SearchActivityQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Activity', id: string, title?: string | null, body?: string | null }> };
|
||||||
|
|
||||||
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
@ -4367,6 +4376,7 @@ export const SearchPeopleDocument = gql`
|
|||||||
city
|
city
|
||||||
firstName
|
firstName
|
||||||
lastName
|
lastName
|
||||||
|
displayName
|
||||||
createdAt
|
createdAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4516,6 +4526,49 @@ export function useSearchCompanyLazyQuery(baseOptions?: Apollo.LazyQueryHookOpti
|
|||||||
export type SearchCompanyQueryHookResult = ReturnType<typeof useSearchCompanyQuery>;
|
export type SearchCompanyQueryHookResult = ReturnType<typeof useSearchCompanyQuery>;
|
||||||
export type SearchCompanyLazyQueryHookResult = ReturnType<typeof useSearchCompanyLazyQuery>;
|
export type SearchCompanyLazyQueryHookResult = ReturnType<typeof useSearchCompanyLazyQuery>;
|
||||||
export type SearchCompanyQueryResult = Apollo.QueryResult<SearchCompanyQuery, SearchCompanyQueryVariables>;
|
export type SearchCompanyQueryResult = Apollo.QueryResult<SearchCompanyQuery, SearchCompanyQueryVariables>;
|
||||||
|
export const SearchActivityDocument = gql`
|
||||||
|
query SearchActivity($where: ActivityWhereInput, $limit: Int, $orderBy: [ActivityOrderByWithRelationInput!]) {
|
||||||
|
searchResults: findManyActivities(
|
||||||
|
where: $where
|
||||||
|
take: $limit
|
||||||
|
orderBy: $orderBy
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useSearchActivityQuery__
|
||||||
|
*
|
||||||
|
* To run a query within a React component, call `useSearchActivityQuery` and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useSearchActivityQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
|
* you can use to render your UI.
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const { data, loading, error } = useSearchActivityQuery({
|
||||||
|
* variables: {
|
||||||
|
* where: // value for 'where'
|
||||||
|
* limit: // value for 'limit'
|
||||||
|
* orderBy: // value for 'orderBy'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useSearchActivityQuery(baseOptions?: Apollo.QueryHookOptions<SearchActivityQuery, SearchActivityQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useQuery<SearchActivityQuery, SearchActivityQueryVariables>(SearchActivityDocument, options);
|
||||||
|
}
|
||||||
|
export function useSearchActivityLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<SearchActivityQuery, SearchActivityQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useLazyQuery<SearchActivityQuery, SearchActivityQueryVariables>(SearchActivityDocument, options);
|
||||||
|
}
|
||||||
|
export type SearchActivityQueryHookResult = ReturnType<typeof useSearchActivityQuery>;
|
||||||
|
export type SearchActivityLazyQueryHookResult = ReturnType<typeof useSearchActivityLazyQuery>;
|
||||||
|
export type SearchActivityQueryResult = Apollo.QueryResult<SearchActivityQuery, SearchActivityQueryVariables>;
|
||||||
export const GetCurrentUserDocument = gql`
|
export const GetCurrentUserDocument = gql`
|
||||||
query GetCurrentUser {
|
query GetCurrentUser {
|
||||||
currentUser {
|
currentUser {
|
||||||
|
|||||||
@ -107,7 +107,7 @@ export function Timeline({ entity }: { entity: CommentableEntity }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const openCreateCommandThread = useOpenCreateActivityDrawer();
|
const openCreateActivity = useOpenCreateActivityDrawer();
|
||||||
|
|
||||||
const activities: ActivityForDrawer[] = queryResult?.findManyActivities ?? [];
|
const activities: ActivityForDrawer[] = queryResult?.findManyActivities ?? [];
|
||||||
|
|
||||||
@ -121,8 +121,8 @@ export function Timeline({ entity }: { entity: CommentableEntity }) {
|
|||||||
<StyledEmptyTimelineTitle>No activity yet</StyledEmptyTimelineTitle>
|
<StyledEmptyTimelineTitle>No activity yet</StyledEmptyTimelineTitle>
|
||||||
<StyledEmptyTimelineSubTitle>Create one:</StyledEmptyTimelineSubTitle>
|
<StyledEmptyTimelineSubTitle>Create one:</StyledEmptyTimelineSubTitle>
|
||||||
<ActivityCreateButton
|
<ActivityCreateButton
|
||||||
onNoteClick={() => openCreateCommandThread(entity, ActivityType.Note)}
|
onNoteClick={() => openCreateActivity(entity, ActivityType.Note)}
|
||||||
onTaskClick={() => openCreateCommandThread(entity, ActivityType.Task)}
|
onTaskClick={() => openCreateActivity(entity, ActivityType.Task)}
|
||||||
/>
|
/>
|
||||||
</StyledTimelineEmptyContainer>
|
</StyledTimelineEmptyContainer>
|
||||||
);
|
);
|
||||||
@ -132,8 +132,8 @@ export function Timeline({ entity }: { entity: CommentableEntity }) {
|
|||||||
<StyledMainContainer>
|
<StyledMainContainer>
|
||||||
<StyledTopActionBar>
|
<StyledTopActionBar>
|
||||||
<ActivityCreateButton
|
<ActivityCreateButton
|
||||||
onNoteClick={() => openCreateCommandThread(entity, ActivityType.Note)}
|
onNoteClick={() => openCreateActivity(entity, ActivityType.Note)}
|
||||||
onTaskClick={() => openCreateCommandThread(entity, ActivityType.Task)}
|
onTaskClick={() => openCreateActivity(entity, ActivityType.Task)}
|
||||||
/>
|
/>
|
||||||
</StyledTopActionBar>
|
</StyledTopActionBar>
|
||||||
<StyledTimelineContainer>
|
<StyledTimelineContainer>
|
||||||
|
|||||||
@ -1,11 +1,18 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { useFilteredSearchCompanyQuery } from '@/companies/queries';
|
import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer';
|
||||||
import { useFilteredSearchPeopleQuery } from '@/people/queries';
|
|
||||||
import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys';
|
||||||
import { AppHotkeyScope } from '@/ui/hotkey/types/AppHotkeyScope';
|
import { AppHotkeyScope } from '@/ui/hotkey/types/AppHotkeyScope';
|
||||||
|
import { IconNotes } from '@/ui/icon';
|
||||||
import { Avatar } from '@/users/components/Avatar';
|
import { Avatar } from '@/users/components/Avatar';
|
||||||
|
import {
|
||||||
|
QueryMode,
|
||||||
|
useSearchActivityQuery,
|
||||||
|
useSearchCompanyQuery,
|
||||||
|
useSearchPeopleQuery,
|
||||||
|
} from '~/generated/graphql';
|
||||||
|
import { getLogoUrlFromDomainName } from '~/utils';
|
||||||
|
|
||||||
import { useCommandMenu } from '../hooks/useCommandMenu';
|
import { useCommandMenu } from '../hooks/useCommandMenu';
|
||||||
import { isCommandMenuOpenedState } from '../states/isCommandMenuOpenedState';
|
import { isCommandMenuOpenedState } from '../states/isCommandMenuOpenedState';
|
||||||
@ -21,6 +28,7 @@ import {
|
|||||||
|
|
||||||
export function CommandMenu() {
|
export function CommandMenu() {
|
||||||
const { openCommandMenu, closeCommandMenu } = useCommandMenu();
|
const { openCommandMenu, closeCommandMenu } = useCommandMenu();
|
||||||
|
const openActivityRightDrawer = useOpenActivityRightDrawer();
|
||||||
const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState);
|
const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState);
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
|
|
||||||
@ -33,16 +41,41 @@ export function CommandMenu() {
|
|||||||
[openCommandMenu],
|
[openCommandMenu],
|
||||||
);
|
);
|
||||||
|
|
||||||
const people = useFilteredSearchPeopleQuery({
|
const { data: peopleData } = useSearchPeopleQuery({
|
||||||
searchFilter: search,
|
variables: {
|
||||||
selectedIds: [],
|
where: {
|
||||||
limit: 3,
|
OR: [
|
||||||
|
{ firstName: { contains: search, mode: QueryMode.Insensitive } },
|
||||||
|
{ lastName: { contains: search, mode: QueryMode.Insensitive } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
limit: 3,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const companies = useFilteredSearchCompanyQuery({
|
const people = peopleData?.searchResults ?? [];
|
||||||
searchFilter: search,
|
|
||||||
selectedIds: [],
|
const { data: companyData } = useSearchCompanyQuery({
|
||||||
limit: 3,
|
variables: {
|
||||||
|
where: {
|
||||||
|
OR: [{ name: { contains: search, mode: QueryMode.Insensitive } }],
|
||||||
|
},
|
||||||
|
limit: 3,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
const companies = companyData?.searchResults ?? [];
|
||||||
|
|
||||||
|
const { data: activityData } = useSearchActivityQuery({
|
||||||
|
variables: {
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ title: { contains: search, mode: QueryMode.Insensitive } },
|
||||||
|
{ body: { contains: search, mode: QueryMode.Insensitive } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
limit: 3,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const activities = activityData?.searchResults ?? [];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: Allow performing actions on page through CommandBar
|
TODO: Allow performing actions on page through CommandBar
|
||||||
@ -99,35 +132,35 @@ export function CommandMenu() {
|
|||||||
/>
|
/>
|
||||||
<StyledList>
|
<StyledList>
|
||||||
<StyledEmpty>No results found.</StyledEmpty>
|
<StyledEmpty>No results found.</StyledEmpty>
|
||||||
{!!people.entitiesToSelect.length && (
|
{!!people.length && (
|
||||||
<StyledGroup heading="People">
|
<StyledGroup heading="People">
|
||||||
{people.entitiesToSelect.map((person) => (
|
{people.map((person) => (
|
||||||
<CommandMenuItem
|
<CommandMenuItem
|
||||||
to={`person/${person.id}`}
|
to={`person/${person.id}`}
|
||||||
label={person.name}
|
label={person.displayName}
|
||||||
key={person.id}
|
key={person.id}
|
||||||
icon={
|
icon={
|
||||||
<Avatar
|
<Avatar
|
||||||
avatarUrl={person.avatarUrl}
|
avatarUrl={null}
|
||||||
size="sm"
|
size="sm"
|
||||||
colorId={person.id}
|
colorId={person.id}
|
||||||
placeholder={person.name}
|
placeholder={person.displayName}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</StyledGroup>
|
</StyledGroup>
|
||||||
)}
|
)}
|
||||||
{!!companies.entitiesToSelect.length && (
|
{!!companies.length && (
|
||||||
<StyledGroup heading="Companies">
|
<StyledGroup heading="Companies">
|
||||||
{companies.entitiesToSelect.map((company) => (
|
{companies.map((company) => (
|
||||||
<CommandMenuItem
|
<CommandMenuItem
|
||||||
to={`companies/${company.id}`}
|
to={`companies/${company.id}`}
|
||||||
label={company.name}
|
label={company.name}
|
||||||
key={company.id}
|
key={company.id}
|
||||||
icon={
|
icon={
|
||||||
<Avatar
|
<Avatar
|
||||||
avatarUrl={company.avatarUrl}
|
avatarUrl={getLogoUrlFromDomainName(company.domainName)}
|
||||||
size="sm"
|
size="sm"
|
||||||
colorId={company.id}
|
colorId={company.id}
|
||||||
placeholder={company.name}
|
placeholder={company.name}
|
||||||
@ -137,6 +170,18 @@ export function CommandMenu() {
|
|||||||
))}
|
))}
|
||||||
</StyledGroup>
|
</StyledGroup>
|
||||||
)}
|
)}
|
||||||
|
{!!activities.length && (
|
||||||
|
<StyledGroup heading="Notes">
|
||||||
|
{activities.map((activity) => (
|
||||||
|
<CommandMenuItem
|
||||||
|
onClick={() => openActivityRightDrawer(activity.id)}
|
||||||
|
label={activity.title ?? ''}
|
||||||
|
key={activity.id}
|
||||||
|
icon={<IconNotes />}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</StyledGroup>
|
||||||
|
)}
|
||||||
<StyledGroup heading="Navigate">
|
<StyledGroup heading="Navigate">
|
||||||
<CommandMenuItem
|
<CommandMenuItem
|
||||||
to="/people"
|
to="/people"
|
||||||
|
|||||||
@ -17,6 +17,8 @@ export const SEARCH_PEOPLE_QUERY = gql`
|
|||||||
city
|
city
|
||||||
firstName
|
firstName
|
||||||
lastName
|
lastName
|
||||||
|
displayName
|
||||||
|
avatarUrl
|
||||||
createdAt
|
createdAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,3 +70,21 @@ export const SEARCH_COMPANY_QUERY = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const SEARCH_ACTIVITY_QUERY = gql`
|
||||||
|
query SearchActivity(
|
||||||
|
$where: ActivityWhereInput
|
||||||
|
$limit: Int
|
||||||
|
$orderBy: [ActivityOrderByWithRelationInput!]
|
||||||
|
) {
|
||||||
|
searchResults: findManyActivities(
|
||||||
|
where: $where
|
||||||
|
take: $limit
|
||||||
|
orderBy: $orderBy
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user