Fix context menu and favorites (#2564)

This commit is contained in:
Lucas Bordeau
2023-11-17 16:24:43 +01:00
committed by GitHub
parent becd7c2ece
commit a6d8cdb116
12 changed files with 197 additions and 35 deletions

View File

@ -36,7 +36,9 @@ export const useCompanyTableContextMenuEntries = () => {
const { data } = useGetFavoritesQuery(); const { data } = useGetFavoritesQuery();
const favorites = data?.findFavorites; const favorites = data?.findFavorites;
const { createFavorite, deleteFavorite } = useFavorites(); const { createFavorite, deleteFavorite } = useFavorites({
objectNamePlural: 'companies',
});
const handleFavoriteButtonClick = useRecoilCallback(({ snapshot }) => () => { const handleFavoriteButtonClick = useRecoilCallback(({ snapshot }) => () => {
const selectedRowIds = snapshot const selectedRowIds = snapshot

View File

@ -24,7 +24,10 @@ const StyledContainer = styled.div`
`; `;
export const Favorites = () => { export const Favorites = () => {
const { favorites, handleReorderFavorite } = useFavorites(); // This is only temporary and will be refactored once we have main identifiers
const { favorites, handleReorderFavorite } = useFavorites({
objectNamePlural: 'companiesV2',
});
const [allCompanies, setAllCompanies] = useState< const [allCompanies, setAllCompanies] = useState<
Record<string, { name: string; domainName?: string }> Record<string, { name: string; domainName?: string }>
>({}); >({});

View File

@ -8,38 +8,45 @@ import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOne
import { favoritesState } from '../states/favoritesState'; import { favoritesState } from '../states/favoritesState';
export const useFavorites = () => { export const useFavorites = ({
objectNamePlural,
}: {
objectNamePlural: string | undefined;
}) => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const [favorites, setFavorites] = useRecoilState(favoritesState); const [favorites, setFavorites] = useRecoilState(favoritesState);
const { updateOneMutation, createOneMutation, deleteOneMutation } = const { updateOneMutation, createOneMutation, deleteOneMutation } =
useFindOneObjectMetadataItem({ useFindOneObjectMetadataItem({
objectNameSingular: 'favoriteV2', objectNamePlural: 'favoritesV2',
});
const { foundObjectMetadataItem: favoriteTargetObjectMetadataItem } =
useFindOneObjectMetadataItem({
objectNamePlural,
}); });
const apolloClient = useApolloClient(); const apolloClient = useApolloClient();
const createFavorite = useRecoilCallback( const createFavorite = useRecoilCallback(
({ snapshot, set }) => ({ snapshot, set }) =>
async ( async (favoriteTargetObjectId: string, additionalData?: any) => {
favoriteNameToCreate: string,
favoriteIdToCreate: string,
additionalData?: any,
) => {
const favoritesStateFromSnapshot = snapshot.getLoadable(favoritesState); const favoritesStateFromSnapshot = snapshot.getLoadable(favoritesState);
const favorites = favoritesStateFromSnapshot.getValue(); const favorites = favoritesStateFromSnapshot.getValue();
if (!favoriteNameToCreate || !favoriteIdToCreate) {
return; const targetObjectName =
} favoriteTargetObjectMetadataItem?.nameSingular.replace('V2', '') ??
'';
const result = await apolloClient.mutate({ const result = await apolloClient.mutate({
mutation: createOneMutation, mutation: createOneMutation,
variables: { variables: {
input: { input: {
[favoriteNameToCreate]: favoriteIdToCreate, [`${targetObjectName}Id`]: favoriteTargetObjectId,
position: favorites.length + 1, position: favorites.length + 1,
workspaceMember: currentWorkspaceMember?.id, // workspaceMember: currentWorkspaceMember?.id,
workspaceMemberId: currentWorkspaceMember?.id,
}, },
}, },
}); });
@ -48,14 +55,19 @@ export const useFavorites = () => {
const newFavorite = { const newFavorite = {
...additionalData, ...additionalData,
...createdFavorite[favoriteNameToCreate], ...createdFavorite[targetObjectName],
}; };
if (createdFavorite) { if (createdFavorite) {
set(favoritesState, [...favorites, newFavorite]); set(favoritesState, [...favorites, newFavorite]);
} }
}, },
[apolloClient, createOneMutation, currentWorkspaceMember?.id], [
apolloClient,
createOneMutation,
currentWorkspaceMember?.id,
favoriteTargetObjectMetadataItem,
],
); );
const _updateFavoritePosition = useRecoilCallback( const _updateFavoritePosition = useRecoilCallback(

View File

@ -36,14 +36,16 @@ export const RecordShowPage = () => {
objectMetadataId: string; objectMetadataId: string;
}>(); }>();
const { favorites, createFavorite, deleteFavorite } = useFavorites();
const { icons } = useLazyLoadIcons(); const { icons } = useLazyLoadIcons();
const { foundObjectMetadataItem } = useFindOneObjectMetadataItem({ const { foundObjectMetadataItem } = useFindOneObjectMetadataItem({
objectNameSingular, objectNameSingular,
}); });
const { favorites, createFavorite, deleteFavorite } = useFavorites({
objectNamePlural: foundObjectMetadataItem?.namePlural,
});
const [, setEntityFields] = useRecoilState( const [, setEntityFields] = useRecoilState(
entityFieldsFamilyState(objectMetadataId ?? ''), entityFieldsFamilyState(objectMetadataId ?? ''),
); );
@ -106,11 +108,7 @@ export const RecordShowPage = () => {
recordId: object.id, recordId: object.id,
} }
: {}; : {};
createFavorite( createFavorite(object.id, additionalData);
objectNameSingular.replace('V2', ''),
object.id,
additionalData,
);
} }
}; };

View File

@ -1,6 +1,7 @@
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem'; import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
import { useRecordTableContextMenuEntries } from '@/object-record/hooks/useRecordTableContextMenuEntries';
import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns'; import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { useView } from '@/views/hooks/useView'; import { useView } from '@/views/hooks/useView';
@ -56,5 +57,13 @@ export const RecordTableEffect = () => {
setAvailableTableColumns, setAvailableTableColumns,
]); ]);
const { setActionBarEntries, setContextMenuEntries } =
useRecordTableContextMenuEntries();
useEffect(() => {
setActionBarEntries?.();
setContextMenuEntries?.();
}, [setActionBarEntries, setContextMenuEntries]);
return <></>; return <></>;
}; };

View File

@ -0,0 +1,133 @@
import { useRecoilCallback, useSetRecoilState } from 'recoil';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { useDeleteOneObjectRecord } from '@/object-record/hooks/useDeleteOneObjectRecord';
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 { useGetFavoritesQuery } from '~/generated/graphql';
export const useRecordTableContextMenuEntries = () => {
const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState);
const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState);
const setTableRowIds = useSetRecoilState(tableRowIdsState);
const { scopeId: objectNamePlural, resetTableRowSelection } =
useRecordTable();
const { data } = useGetFavoritesQuery();
const favorites = data?.findFavorites;
const { createFavorite, deleteFavorite } = useFavorites({ objectNamePlural });
const handleFavoriteButtonClick = useRecoilCallback(({ snapshot }) => () => {
const selectedRowIds = snapshot
.getLoadable(selectedRowIdsSelector)
.getValue();
const selectedRowId = selectedRowIds.length === 1 ? selectedRowIds[0] : '';
const isFavorite =
!!selectedRowId &&
!!favorites?.find((favorite) => favorite.company?.id === selectedRowId);
resetTableRowSelection();
if (isFavorite) {
deleteFavorite(selectedRowId);
} else {
createFavorite(selectedRowId);
}
});
const { deleteOneObject } = useDeleteOneObjectRecord({
objectNamePlural,
});
const handleDeleteClick = useRecoilCallback(({ snapshot }) => async () => {
const rowIdsToDelete = snapshot
.getLoadable(selectedRowIdsSelector)
.getValue();
resetTableRowSelection();
if (deleteOneObject) {
for (const rowId of rowIdsToDelete) {
await deleteOneObject(rowId);
}
setTableRowIds((tableRowIds) =>
tableRowIds.filter((id) => !rowIdsToDelete.includes(id)),
);
}
});
return {
setContextMenuEntries: useRecoilCallback(({ snapshot }) => () => {
const selectedRowIds = snapshot
.getLoadable(selectedRowIdsSelector)
.getValue();
const selectedRowId =
selectedRowIds.length === 1 ? selectedRowIds[0] : '';
const isFavorite =
!!selectedRowId &&
!!favorites?.find((favorite) => favorite.company?.id === selectedRowId);
setContextMenuEntries([
{
label: 'New task',
Icon: IconCheckbox,
onClick: () => {},
},
{
label: 'New note',
Icon: IconNotes,
onClick: () => {},
},
{
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: () => {},
},
{
label: 'Note',
Icon: IconNotes,
onClick: () => {},
},
{
label: 'Delete',
Icon: IconTrash,
accent: 'danger',
onClick: () => handleDeleteClick(),
},
]);
}),
};
};

View File

@ -36,7 +36,9 @@ export const usePersonTableContextMenuEntries = () => {
const { data } = useGetFavoritesQuery(); const { data } = useGetFavoritesQuery();
const favorites = data?.findFavorites; const favorites = data?.findFavorites;
const { createFavorite, deleteFavorite } = useFavorites(); const { createFavorite, deleteFavorite } = useFavorites({
objectNamePlural: 'people',
});
const handleFavoriteButtonClick = useRecoilCallback(({ snapshot }) => () => { const handleFavoriteButtonClick = useRecoilCallback(({ snapshot }) => () => {
const selectedRowIds = snapshot const selectedRowIds = snapshot

View File

@ -13,7 +13,7 @@ export type AvatarSize = 'xl' | 'lg' | 'md' | 'sm' | 'xs';
export type AvatarProps = { export type AvatarProps = {
avatarUrl: string | null | undefined; avatarUrl: string | null | undefined;
size?: AvatarSize; size?: AvatarSize;
placeholder: string; placeholder: string | undefined;
colorId?: string; colorId?: string;
type?: AvatarType; type?: AvatarType;
onClick?: () => void; onClick?: () => void;
@ -118,11 +118,11 @@ export const Avatar = ({
placeholder={placeholder} placeholder={placeholder}
size={size} size={size}
type={type} type={type}
colorId={colorId} colorId={colorId ?? ''}
onClick={onClick} onClick={onClick}
> >
{(noAvatarUrl || isInvalidAvatarUrl) && {(noAvatarUrl || isInvalidAvatarUrl) &&
placeholder[0]?.toLocaleUpperCase()} placeholder?.[0]?.toLocaleUpperCase()}
</StyledAvatar> </StyledAvatar>
); );
}; };

View File

@ -31,7 +31,9 @@ import { companyShowFieldDefinitions } from './constants/companyShowFieldDefinit
export const CompanyShow = () => { export const CompanyShow = () => {
const companyId = useParams().companyId ?? ''; const companyId = useParams().companyId ?? '';
const { createFavorite, deleteFavorite } = useFavorites(); const { createFavorite, deleteFavorite } = useFavorites({
objectNamePlural: 'companies',
});
const navigate = useNavigate(); const navigate = useNavigate();
const { data, loading } = useCompanyQuery(companyId); const { data, loading } = useCompanyQuery(companyId);
const company = data?.findUniqueCompany; const company = data?.findUniqueCompany;

View File

@ -34,7 +34,9 @@ import { personShowFieldDefinition } from './constants/personShowFieldDefinition
export const PersonShow = () => { export const PersonShow = () => {
const personId = useParams().personId ?? ''; const personId = useParams().personId ?? '';
const { createFavorite, deleteFavorite } = useFavorites(); const { createFavorite, deleteFavorite } = useFavorites({
objectNamePlural: 'peopleV2',
});
const navigate = useNavigate(); const navigate = useNavigate();
const { data, loading } = usePersonQuery(personId); const { data, loading } = usePersonQuery(personId);

View File

@ -125,11 +125,10 @@ export const seedCompanyFieldMetadata = async (
}, },
description: 'The company name', description: 'The company name',
icon: 'IconBuildingSkyscraper', icon: 'IconBuildingSkyscraper',
isNullable: false, isNullable: true,
isSystem: false, isSystem: false,
defaultValue: { value: '' }, defaultValue: { value: '' },
}, },
// Scalar Fields // Scalar Fields
{ {
id: SeedCompanyFieldMetadataIds.DomainName, id: SeedCompanyFieldMetadataIds.DomainName,

View File

@ -135,7 +135,7 @@ export const seedFavoriteFieldMetadata = async (
targetColumnMap: {}, targetColumnMap: {},
description: 'Favorite workspace member', description: 'Favorite workspace member',
icon: 'IconCircleUser', icon: 'IconCircleUser',
isNullable: false, isNullable: true,
isSystem: false, isSystem: false,
defaultValue: undefined, defaultValue: undefined,
}, },
@ -151,7 +151,7 @@ export const seedFavoriteFieldMetadata = async (
targetColumnMap: {}, targetColumnMap: {},
description: 'Foreign key for workspace member', description: 'Foreign key for workspace member',
icon: undefined, icon: undefined,
isNullable: false, isNullable: true,
isSystem: true, isSystem: true,
defaultValue: undefined, defaultValue: undefined,
}, },
@ -185,7 +185,7 @@ export const seedFavoriteFieldMetadata = async (
targetColumnMap: {}, targetColumnMap: {},
description: 'Foreign key for person', description: 'Foreign key for person',
icon: undefined, icon: undefined,
isNullable: false, isNullable: true,
isSystem: true, isSystem: true,
defaultValue: undefined, defaultValue: undefined,
}, },
@ -217,7 +217,7 @@ export const seedFavoriteFieldMetadata = async (
targetColumnMap: {}, targetColumnMap: {},
description: 'Foreign key for company', description: 'Foreign key for company',
icon: undefined, icon: undefined,
isNullable: false, isNullable: true,
isSystem: true, isSystem: true,
defaultValue: undefined, defaultValue: undefined,
}, },