Removing Prisma and Grapql-nestjs-prisma resolvers (#2574)
* Some cleaning * Fix seeds * Fix all sign in, sign up flow and apiKey optimistic rendering * Fix
This commit is contained in:
@ -1,9 +1,9 @@
|
||||
import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import styled from '@emotion/styled';
|
||||
import { autoUpdate, flip, offset, useFloating } from '@floating-ui/react';
|
||||
|
||||
import { Person } from '@/people/types/Person';
|
||||
import { IconDotsVertical, IconLinkOff, IconTrash } from '@/ui/display/icon';
|
||||
import { FloatingIconButton } from '@/ui/input/button/components/FloatingIconButton';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
@ -11,16 +11,9 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
import { Avatar } from '@/users/components/Avatar';
|
||||
import {
|
||||
Person,
|
||||
useDeleteManyPersonMutation,
|
||||
useUpdateOnePersonMutation,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { GET_PEOPLE } from '../graphql/queries/getPeople';
|
||||
|
||||
export type PeopleCardProps = {
|
||||
person: Pick<Person, 'id' | 'avatarUrl' | 'displayName' | 'jobTitle'>;
|
||||
person: Pick<Person, 'id' | 'avatarUrl' | 'name' | 'jobTitle'>;
|
||||
hasBottomBorder?: boolean;
|
||||
};
|
||||
|
||||
@ -78,8 +71,6 @@ export const PeopleCard = ({
|
||||
const navigate = useNavigate();
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const [isOptionsOpen, setIsOptionsOpen] = useState(false);
|
||||
const [updatePerson] = useUpdateOnePersonMutation();
|
||||
const [deletePerson] = useDeleteManyPersonMutation();
|
||||
|
||||
const { refs, floatingStyles } = useFloating({
|
||||
strategy: 'absolute',
|
||||
@ -114,28 +105,28 @@ export const PeopleCard = ({
|
||||
};
|
||||
|
||||
const handleDetachPerson = () => {
|
||||
updatePerson({
|
||||
variables: {
|
||||
where: {
|
||||
id: person.id,
|
||||
},
|
||||
data: {
|
||||
company: {
|
||||
disconnect: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
refetchQueries: [getOperationName(GET_PEOPLE) ?? ''],
|
||||
});
|
||||
// updatePerson({
|
||||
// variables: {
|
||||
// where: {
|
||||
// id: person.id,
|
||||
// },
|
||||
// data: {
|
||||
// company: {
|
||||
// disconnect: true,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// refetchQueries: [getOperationName(GET_PEOPLE) ?? ''],
|
||||
// });
|
||||
};
|
||||
|
||||
const handleDeletePerson = () => {
|
||||
deletePerson({
|
||||
variables: {
|
||||
ids: person.id,
|
||||
},
|
||||
refetchQueries: [getOperationName(GET_PEOPLE) ?? ''],
|
||||
});
|
||||
// deletePerson({
|
||||
// variables: {
|
||||
// ids: person.id,
|
||||
// },
|
||||
// refetchQueries: [getOperationName(GET_PEOPLE) ?? ''],
|
||||
// });
|
||||
};
|
||||
|
||||
return (
|
||||
@ -149,11 +140,13 @@ export const PeopleCard = ({
|
||||
<Avatar
|
||||
size="lg"
|
||||
type="rounded"
|
||||
placeholder={person.displayName}
|
||||
placeholder={person.name.firstName + ' ' + person.name.lastName}
|
||||
avatarUrl={person.avatarUrl}
|
||||
/>
|
||||
<StyledCardInfo>
|
||||
<StyledTitle>{person.displayName}</StyledTitle>
|
||||
<StyledTitle>
|
||||
{person.name.firstName + ' ' + person.name.lastName}
|
||||
</StyledTitle>
|
||||
{person.jobTitle && <StyledJobTitle>{person.jobTitle}</StyledJobTitle>}
|
||||
</StyledCardInfo>
|
||||
{isHovered && (
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useQuery } from '@apollo/client';
|
||||
|
||||
import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
|
||||
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||
import { useFilteredSearchEntityQueryV2 } from '@/search/hooks/useFilteredSearchEntityQueryV2';
|
||||
import { SingleEntitySelect } from '@/ui/input/relation-picker/components/SingleEntitySelect';
|
||||
import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState';
|
||||
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
|
||||
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
|
||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||
import { useSearchPeopleQuery } from '~/generated/graphql';
|
||||
|
||||
export type PeoplePickerProps = {
|
||||
personId: string | null;
|
||||
@ -40,7 +41,7 @@ export const PeoplePicker = ({
|
||||
|
||||
const queryFilters = [
|
||||
{
|
||||
fieldNames: ['firstName', 'lastName'],
|
||||
fieldNames: ['name.firstName', 'name.lastName'],
|
||||
filter: relationPickerSearchFilter,
|
||||
},
|
||||
];
|
||||
@ -52,24 +53,32 @@ export const PeoplePicker = ({
|
||||
});
|
||||
}
|
||||
|
||||
const people = useFilteredSearchEntityQuery({
|
||||
queryHook: useSearchPeopleQuery,
|
||||
selectedIds: [personId ?? ''],
|
||||
const { findManyQuery } = useFindOneObjectMetadataItem({
|
||||
objectNameSingular: 'person',
|
||||
});
|
||||
|
||||
const useFindManyPeople = (options: any) => useQuery(findManyQuery, options);
|
||||
|
||||
const people = useFilteredSearchEntityQueryV2({
|
||||
queryHook: useFindManyPeople,
|
||||
filters: queryFilters,
|
||||
mappingFunction: (person) => ({
|
||||
entityType: Entity.Person,
|
||||
id: person.id,
|
||||
name: `${person.firstName} ${person.lastName}`,
|
||||
orderByField: 'createdAt',
|
||||
mappingFunction: (workspaceMember) => ({
|
||||
entityType: Entity.WorkspaceMember,
|
||||
id: workspaceMember.id,
|
||||
name:
|
||||
workspaceMember.name.firstName + ' ' + workspaceMember.name.lastName,
|
||||
avatarType: 'rounded',
|
||||
avatarUrl: person.avatarUrl ?? '',
|
||||
originalEntity: person,
|
||||
avatarUrl: '',
|
||||
originalEntity: workspaceMember,
|
||||
}),
|
||||
orderByField: 'firstName',
|
||||
selectedIds: [personId ?? ''],
|
||||
excludeEntityIds: excludePersonIds,
|
||||
objectNamePlural: 'people',
|
||||
});
|
||||
|
||||
const handleEntitySelected = async (
|
||||
selectedPerson: PersonForSelect | null | undefined,
|
||||
selectedPerson: any | null | undefined,
|
||||
) => {
|
||||
onSubmit(selectedPerson ?? null);
|
||||
};
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
import {
|
||||
PersonOrderByWithRelationInput,
|
||||
SortOrder,
|
||||
useGetPeopleQuery,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { useSetPeopleRecordTable } from '../hooks/useSetPeopleRecordTable';
|
||||
|
||||
export const PeopleRecordTableDataEffect = ({
|
||||
orderBy = [
|
||||
{
|
||||
createdAt: SortOrder.Desc,
|
||||
},
|
||||
],
|
||||
whereFilters,
|
||||
}: {
|
||||
orderBy?: PersonOrderByWithRelationInput[];
|
||||
whereFilters?: any;
|
||||
}) => {
|
||||
const setPeopleRecordTable = useSetPeopleRecordTable();
|
||||
|
||||
useGetPeopleQuery({
|
||||
variables: { orderBy, where: whereFilters },
|
||||
onCompleted: (data) => {
|
||||
const people = data.people ?? [];
|
||||
|
||||
setPeopleRecordTable(people);
|
||||
},
|
||||
});
|
||||
|
||||
return <></>;
|
||||
};
|
||||
@ -1,17 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { mockedPeopleData } from '~/testing/mock-data/people';
|
||||
|
||||
import { PeopleFullNameEditableField } from '../../editable-field/components/PeopleFullNameEditableField';
|
||||
|
||||
const meta: Meta<typeof PeopleFullNameEditableField> = {
|
||||
title: 'Modules/People/EditableFields/PeopleFullNameEditableField',
|
||||
component: PeopleFullNameEditableField,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof PeopleFullNameEditableField>;
|
||||
|
||||
export const Default: Story = {
|
||||
render: () => <PeopleFullNameEditableField people={mockedPeopleData[0]} />,
|
||||
};
|
||||
@ -1,157 +0,0 @@
|
||||
import {
|
||||
IconBrandLinkedin,
|
||||
IconBrandX,
|
||||
IconBriefcase,
|
||||
IconBuildingSkyscraper,
|
||||
IconCalendarEvent,
|
||||
IconMail,
|
||||
IconMap,
|
||||
IconPhone,
|
||||
IconUser,
|
||||
} from '@/ui/display/icon/index';
|
||||
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
|
||||
import {
|
||||
FieldDateMetadata,
|
||||
FieldDoubleTextChipMetadata,
|
||||
FieldEmailMetadata,
|
||||
FieldMetadata,
|
||||
FieldPhoneMetadata,
|
||||
FieldRelationMetadata,
|
||||
FieldTextMetadata,
|
||||
FieldURLMetadata,
|
||||
} from '@/ui/object/field/types/FieldMetadata';
|
||||
import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition';
|
||||
import { Company } from '~/generated/graphql';
|
||||
import { getLogoUrlFromDomainName } from '~/utils';
|
||||
|
||||
export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[] =
|
||||
[
|
||||
{
|
||||
fieldMetadataId: 'displayName',
|
||||
label: 'People',
|
||||
Icon: IconUser,
|
||||
size: 210,
|
||||
position: 0,
|
||||
type: 'DOUBLE_TEXT_CHIP',
|
||||
metadata: {
|
||||
firstValueFieldName: 'firstName',
|
||||
secondValueFieldName: 'lastName',
|
||||
firstValuePlaceholder: 'First name', // Hack: Fake character to prevent password-manager from filling the field
|
||||
secondValuePlaceholder: 'Last name', // Hack: Fake character to prevent password-manager from filling the field
|
||||
avatarUrlFieldName: 'avatarUrl',
|
||||
entityType: Entity.Person,
|
||||
},
|
||||
infoTooltipContent: 'Contact’s first and last name.',
|
||||
basePathToShowPage: '/person/',
|
||||
} satisfies ColumnDefinition<FieldDoubleTextChipMetadata>,
|
||||
{
|
||||
fieldMetadataId: 'email',
|
||||
label: 'Email',
|
||||
Icon: IconMail,
|
||||
size: 150,
|
||||
type: 'EMAIL',
|
||||
position: 1,
|
||||
metadata: {
|
||||
fieldName: 'email',
|
||||
placeHolder: 'Email', // Hack: Fake character to prevent password-manager from filling the field
|
||||
},
|
||||
infoTooltipContent: 'Contact’s Email.',
|
||||
} satisfies ColumnDefinition<FieldEmailMetadata>,
|
||||
{
|
||||
fieldMetadataId: 'company',
|
||||
label: 'Company',
|
||||
Icon: IconBuildingSkyscraper,
|
||||
size: 150,
|
||||
position: 2,
|
||||
type: 'RELATION',
|
||||
metadata: {
|
||||
fieldName: 'company',
|
||||
relationType: Entity.Company,
|
||||
},
|
||||
infoTooltipContent: 'Contact’s company.',
|
||||
entityChipDisplayMapper: (dataObject: Company) => {
|
||||
return {
|
||||
name: dataObject?.name,
|
||||
pictureUrl: getLogoUrlFromDomainName(dataObject?.domainName),
|
||||
avatarType: 'squared',
|
||||
};
|
||||
},
|
||||
} satisfies ColumnDefinition<FieldRelationMetadata>,
|
||||
{
|
||||
fieldMetadataId: 'phone',
|
||||
label: 'Phone',
|
||||
Icon: IconPhone,
|
||||
size: 150,
|
||||
position: 3,
|
||||
type: 'PHONE',
|
||||
metadata: {
|
||||
fieldName: 'phone',
|
||||
placeHolder: 'Phone', // Hack: Fake character to prevent password-manager from filling the field
|
||||
},
|
||||
infoTooltipContent: 'Contact’s phone number.',
|
||||
} satisfies ColumnDefinition<FieldPhoneMetadata>,
|
||||
{
|
||||
fieldMetadataId: 'createdAt',
|
||||
label: 'Creation',
|
||||
Icon: IconCalendarEvent,
|
||||
size: 150,
|
||||
position: 4,
|
||||
type: 'DATE',
|
||||
metadata: {
|
||||
fieldName: 'createdAt',
|
||||
},
|
||||
infoTooltipContent: 'Date when the contact was added.',
|
||||
} satisfies ColumnDefinition<FieldDateMetadata>,
|
||||
{
|
||||
fieldMetadataId: 'city',
|
||||
label: 'City',
|
||||
Icon: IconMap,
|
||||
size: 150,
|
||||
position: 5,
|
||||
type: 'TEXT',
|
||||
metadata: {
|
||||
fieldName: 'city',
|
||||
placeHolder: 'City', // Hack: Fake character to prevent password-manager from filling the field
|
||||
},
|
||||
infoTooltipContent: 'Contact’s city.',
|
||||
} satisfies ColumnDefinition<FieldTextMetadata>,
|
||||
{
|
||||
fieldMetadataId: 'jobTitle',
|
||||
label: 'Job title',
|
||||
Icon: IconBriefcase,
|
||||
size: 150,
|
||||
position: 6,
|
||||
type: 'TEXT',
|
||||
metadata: {
|
||||
fieldName: 'jobTitle',
|
||||
placeHolder: 'Job title',
|
||||
},
|
||||
infoTooltipContent: 'Contact’s job title.',
|
||||
} satisfies ColumnDefinition<FieldTextMetadata>,
|
||||
{
|
||||
fieldMetadataId: 'linkedin',
|
||||
label: 'LinkedIn',
|
||||
Icon: IconBrandLinkedin,
|
||||
size: 150,
|
||||
position: 7,
|
||||
type: 'URL',
|
||||
metadata: {
|
||||
fieldName: 'linkedinUrl',
|
||||
placeHolder: 'LinkedIn',
|
||||
},
|
||||
infoTooltipContent: 'Contact’s Linkedin account.',
|
||||
} satisfies ColumnDefinition<FieldURLMetadata>,
|
||||
{
|
||||
fieldMetadataId: 'x',
|
||||
label: 'Twitter',
|
||||
Icon: IconBrandX,
|
||||
size: 150,
|
||||
position: 8,
|
||||
type: 'URL',
|
||||
metadata: {
|
||||
fieldName: 'xUrl',
|
||||
placeHolder: 'X',
|
||||
},
|
||||
infoTooltipContent: 'Contact’s Twitter account.',
|
||||
} satisfies ColumnDefinition<FieldURLMetadata>,
|
||||
];
|
||||
@ -1,61 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { EntityTitleDoubleTextInput } from '@/ui/input/components/EntityTitleDoubleTextInput';
|
||||
import { FieldRecoilScopeContext } from '@/ui/object/record-inline-cell/states/recoil-scope-contexts/FieldRecoilScopeContext';
|
||||
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
|
||||
import { Person, useUpdateOnePersonMutation } from '~/generated/graphql';
|
||||
|
||||
type PeopleFullNameEditableFieldProps = {
|
||||
people: Pick<Person, 'id' | 'firstName' | 'lastName'>;
|
||||
};
|
||||
|
||||
export const PeopleFullNameEditableField = ({
|
||||
people,
|
||||
}: PeopleFullNameEditableFieldProps) => {
|
||||
const [internalValueFirstName, setInternalValueFirstName] = useState(
|
||||
people.firstName,
|
||||
);
|
||||
const [internalValueLastName, setInternalValueLastName] = useState(
|
||||
people.lastName,
|
||||
);
|
||||
|
||||
const [updatePeople] = useUpdateOnePersonMutation();
|
||||
|
||||
const handleChange = async (
|
||||
newValueFirstName: string,
|
||||
newValueLastName: string,
|
||||
) => {
|
||||
setInternalValueFirstName(newValueFirstName);
|
||||
setInternalValueLastName(newValueLastName);
|
||||
handleSubmit(newValueFirstName, newValueLastName);
|
||||
};
|
||||
|
||||
const handleSubmit = async (
|
||||
newValueFirstName: string,
|
||||
newValueLastName: string,
|
||||
) => {
|
||||
await updatePeople({
|
||||
variables: {
|
||||
where: {
|
||||
id: people.id,
|
||||
},
|
||||
data: {
|
||||
firstName: newValueFirstName ?? '',
|
||||
lastName: newValueLastName ?? '',
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
|
||||
<EntityTitleDoubleTextInput
|
||||
firstValuePlaceholder="Empty"
|
||||
secondValuePlaceholder="Empty"
|
||||
firstValue={internalValueFirstName ?? ''}
|
||||
secondValue={internalValueLastName ?? ''}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</RecoilScope>
|
||||
);
|
||||
};
|
||||
@ -1,31 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const BASE_PERSON_FIELDS_FRAGMENT = gql`
|
||||
fragment basePersonFieldsFragment on Person {
|
||||
id
|
||||
phone
|
||||
email
|
||||
city
|
||||
firstName
|
||||
lastName
|
||||
displayName
|
||||
avatarUrl
|
||||
createdAt
|
||||
}
|
||||
`;
|
||||
|
||||
export const PERSON_FIELDS_FRAGMENT = gql`
|
||||
${BASE_PERSON_FIELDS_FRAGMENT}
|
||||
fragment personFieldsFragment on Person {
|
||||
...basePersonFieldsFragment
|
||||
jobTitle
|
||||
linkedinUrl
|
||||
xUrl
|
||||
_activityCount
|
||||
company {
|
||||
id
|
||||
name
|
||||
domainName
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,9 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const DELETE_MANY_PERSON = gql`
|
||||
mutation DeleteManyPerson($ids: [String!]) {
|
||||
deleteManyPerson(where: { id: { in: $ids } }) {
|
||||
count
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,9 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const INSERT_MANY_PERSON = gql`
|
||||
mutation InsertManyPerson($data: [PersonCreateManyInput!]!) {
|
||||
createManyPerson(data: $data) {
|
||||
count
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,9 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const INSERT_ONE_PERSON = gql`
|
||||
mutation InsertOnePerson($data: PersonCreateInput!) {
|
||||
createOnePerson(data: $data) {
|
||||
...personFieldsFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,10 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const REMOVE_PERSON_PICTURE = gql`
|
||||
mutation RemovePersonPicture($where: PersonWhereUniqueInput!) {
|
||||
updateOnePerson(data: { avatarUrl: null }, where: $where) {
|
||||
id
|
||||
avatarUrl
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,12 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const UPDATE_ONE_PERSON = gql`
|
||||
mutation UpdateOnePerson(
|
||||
$where: PersonWhereUniqueInput!
|
||||
$data: PersonUpdateInput!
|
||||
) {
|
||||
updateOnePerson(data: $data, where: $where) {
|
||||
...personFieldsFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,7 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const UPDATE_PERSON_PICTURE = gql`
|
||||
mutation UploadPersonPicture($id: String!, $file: Upload!) {
|
||||
uploadPersonPicture(id: $id, file: $file)
|
||||
}
|
||||
`;
|
||||
@ -1,18 +0,0 @@
|
||||
import { Person } from '~/generated/graphql';
|
||||
|
||||
import { GET_PEOPLE } from '../queries/getPeople';
|
||||
|
||||
export const getPeopleOptimisticEffectDefinition = {
|
||||
key: 'generic-entity-table-data-people',
|
||||
typename: 'Person',
|
||||
query: GET_PEOPLE,
|
||||
resolver: ({
|
||||
currentData,
|
||||
newData,
|
||||
}: {
|
||||
currentData: Person[];
|
||||
newData: Person[];
|
||||
}) => {
|
||||
return [...newData, ...currentData];
|
||||
},
|
||||
};
|
||||
@ -1,16 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
import { PERSON_FIELDS_FRAGMENT } from '../fragments/personFieldsFragment';
|
||||
|
||||
export const GET_PEOPLE = gql`
|
||||
${PERSON_FIELDS_FRAGMENT}
|
||||
query GetPeople(
|
||||
$orderBy: [PersonOrderByWithRelationInput!]
|
||||
$where: PersonWhereInput
|
||||
$limit: Int
|
||||
) {
|
||||
people: findManyPerson(orderBy: $orderBy, where: $where, take: $limit) {
|
||||
...personFieldsFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,18 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_PERSON = gql`
|
||||
query GetPerson($id: String!) {
|
||||
findUniquePerson(id: $id) {
|
||||
...personFieldsFragment
|
||||
Favorite {
|
||||
id
|
||||
person {
|
||||
id
|
||||
}
|
||||
company {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,10 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_PERSON_CITY = gql`
|
||||
query GetPersonCityById($id: String!) {
|
||||
person: findUniquePerson(id: $id) {
|
||||
id
|
||||
city
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,10 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_PERSON_COMMENT_COUNT = gql`
|
||||
query GetPersonCommentCountById($id: String!) {
|
||||
person: findUniquePerson(id: $id) {
|
||||
id
|
||||
_activityCount
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,14 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_PERSON_COMPANY = gql`
|
||||
query GetPersonCompanyById($id: String!) {
|
||||
person: findUniquePerson(id: $id) {
|
||||
id
|
||||
company {
|
||||
id
|
||||
name
|
||||
domainName
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,10 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_PERSON_CREATED_AT = gql`
|
||||
query GetPersonCreatedAtById($id: String!) {
|
||||
person: findUniquePerson(id: $id) {
|
||||
id
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,10 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_PERSON_EMAIL = gql`
|
||||
query GetPersonEmailById($id: String!) {
|
||||
person: findUniquePerson(id: $id) {
|
||||
id
|
||||
email
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,13 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_PERSON_NAMES_AND_COMMENT_COUNT = gql`
|
||||
query GetPersonNamesAndCommentCountById($id: String!) {
|
||||
person: findUniquePerson(id: $id) {
|
||||
id
|
||||
firstName
|
||||
lastName
|
||||
displayName
|
||||
_activityCount
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,10 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_PERSON_PHONE = gql`
|
||||
query GetPersonPhoneById($id: String!) {
|
||||
person: findUniquePerson(id: $id) {
|
||||
id
|
||||
phone
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,39 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useOpenCreateActivityDrawerForSelectedRowIds } from '@/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds';
|
||||
import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { entityFieldsFamilyState } from '@/ui/object/field/states/entityFieldsFamilyState';
|
||||
import { selectedRowIdsSelector } from '@/ui/object/record-table/states/selectors/selectedRowIdsSelector';
|
||||
import { ActivityType, Person } from '~/generated/graphql';
|
||||
|
||||
export const useCreateActivityForPeople = () => {
|
||||
const openCreateActivityRightDrawer =
|
||||
useOpenCreateActivityDrawerForSelectedRowIds();
|
||||
|
||||
return useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
(type: ActivityType) => {
|
||||
const relatedEntites: ActivityTargetableEntity[] = [];
|
||||
const selectedRowIds = Object.keys(
|
||||
snapshot.getLoadable(selectedRowIdsSelector).getValue(),
|
||||
);
|
||||
for (const id of selectedRowIds) {
|
||||
const person = snapshot
|
||||
.getLoadable(entityFieldsFamilyState(id))
|
||||
.getValue() as Person;
|
||||
if (
|
||||
person?.company?.id &&
|
||||
!relatedEntites.find((x) => x.id === person?.company?.id)
|
||||
) {
|
||||
relatedEntites.push({
|
||||
id: person.company.id,
|
||||
type: 'Company',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
openCreateActivityRightDrawer(type, 'Person', relatedEntites);
|
||||
},
|
||||
[openCreateActivityRightDrawer],
|
||||
);
|
||||
};
|
||||
@ -1,6 +1,8 @@
|
||||
import { ActivityTargetableEntityForSelect } from '@/activities/types/ActivityTargetableEntityForSelect';
|
||||
import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
|
||||
import { useSearchPeopleQuery } from '~/generated/graphql';
|
||||
import { useQuery } from '@apollo/client';
|
||||
|
||||
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||
import { useFilteredSearchEntityQueryV2 } from '@/search/hooks/useFilteredSearchEntityQueryV2';
|
||||
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
|
||||
|
||||
export const useFilteredSearchPeopleQuery = ({
|
||||
searchFilter,
|
||||
@ -10,24 +12,32 @@ export const useFilteredSearchPeopleQuery = ({
|
||||
searchFilter: string;
|
||||
selectedIds?: string[];
|
||||
limit?: number;
|
||||
}) =>
|
||||
useFilteredSearchEntityQuery({
|
||||
queryHook: useSearchPeopleQuery,
|
||||
}) => {
|
||||
const { findManyQuery } = useFindOneObjectMetadataItem({
|
||||
objectNameSingular: 'person',
|
||||
});
|
||||
|
||||
const useFindManyPeople = (options: any) => useQuery(findManyQuery, options);
|
||||
|
||||
return useFilteredSearchEntityQueryV2({
|
||||
queryHook: useFindManyPeople,
|
||||
filters: [
|
||||
{
|
||||
fieldNames: ['firstName', 'lastName'],
|
||||
fieldNames: ['name.firstName', 'name.lastName'],
|
||||
filter: searchFilter,
|
||||
},
|
||||
],
|
||||
orderByField: 'lastName',
|
||||
orderByField: 'createdAt',
|
||||
mappingFunction: (person) => ({
|
||||
entityType: Entity.Person,
|
||||
id: person.id,
|
||||
name: person.name.firstName + ' ' + person.name.lastName,
|
||||
avatarType: 'rounded',
|
||||
avatarUrl: '',
|
||||
originalEntity: person,
|
||||
}),
|
||||
selectedIds: selectedIds,
|
||||
mappingFunction: (entity) =>
|
||||
({
|
||||
id: entity.id,
|
||||
entityType: 'Person',
|
||||
name: `${entity.firstName} ${entity.lastName}`,
|
||||
avatarUrl: entity.avatarUrl,
|
||||
avatarType: 'rounded',
|
||||
} as ActivityTargetableEntityForSelect),
|
||||
objectNamePlural: 'workspaceMembers',
|
||||
limit,
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { entityFieldsFamilyState } from '@/ui/object/field/states/entityFieldsFamilyState';
|
||||
import { useGetPersonQuery } from '~/generated/graphql';
|
||||
|
||||
export const usePersonQuery = (id: string) => {
|
||||
const updatePersonShowPage = useSetRecoilState(entityFieldsFamilyState(id));
|
||||
|
||||
return useGetPersonQuery({
|
||||
variables: { id },
|
||||
onCompleted: (data) => {
|
||||
updatePersonShowPage(data?.findUniquePerson);
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -1,155 +0,0 @@
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useFavorites } from '@/favorites/hooks/useFavorites';
|
||||
import {
|
||||
IconCheckbox,
|
||||
IconHeart,
|
||||
IconHeartOff,
|
||||
IconNotes,
|
||||
IconTrash,
|
||||
} from '@/ui/display/icon';
|
||||
import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState';
|
||||
import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState';
|
||||
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
|
||||
import { selectedRowIdsSelector } from '@/ui/object/record-table/states/selectors/selectedRowIdsSelector';
|
||||
import { tableRowIdsState } from '@/ui/object/record-table/states/tableRowIdsState';
|
||||
import {
|
||||
ActivityType,
|
||||
useDeleteManyPersonMutation,
|
||||
useGetFavoritesQuery,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { GET_PEOPLE } from '../graphql/queries/getPeople';
|
||||
|
||||
import { useCreateActivityForPeople } from './useCreateActivityForPeople';
|
||||
|
||||
export const usePersonTableContextMenuEntries = () => {
|
||||
const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState);
|
||||
const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState);
|
||||
const createActivityForPeople = useCreateActivityForPeople();
|
||||
|
||||
const setTableRowIds = useSetRecoilState(tableRowIdsState);
|
||||
const { resetTableRowSelection } = useRecordTable({
|
||||
recordTableScopeId: 'people',
|
||||
});
|
||||
|
||||
const { data } = useGetFavoritesQuery();
|
||||
const favorites = data?.findFavorites;
|
||||
const { createFavorite, deleteFavorite } = useFavorites({
|
||||
objectNamePlural: 'people',
|
||||
});
|
||||
|
||||
const handleFavoriteButtonClick = useRecoilCallback(({ snapshot }) => () => {
|
||||
const selectedRowIds = snapshot
|
||||
.getLoadable(selectedRowIdsSelector)
|
||||
.getValue();
|
||||
|
||||
const selectedPersonId =
|
||||
selectedRowIds.length === 1 ? selectedRowIds[0] : '';
|
||||
|
||||
const isFavorite =
|
||||
!!selectedPersonId &&
|
||||
!!favorites?.find((favorite) => favorite.person?.id === selectedPersonId);
|
||||
|
||||
resetTableRowSelection();
|
||||
if (isFavorite) deleteFavorite(selectedPersonId);
|
||||
else createFavorite('person', selectedPersonId);
|
||||
});
|
||||
|
||||
const [deleteManyPerson] = useDeleteManyPersonMutation({
|
||||
refetchQueries: [getOperationName(GET_PEOPLE) ?? ''],
|
||||
});
|
||||
|
||||
const handleDeleteClick = useRecoilCallback(({ snapshot }) => async () => {
|
||||
const rowIdsToDelete = snapshot
|
||||
.getLoadable(selectedRowIdsSelector)
|
||||
.getValue();
|
||||
|
||||
resetTableRowSelection();
|
||||
|
||||
await deleteManyPerson({
|
||||
variables: {
|
||||
ids: rowIdsToDelete,
|
||||
},
|
||||
optimisticResponse: {
|
||||
__typename: 'Mutation',
|
||||
deleteManyPerson: {
|
||||
count: rowIdsToDelete.length,
|
||||
},
|
||||
},
|
||||
update: () => {
|
||||
setTableRowIds((tableRowIds) =>
|
||||
tableRowIds.filter((id) => !rowIdsToDelete.includes(id)),
|
||||
);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
setContextMenuEntries: useRecoilCallback(({ snapshot }) => () => {
|
||||
const selectedRowIds = snapshot
|
||||
.getLoadable(selectedRowIdsSelector)
|
||||
.getValue();
|
||||
|
||||
const selectedPersonId =
|
||||
selectedRowIds.length === 1 ? selectedRowIds[0] : '';
|
||||
|
||||
const isFavorite =
|
||||
!!selectedPersonId &&
|
||||
!!favorites?.find(
|
||||
(favorite) => favorite.person?.id === selectedPersonId,
|
||||
);
|
||||
|
||||
setContextMenuEntries([
|
||||
{
|
||||
label: 'New task',
|
||||
Icon: IconCheckbox,
|
||||
onClick: () => createActivityForPeople(ActivityType.Task),
|
||||
},
|
||||
{
|
||||
label: 'New note',
|
||||
Icon: IconNotes,
|
||||
onClick: () => createActivityForPeople(ActivityType.Note),
|
||||
},
|
||||
...(!!selectedPersonId
|
||||
? [
|
||||
{
|
||||
label: isFavorite
|
||||
? 'Remove from favorites'
|
||||
: 'Add to favorites',
|
||||
Icon: isFavorite ? IconHeartOff : IconHeart,
|
||||
onClick: () => handleFavoriteButtonClick(),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
label: 'Delete',
|
||||
Icon: IconTrash,
|
||||
accent: 'danger',
|
||||
onClick: () => handleDeleteClick(),
|
||||
},
|
||||
]);
|
||||
}),
|
||||
setActionBarEntries: useRecoilCallback(() => () => {
|
||||
setActionBarEntriesState([
|
||||
{
|
||||
label: 'Task',
|
||||
Icon: IconCheckbox,
|
||||
onClick: () => createActivityForPeople(ActivityType.Task),
|
||||
},
|
||||
{
|
||||
label: 'Note',
|
||||
Icon: IconNotes,
|
||||
onClick: () => createActivityForPeople(ActivityType.Note),
|
||||
},
|
||||
{
|
||||
label: 'Delete',
|
||||
Icon: IconTrash,
|
||||
accent: 'danger',
|
||||
onClick: () => handleDeleteClick(),
|
||||
},
|
||||
]);
|
||||
}),
|
||||
};
|
||||
};
|
||||
@ -1,129 +0,0 @@
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
|
||||
import { isFetchingRecordTableDataState } from '@/ui/object/record-table/states/isFetchingRecordTableDataState';
|
||||
import { numberOfTableRowsState } from '@/ui/object/record-table/states/numberOfTableRowsState';
|
||||
import { tableRowIdsState } from '@/ui/object/record-table/states/tableRowIdsState';
|
||||
import { currentPageLocationState } from '@/ui/utilities/loading-state/states/currentPageLocationState';
|
||||
import { GetPeopleQuery } from '~/generated/graphql';
|
||||
|
||||
import { peopleCityFamilyState } from '../states/peopleCityFamilyState';
|
||||
import { peopleCompanyFamilyState } from '../states/peopleCompanyFamilyState';
|
||||
import { peopleCreatedAtFamilyState } from '../states/peopleCreatedAtFamilyState';
|
||||
import { peopleEmailFamilyState } from '../states/peopleEmailFamilyState';
|
||||
import { peopleJobTitleFamilyState } from '../states/peopleJobTitleFamilyState';
|
||||
import { peopleLinkedinUrlFamilyState } from '../states/peopleLinkedinUrlFamilyState';
|
||||
import { peopleNameCellFamilyState } from '../states/peopleNamesFamilyState';
|
||||
import { peoplePhoneFamilyState } from '../states/peoplePhoneFamilyState';
|
||||
|
||||
export const useSetPeopleRecordTable = () => {
|
||||
const { resetTableRowSelection } = useRecordTable();
|
||||
|
||||
const currentLocation = useLocation().pathname;
|
||||
|
||||
return useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(newPeopleArray: GetPeopleQuery['people']) => {
|
||||
for (const person of newPeopleArray) {
|
||||
const currentEmail = snapshot
|
||||
.getLoadable(peopleEmailFamilyState(person.id))
|
||||
.valueOrThrow();
|
||||
|
||||
if (currentEmail !== person.email) {
|
||||
set(peopleEmailFamilyState(person.id), person.email ?? null);
|
||||
}
|
||||
|
||||
const currentCity = snapshot
|
||||
.getLoadable(peopleCityFamilyState(person.id))
|
||||
.valueOrThrow();
|
||||
|
||||
if (currentCity !== person.city) {
|
||||
set(peopleCityFamilyState(person.id), person.city ?? null);
|
||||
}
|
||||
|
||||
const currentCompany = snapshot
|
||||
.getLoadable(peopleCompanyFamilyState(person.id))
|
||||
.valueOrThrow();
|
||||
|
||||
if (
|
||||
JSON.stringify(currentCompany) !== JSON.stringify(person.company)
|
||||
) {
|
||||
set(peopleCompanyFamilyState(person.id), person.company);
|
||||
}
|
||||
|
||||
const currentPhone = snapshot
|
||||
.getLoadable(peoplePhoneFamilyState(person.id))
|
||||
.valueOrThrow();
|
||||
|
||||
if (currentPhone !== person.phone) {
|
||||
set(peoplePhoneFamilyState(person.id), person.phone ?? null);
|
||||
}
|
||||
|
||||
const currentCreatedAt = snapshot
|
||||
.getLoadable(peopleCreatedAtFamilyState(person.id))
|
||||
.valueOrThrow();
|
||||
|
||||
if (currentCreatedAt !== person.createdAt) {
|
||||
set(peopleCreatedAtFamilyState(person.id), person.createdAt);
|
||||
}
|
||||
|
||||
const currentJobTitle = snapshot
|
||||
.getLoadable(peopleJobTitleFamilyState(person.id))
|
||||
.valueOrThrow();
|
||||
|
||||
if (currentJobTitle !== person.jobTitle) {
|
||||
set(peopleJobTitleFamilyState(person.id), person.jobTitle ?? null);
|
||||
}
|
||||
|
||||
const currentLinkedinUrl = snapshot
|
||||
.getLoadable(peopleLinkedinUrlFamilyState(person.id))
|
||||
.valueOrThrow();
|
||||
|
||||
if (currentLinkedinUrl !== person.linkedinUrl) {
|
||||
set(
|
||||
peopleLinkedinUrlFamilyState(person.id),
|
||||
person.linkedinUrl ?? null,
|
||||
);
|
||||
}
|
||||
|
||||
const currentNameCell = snapshot
|
||||
.getLoadable(peopleNameCellFamilyState(person.id))
|
||||
.valueOrThrow();
|
||||
|
||||
if (
|
||||
currentNameCell.firstName !== person.firstName ||
|
||||
currentNameCell.lastName !== person.lastName ||
|
||||
currentNameCell.commentCount !== person._activityCount
|
||||
) {
|
||||
set(peopleNameCellFamilyState(person.id), {
|
||||
firstName: person.firstName ?? null,
|
||||
lastName: person.lastName ?? null,
|
||||
commentCount: person._activityCount,
|
||||
displayName: person.displayName ?? null,
|
||||
avatarUrl: person.avatarUrl ?? null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const peopleIds = newPeopleArray.map((people) => people.id);
|
||||
|
||||
set(tableRowIdsState, (currentRowIds) => {
|
||||
if (JSON.stringify(currentRowIds) !== JSON.stringify(peopleIds)) {
|
||||
return peopleIds;
|
||||
}
|
||||
|
||||
return currentRowIds;
|
||||
});
|
||||
|
||||
resetTableRowSelection();
|
||||
|
||||
set(numberOfTableRowsState, peopleIds.length);
|
||||
|
||||
set(currentPageLocationState, currentLocation);
|
||||
|
||||
set(isFetchingRecordTableDataState, false);
|
||||
},
|
||||
[currentLocation, resetTableRowSelection],
|
||||
);
|
||||
};
|
||||
@ -3,7 +3,6 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
import { useSpreadsheetImport } from '@/spreadsheet-import/hooks/useSpreadsheetImport';
|
||||
import { SpreadsheetOptions } from '@/spreadsheet-import/types';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
||||
import { useInsertManyPersonMutation } from '~/generated/graphql';
|
||||
|
||||
import { fieldsForPerson } from '../utils/fieldsForPerson';
|
||||
|
||||
@ -13,8 +12,6 @@ export const useSpreadsheetPersonImport = () => {
|
||||
const { openSpreadsheetImport } = useSpreadsheetImport<FieldPersonMapping>();
|
||||
const { enqueueSnackBar } = useSnackBar();
|
||||
|
||||
const [createManyPerson] = useInsertManyPersonMutation();
|
||||
|
||||
const openPersonSpreadsheetImport = (
|
||||
options?: Omit<
|
||||
SpreadsheetOptions<FieldPersonMapping>,
|
||||
@ -37,22 +34,23 @@ export const useSpreadsheetPersonImport = () => {
|
||||
city: person.city as string | undefined,
|
||||
}));
|
||||
|
||||
try {
|
||||
const result = await createManyPerson({
|
||||
variables: {
|
||||
data: createInputs,
|
||||
},
|
||||
refetchQueries: 'active',
|
||||
});
|
||||
// TODO : abstract this part for any object
|
||||
// try {
|
||||
// const result = await createManyPerson({
|
||||
// variables: {
|
||||
// data: createInputs,
|
||||
// },
|
||||
// refetchQueries: 'active',
|
||||
// });
|
||||
|
||||
if (result.errors) {
|
||||
throw result.errors;
|
||||
}
|
||||
} catch (error: any) {
|
||||
enqueueSnackBar(error?.message || 'Something went wrong', {
|
||||
variant: 'error',
|
||||
});
|
||||
}
|
||||
// if (result.errors) {
|
||||
// throw result.errors;
|
||||
// }
|
||||
// } catch (error: any) {
|
||||
// enqueueSnackBar(error?.message || 'Something went wrong', {
|
||||
// variant: 'error',
|
||||
// });
|
||||
// }
|
||||
},
|
||||
fields: fieldsForPerson,
|
||||
});
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
export const peopleCityFamilyState = atomFamily<string | null, string>({
|
||||
key: 'peopleCityFamilyState',
|
||||
default: null,
|
||||
});
|
||||
@ -1,11 +0,0 @@
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
import { GetPeopleQuery } from '~/generated/graphql';
|
||||
|
||||
export const peopleCompanyFamilyState = atomFamily<
|
||||
GetPeopleQuery['people'][0]['company'] | null,
|
||||
string
|
||||
>({
|
||||
key: 'peopleCompanyFamilyState',
|
||||
default: null,
|
||||
});
|
||||
@ -1,6 +0,0 @@
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
export const peopleCreatedAtFamilyState = atomFamily<string | null, string>({
|
||||
key: 'peopleCreatedAtFamilyState',
|
||||
default: null,
|
||||
});
|
||||
@ -1,6 +0,0 @@
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
export const peopleEmailFamilyState = atomFamily<string | null, string>({
|
||||
key: 'peopleEmailFamilyState',
|
||||
default: null,
|
||||
});
|
||||
@ -1,6 +0,0 @@
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
export const peopleJobTitleFamilyState = atomFamily<string | null, string>({
|
||||
key: 'peopleJobTitleFamilyState',
|
||||
default: null,
|
||||
});
|
||||
@ -1,6 +0,0 @@
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
export const peopleLinkedinUrlFamilyState = atomFamily<string | null, string>({
|
||||
key: 'peopleLinkedinUrlFamilyState',
|
||||
default: null,
|
||||
});
|
||||
@ -1,21 +0,0 @@
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
export const peopleNameCellFamilyState = atomFamily<
|
||||
{
|
||||
firstName: string | null;
|
||||
lastName: string | null;
|
||||
commentCount: number | null;
|
||||
displayName: string | null;
|
||||
avatarUrl: string | null;
|
||||
},
|
||||
string
|
||||
>({
|
||||
key: 'peopleNameCellFamilyState',
|
||||
default: {
|
||||
firstName: null,
|
||||
lastName: null,
|
||||
commentCount: null,
|
||||
displayName: null,
|
||||
avatarUrl: null,
|
||||
},
|
||||
});
|
||||
@ -1,6 +0,0 @@
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
export const peoplePhoneFamilyState = atomFamily<string | null, string>({
|
||||
key: 'peoplePhoneFamilyState',
|
||||
default: null,
|
||||
});
|
||||
@ -1,133 +0,0 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { peopleAvailableFieldDefinitions } from '@/people/constants/peopleAvailableFieldDefinitions';
|
||||
import { getPeopleOptimisticEffectDefinition } from '@/people/graphql/optimistic-effect-definitions/getPeopleOptimisticEffectDefinition';
|
||||
import { usePersonTableContextMenuEntries } from '@/people/hooks/usePersonTableContextMenuEntries';
|
||||
import { useSpreadsheetPersonImport } from '@/people/hooks/useSpreadsheetPersonImport';
|
||||
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
|
||||
import { RecordTableEffect } from '@/ui/object/record-table/components/RecordTableEffect';
|
||||
import { RecordTableV1 } from '@/ui/object/record-table/components/RecordTableV1';
|
||||
import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId';
|
||||
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
|
||||
import { TableOptionsDropdown } from '@/ui/object/record-table/options/components/TableOptionsDropdown';
|
||||
import { RecordTableScope } from '@/ui/object/record-table/scopes/RecordTableScope';
|
||||
import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition';
|
||||
import { ViewBar } from '@/views/components/ViewBar';
|
||||
import { useViewFields } from '@/views/hooks/internal/useViewFields';
|
||||
import { useView } from '@/views/hooks/useView';
|
||||
import { ViewScope } from '@/views/scopes/ViewScope';
|
||||
import { mapColumnDefinitionsToViewFields } from '@/views/utils/mapColumnDefinitionToViewField';
|
||||
import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
|
||||
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
|
||||
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
|
||||
import {
|
||||
UpdateOnePersonMutationVariables,
|
||||
useGetPeopleQuery,
|
||||
useUpdateOnePersonMutation,
|
||||
} from '~/generated/graphql';
|
||||
import { personTableFilterDefinitions } from '~/pages/people/constants/personTableFilterDefinitions';
|
||||
import { personTableSortDefinitions } from '~/pages/people/constants/personTableSortDefinitions';
|
||||
|
||||
import PersonTableEffect from './PersonTableEffect';
|
||||
|
||||
export const PersonTable = () => {
|
||||
const viewScopeId = 'person-table-view';
|
||||
const tableScopeId = 'people';
|
||||
|
||||
const {
|
||||
setTableFilters,
|
||||
setTableSorts,
|
||||
setTableColumns,
|
||||
upsertRecordTableItem,
|
||||
} = useRecordTable({
|
||||
recordTableScopeId: tableScopeId,
|
||||
});
|
||||
|
||||
const [updateEntityMutation] = useUpdateOnePersonMutation();
|
||||
|
||||
const { persistViewFields } = useViewFields(viewScopeId);
|
||||
|
||||
const { setContextMenuEntries, setActionBarEntries } =
|
||||
usePersonTableContextMenuEntries();
|
||||
|
||||
const updatePerson = async (variables: UpdateOnePersonMutationVariables) => {
|
||||
updateEntityMutation({
|
||||
variables: variables,
|
||||
onCompleted: (data) => {
|
||||
if (!data.updateOnePerson) {
|
||||
return;
|
||||
}
|
||||
upsertRecordTableItem(data.updateOnePerson);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleColumnChange = (columns: ColumnDefinition<FieldMetadata>[]) => {
|
||||
persistViewFields(mapColumnDefinitionsToViewFields(columns));
|
||||
};
|
||||
|
||||
const { openPersonSpreadsheetImport: onImport } =
|
||||
useSpreadsheetPersonImport();
|
||||
|
||||
const { setEntityCountInCurrentView } = useView({ viewScopeId });
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
`;
|
||||
|
||||
return (
|
||||
<ViewScope
|
||||
viewScopeId={viewScopeId}
|
||||
onViewFieldsChange={(viewFields) => {
|
||||
setTableColumns(
|
||||
mapViewFieldsToColumnDefinitions(
|
||||
viewFields,
|
||||
peopleAvailableFieldDefinitions,
|
||||
),
|
||||
);
|
||||
}}
|
||||
onViewFiltersChange={(viewFilters) => {
|
||||
setTableFilters(mapViewFiltersToFilters(viewFilters));
|
||||
}}
|
||||
onViewSortsChange={(viewSorts) => {
|
||||
setTableSorts(mapViewSortsToSorts(viewSorts));
|
||||
}}
|
||||
>
|
||||
<StyledContainer>
|
||||
<RecordTableScope
|
||||
recordTableScopeId={tableScopeId}
|
||||
onColumnsChange={handleColumnChange}
|
||||
onEntityCountChange={(entityCount) => {
|
||||
setEntityCountInCurrentView(entityCount);
|
||||
}}
|
||||
>
|
||||
<ViewBar
|
||||
optionsDropdownButton={<TableOptionsDropdown onImport={onImport} />}
|
||||
optionsDropdownScopeId={TableOptionsDropdownId}
|
||||
/>
|
||||
<PersonTableEffect />
|
||||
<RecordTableEffect
|
||||
getRequestResultKey="people"
|
||||
useGetRequest={useGetPeopleQuery}
|
||||
getRequestOptimisticEffectDefinition={
|
||||
getPeopleOptimisticEffectDefinition
|
||||
}
|
||||
filterDefinitionArray={personTableFilterDefinitions}
|
||||
sortDefinitionArray={personTableSortDefinitions}
|
||||
setContextMenuEntries={setContextMenuEntries}
|
||||
setActionBarEntries={setActionBarEntries}
|
||||
/>
|
||||
<RecordTableV1
|
||||
updateEntityMutation={({
|
||||
variables,
|
||||
}: {
|
||||
variables: UpdateOnePersonMutationVariables;
|
||||
}) => updatePerson(variables)}
|
||||
/>
|
||||
</RecordTableScope>
|
||||
</StyledContainer>
|
||||
</ViewScope>
|
||||
);
|
||||
};
|
||||
@ -1,41 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { peopleAvailableFieldDefinitions } from '@/people/constants/peopleAvailableFieldDefinitions';
|
||||
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
|
||||
import { useView } from '@/views/hooks/useView';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { personTableFilterDefinitions } from '~/pages/people/constants/personTableFilterDefinitions';
|
||||
import { personTableSortDefinitions } from '~/pages/people/constants/personTableSortDefinitions';
|
||||
|
||||
const PeopleTableEffect = () => {
|
||||
const {
|
||||
setAvailableSortDefinitions,
|
||||
setAvailableFilterDefinitions,
|
||||
setAvailableFieldDefinitions,
|
||||
setViewType,
|
||||
setViewObjectMetadataId,
|
||||
} = useView();
|
||||
|
||||
const { setAvailableTableColumns } = useRecordTable();
|
||||
|
||||
useEffect(() => {
|
||||
setAvailableSortDefinitions?.(personTableSortDefinitions);
|
||||
setAvailableFilterDefinitions?.(personTableFilterDefinitions);
|
||||
setAvailableFieldDefinitions?.(peopleAvailableFieldDefinitions);
|
||||
setViewObjectMetadataId?.('person');
|
||||
setViewType?.(ViewType.Table);
|
||||
|
||||
setAvailableTableColumns(peopleAvailableFieldDefinitions);
|
||||
}, [
|
||||
setAvailableFieldDefinitions,
|
||||
setAvailableFilterDefinitions,
|
||||
setAvailableSortDefinitions,
|
||||
setAvailableTableColumns,
|
||||
setViewObjectMetadataId,
|
||||
setViewType,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
export default PeopleTableEffect;
|
||||
24
front/src/modules/people/types/Person.ts
Normal file
24
front/src/modules/people/types/Person.ts
Normal file
@ -0,0 +1,24 @@
|
||||
export type Person = {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
deletedAt: string | null;
|
||||
name: {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
};
|
||||
avatarUrl: string;
|
||||
jobTitle: string;
|
||||
linkedinLink: {
|
||||
url: string;
|
||||
label: string;
|
||||
};
|
||||
xLink: {
|
||||
url: string;
|
||||
label: string;
|
||||
};
|
||||
city: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
companyId: string;
|
||||
};
|
||||
Reference in New Issue
Block a user