Feat/account owner picker (#359)
* Added account owner picker * Regenerated graphql files * Fixed pickers staying in edit mode with a new generic hook * Fixed lint
This commit is contained in:
@ -1359,16 +1359,6 @@ export type User = {
|
|||||||
workspaceMember?: Maybe<WorkspaceMember>;
|
workspaceMember?: Maybe<WorkspaceMember>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type UserCompaniesArgs = {
|
|
||||||
cursor?: InputMaybe<CompanyWhereUniqueInput>;
|
|
||||||
distinct?: InputMaybe<Array<CompanyScalarFieldEnum>>;
|
|
||||||
orderBy?: InputMaybe<Array<CompanyOrderByWithRelationInput>>;
|
|
||||||
skip?: InputMaybe<Scalars['Int']>;
|
|
||||||
take?: InputMaybe<Scalars['Int']>;
|
|
||||||
where?: InputMaybe<CompanyWhereInput>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UserCreateNestedOneWithoutCommentsInput = {
|
export type UserCreateNestedOneWithoutCommentsInput = {
|
||||||
connect?: InputMaybe<UserWhereUniqueInput>;
|
connect?: InputMaybe<UserWhereUniqueInput>;
|
||||||
};
|
};
|
||||||
@ -1527,6 +1517,7 @@ export type WorkspaceMember = {
|
|||||||
user: User;
|
user: User;
|
||||||
userId: Scalars['String'];
|
userId: Scalars['String'];
|
||||||
workspace: Workspace;
|
workspace: Workspace;
|
||||||
|
workspaceId: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreateCommentMutationVariables = Exact<{
|
export type CreateCommentMutationVariables = Exact<{
|
||||||
@ -1706,6 +1697,7 @@ export type SearchPeopleQuery = { __typename?: 'Query', searchResults: Array<{ _
|
|||||||
export type SearchUserQueryVariables = Exact<{
|
export type SearchUserQueryVariables = Exact<{
|
||||||
where?: InputMaybe<UserWhereInput>;
|
where?: InputMaybe<UserWhereInput>;
|
||||||
limit?: InputMaybe<Scalars['Int']>;
|
limit?: InputMaybe<Scalars['Int']>;
|
||||||
|
orderBy?: InputMaybe<Array<UserOrderByWithRelationInput> | UserOrderByWithRelationInput>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
@ -2575,8 +2567,8 @@ export type SearchPeopleQueryHookResult = ReturnType<typeof useSearchPeopleQuery
|
|||||||
export type SearchPeopleLazyQueryHookResult = ReturnType<typeof useSearchPeopleLazyQuery>;
|
export type SearchPeopleLazyQueryHookResult = ReturnType<typeof useSearchPeopleLazyQuery>;
|
||||||
export type SearchPeopleQueryResult = Apollo.QueryResult<SearchPeopleQuery, SearchPeopleQueryVariables>;
|
export type SearchPeopleQueryResult = Apollo.QueryResult<SearchPeopleQuery, SearchPeopleQueryVariables>;
|
||||||
export const SearchUserDocument = gql`
|
export const SearchUserDocument = gql`
|
||||||
query SearchUser($where: UserWhereInput, $limit: Int) {
|
query SearchUser($where: UserWhereInput, $limit: Int, $orderBy: [UserOrderByWithRelationInput!]) {
|
||||||
searchResults: findManyUser(where: $where, take: $limit) {
|
searchResults: findManyUser(where: $where, take: $limit, orderBy: $orderBy) {
|
||||||
id
|
id
|
||||||
email
|
email
|
||||||
displayName
|
displayName
|
||||||
@ -2598,6 +2590,7 @@ export const SearchUserDocument = gql`
|
|||||||
* variables: {
|
* variables: {
|
||||||
* where: // value for 'where'
|
* where: // value for 'where'
|
||||||
* limit: // value for 'limit'
|
* limit: // value for 'limit'
|
||||||
|
* orderBy: // value for 'orderBy'
|
||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { PersonChip } from '@/people/components/PersonChip';
|
||||||
|
import { EditableCellV2 } from '@/ui/components/editable-cell/EditableCellV2';
|
||||||
|
import { Company, User } from '~/generated/graphql';
|
||||||
|
|
||||||
|
import { CompanyAccountOwnerPicker } from './CompanyAccountOwnerPicker';
|
||||||
|
|
||||||
|
export type OwnProps = {
|
||||||
|
company: Pick<Company, 'id'> & {
|
||||||
|
accountOwner?: Pick<User, 'id' | 'displayName'> | null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export function CompanyAccountOwnerCell({ company }: OwnProps) {
|
||||||
|
return (
|
||||||
|
<EditableCellV2
|
||||||
|
editModeContent={<CompanyAccountOwnerPicker company={company} />}
|
||||||
|
nonEditModeContent={
|
||||||
|
company.accountOwner?.displayName ? (
|
||||||
|
<PersonChip name={company.accountOwner?.displayName ?? ''} />
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
import { SingleEntitySelect } from '@/relation-picker/components/SingleEntitySelect';
|
||||||
|
import { useFilteredSearchEntityQuery } from '@/relation-picker/hooks/useFilteredSearchEntityQuery';
|
||||||
|
import { relationPickerSearchFilterScopedState } from '@/relation-picker/states/relationPickerSearchFilterScopedState';
|
||||||
|
import { EntityForSelect } from '@/relation-picker/types/EntityForSelect';
|
||||||
|
import { Entity } from '@/relation-picker/types/EntityTypeForSelect';
|
||||||
|
import { useCloseEditableCell } from '@/ui/components/editable-cell/hooks/useCloseEditableCell';
|
||||||
|
import { useRecoilScopedState } from '@/ui/hooks/useRecoilScopedState';
|
||||||
|
import {
|
||||||
|
Company,
|
||||||
|
User,
|
||||||
|
useSearchUserQuery,
|
||||||
|
useUpdateCompanyMutation,
|
||||||
|
} from '~/generated/graphql';
|
||||||
|
|
||||||
|
export type OwnProps = {
|
||||||
|
company: Pick<Company, 'id'> & {
|
||||||
|
accountOwner?: Pick<User, 'id' | 'displayName'> | null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserForSelect = EntityForSelect & {
|
||||||
|
entityType: Entity.User;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function CompanyAccountOwnerPicker({ company }: OwnProps) {
|
||||||
|
const [searchFilter] = useRecoilScopedState(
|
||||||
|
relationPickerSearchFilterScopedState,
|
||||||
|
);
|
||||||
|
const [updateCompany] = useUpdateCompanyMutation();
|
||||||
|
|
||||||
|
const closeEditableCell = useCloseEditableCell();
|
||||||
|
|
||||||
|
const companies = useFilteredSearchEntityQuery({
|
||||||
|
queryHook: useSearchUserQuery,
|
||||||
|
selectedIds: [company?.accountOwner?.id ?? ''],
|
||||||
|
searchFilter: searchFilter,
|
||||||
|
mappingFunction: (user) => ({
|
||||||
|
entityType: Entity.User,
|
||||||
|
id: user.id,
|
||||||
|
name: user.displayName,
|
||||||
|
avatarType: 'rounded',
|
||||||
|
}),
|
||||||
|
orderByField: 'displayName',
|
||||||
|
searchOnFields: ['displayName'],
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleEntitySelected(selectedUser: UserForSelect) {
|
||||||
|
await updateCompany({
|
||||||
|
variables: {
|
||||||
|
...company,
|
||||||
|
accountOwnerId: selectedUser.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
closeEditableCell();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SingleEntitySelect
|
||||||
|
onEntitySelected={handleEntitySelected}
|
||||||
|
entities={{
|
||||||
|
entitiesToSelect: companies.entitiesToSelect,
|
||||||
|
selectedEntity: companies.selectedEntities[0],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,11 +1,9 @@
|
|||||||
import { useRecoilState } from 'recoil';
|
|
||||||
|
|
||||||
import { SingleEntitySelect } from '@/relation-picker/components/SingleEntitySelect';
|
import { SingleEntitySelect } from '@/relation-picker/components/SingleEntitySelect';
|
||||||
import { useFilteredSearchEntityQuery } from '@/relation-picker/hooks/useFilteredSearchEntityQuery';
|
import { useFilteredSearchEntityQuery } from '@/relation-picker/hooks/useFilteredSearchEntityQuery';
|
||||||
import { relationPickerSearchFilterScopedState } from '@/relation-picker/states/relationPickerSearchFilterScopedState';
|
import { relationPickerSearchFilterScopedState } from '@/relation-picker/states/relationPickerSearchFilterScopedState';
|
||||||
|
import { useCloseEditableCell } from '@/ui/components/editable-cell/hooks/useCloseEditableCell';
|
||||||
import { isCreateModeScopedState } from '@/ui/components/editable-cell/states/isCreateModeScopedState';
|
import { isCreateModeScopedState } from '@/ui/components/editable-cell/states/isCreateModeScopedState';
|
||||||
import { useRecoilScopedState } from '@/ui/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/ui/hooks/useRecoilScopedState';
|
||||||
import { isSomeInputInEditModeState } from '@/ui/tables/states/isSomeInputInEditModeState';
|
|
||||||
import { getLogoUrlFromDomainName } from '@/utils/utils';
|
import { getLogoUrlFromDomainName } from '@/utils/utils';
|
||||||
import {
|
import {
|
||||||
CommentableType,
|
CommentableType,
|
||||||
@ -26,9 +24,8 @@ export function PeopleCompanyPicker({ people }: OwnProps) {
|
|||||||
relationPickerSearchFilterScopedState,
|
relationPickerSearchFilterScopedState,
|
||||||
);
|
);
|
||||||
const [updatePeople] = useUpdatePeopleMutation();
|
const [updatePeople] = useUpdatePeopleMutation();
|
||||||
const [, setIsSomeInputInEditMode] = useRecoilState(
|
|
||||||
isSomeInputInEditModeState,
|
const closeEditableCell = useCloseEditableCell();
|
||||||
);
|
|
||||||
|
|
||||||
const companies = useFilteredSearchEntityQuery({
|
const companies = useFilteredSearchEntityQuery({
|
||||||
queryHook: useSearchCompanyQuery,
|
queryHook: useSearchCompanyQuery,
|
||||||
@ -46,14 +43,14 @@ export function PeopleCompanyPicker({ people }: OwnProps) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function handleEntitySelected(entity: any) {
|
async function handleEntitySelected(entity: any) {
|
||||||
setIsSomeInputInEditMode(false);
|
|
||||||
|
|
||||||
await updatePeople({
|
await updatePeople({
|
||||||
variables: {
|
variables: {
|
||||||
...people,
|
...people,
|
||||||
companyId: entity.id,
|
companyId: entity.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
closeEditableCell();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCreate() {
|
function handleCreate() {
|
||||||
|
|||||||
@ -1,3 +1,12 @@
|
|||||||
import { CommentableType, PipelineProgressableType } from '~/generated/graphql';
|
import { CommentableType, PipelineProgressableType } from '~/generated/graphql';
|
||||||
|
|
||||||
export type EntityTypeForSelect = CommentableType | PipelineProgressableType;
|
export enum Entity {
|
||||||
|
Company = 'Company',
|
||||||
|
Person = 'Person',
|
||||||
|
User = 'User',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type EntityTypeForSelect =
|
||||||
|
| CommentableType
|
||||||
|
| PipelineProgressableType
|
||||||
|
| Entity;
|
||||||
|
|||||||
@ -28,8 +28,16 @@ export const SEARCH_PEOPLE_QUERY = gql`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const SEARCH_USER_QUERY = gql`
|
export const SEARCH_USER_QUERY = gql`
|
||||||
query SearchUser($where: UserWhereInput, $limit: Int) {
|
query SearchUser(
|
||||||
searchResults: findManyUser(where: $where, take: $limit) {
|
$where: UserWhereInput
|
||||||
|
$limit: Int
|
||||||
|
$orderBy: [UserOrderByWithRelationInput!]
|
||||||
|
) {
|
||||||
|
searchResults: findManyUser(
|
||||||
|
where: $where
|
||||||
|
take: $limit
|
||||||
|
orderBy: $orderBy
|
||||||
|
) {
|
||||||
id
|
id
|
||||||
email
|
email
|
||||||
displayName
|
displayName
|
||||||
|
|||||||
@ -0,0 +1,19 @@
|
|||||||
|
import { useCallback } from 'react';
|
||||||
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
|
import { useRecoilScopedState } from '@/ui/hooks/useRecoilScopedState';
|
||||||
|
import { isSomeInputInEditModeState } from '@/ui/tables/states/isSomeInputInEditModeState';
|
||||||
|
|
||||||
|
import { isEditModeScopedState } from '../states/isEditModeScopedState';
|
||||||
|
|
||||||
|
export function useCloseEditableCell() {
|
||||||
|
const [, setIsSomeInputInEditMode] = useRecoilState(
|
||||||
|
isSomeInputInEditModeState,
|
||||||
|
);
|
||||||
|
const [, setIsEditMode] = useRecoilScopedState(isEditModeScopedState);
|
||||||
|
|
||||||
|
return useCallback(() => {
|
||||||
|
setIsSomeInputInEditMode(false);
|
||||||
|
setIsEditMode(false);
|
||||||
|
}, [setIsEditMode, setIsSomeInputInEditMode]);
|
||||||
|
}
|
||||||
@ -1,17 +1,12 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { createColumnHelper } from '@tanstack/react-table';
|
import { createColumnHelper } from '@tanstack/react-table';
|
||||||
|
|
||||||
|
import { CompanyAccountOwnerCell } from '@/companies/components/CompanyAccountOwnerCell';
|
||||||
import { CompanyEditableNameChipCell } from '@/companies/components/CompanyEditableNameCell';
|
import { CompanyEditableNameChipCell } from '@/companies/components/CompanyEditableNameCell';
|
||||||
import {
|
|
||||||
PersonChip,
|
|
||||||
PersonChipPropsType,
|
|
||||||
} from '@/people/components/PersonChip';
|
|
||||||
import { SearchConfigType } from '@/search/interfaces/interface';
|
|
||||||
import { SEARCH_USER_QUERY } from '@/search/services/search';
|
|
||||||
import { EditableDate } from '@/ui/components/editable-cell/types/EditableDate';
|
import { EditableDate } from '@/ui/components/editable-cell/types/EditableDate';
|
||||||
import { EditableRelation } from '@/ui/components/editable-cell/types/EditableRelation';
|
|
||||||
import { EditableText } from '@/ui/components/editable-cell/types/EditableText';
|
import { EditableText } from '@/ui/components/editable-cell/types/EditableText';
|
||||||
import { ColumnHead } from '@/ui/components/table/ColumnHead';
|
import { ColumnHead } from '@/ui/components/table/ColumnHead';
|
||||||
|
import { RecoilScope } from '@/ui/hooks/RecoilScope';
|
||||||
import {
|
import {
|
||||||
IconBuildingSkyscraper,
|
IconBuildingSkyscraper,
|
||||||
IconCalendarEvent,
|
IconCalendarEvent,
|
||||||
@ -23,7 +18,6 @@ import {
|
|||||||
import { getCheckBoxColumn } from '@/ui/tables/utils/getCheckBoxColumn';
|
import { getCheckBoxColumn } from '@/ui/tables/utils/getCheckBoxColumn';
|
||||||
import {
|
import {
|
||||||
GetCompaniesQuery,
|
GetCompaniesQuery,
|
||||||
QueryMode,
|
|
||||||
useUpdateCompanyMutation,
|
useUpdateCompanyMutation,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
|
|
||||||
@ -149,41 +143,9 @@ export const useCompaniesColumns = () => {
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
cell: (props) => (
|
cell: (props) => (
|
||||||
<EditableRelation<any, PersonChipPropsType>
|
<RecoilScope>
|
||||||
relation={props.row.original.accountOwner}
|
<CompanyAccountOwnerCell company={props.row.original} />
|
||||||
searchPlaceholder="Account Owner"
|
</RecoilScope>
|
||||||
ChipComponent={PersonChip}
|
|
||||||
chipComponentPropsMapper={(
|
|
||||||
accountOwner: any,
|
|
||||||
): PersonChipPropsType => {
|
|
||||||
return {
|
|
||||||
name: accountOwner.displayName || '',
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
onChange={(relation: any) => {
|
|
||||||
updateCompany({
|
|
||||||
variables: {
|
|
||||||
...props.row.original,
|
|
||||||
accountOwnerId: relation.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
searchConfig={
|
|
||||||
{
|
|
||||||
query: SEARCH_USER_QUERY,
|
|
||||||
template: (searchInput: string) => ({
|
|
||||||
displayName: {
|
|
||||||
contains: `%${searchInput}%`,
|
|
||||||
mode: QueryMode.Insensitive,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
resultMapper: (accountOwner: any) => ({
|
|
||||||
render: (accountOwner: any) => accountOwner.displayName,
|
|
||||||
value: accountOwner,
|
|
||||||
}),
|
|
||||||
} satisfies SearchConfigType
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user