Fix context menu and favorites (#2564)
This commit is contained in:
@ -36,7 +36,9 @@ export const useCompanyTableContextMenuEntries = () => {
|
||||
|
||||
const { data } = useGetFavoritesQuery();
|
||||
const favorites = data?.findFavorites;
|
||||
const { createFavorite, deleteFavorite } = useFavorites();
|
||||
const { createFavorite, deleteFavorite } = useFavorites({
|
||||
objectNamePlural: 'companies',
|
||||
});
|
||||
|
||||
const handleFavoriteButtonClick = useRecoilCallback(({ snapshot }) => () => {
|
||||
const selectedRowIds = snapshot
|
||||
|
||||
@ -24,7 +24,10 @@ const StyledContainer = styled.div`
|
||||
`;
|
||||
|
||||
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<
|
||||
Record<string, { name: string; domainName?: string }>
|
||||
>({});
|
||||
|
||||
@ -8,38 +8,45 @@ import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOne
|
||||
|
||||
import { favoritesState } from '../states/favoritesState';
|
||||
|
||||
export const useFavorites = () => {
|
||||
export const useFavorites = ({
|
||||
objectNamePlural,
|
||||
}: {
|
||||
objectNamePlural: string | undefined;
|
||||
}) => {
|
||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||
|
||||
const [favorites, setFavorites] = useRecoilState(favoritesState);
|
||||
|
||||
const { updateOneMutation, createOneMutation, deleteOneMutation } =
|
||||
useFindOneObjectMetadataItem({
|
||||
objectNameSingular: 'favoriteV2',
|
||||
objectNamePlural: 'favoritesV2',
|
||||
});
|
||||
|
||||
const { foundObjectMetadataItem: favoriteTargetObjectMetadataItem } =
|
||||
useFindOneObjectMetadataItem({
|
||||
objectNamePlural,
|
||||
});
|
||||
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const createFavorite = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (
|
||||
favoriteNameToCreate: string,
|
||||
favoriteIdToCreate: string,
|
||||
additionalData?: any,
|
||||
) => {
|
||||
async (favoriteTargetObjectId: string, additionalData?: any) => {
|
||||
const favoritesStateFromSnapshot = snapshot.getLoadable(favoritesState);
|
||||
const favorites = favoritesStateFromSnapshot.getValue();
|
||||
if (!favoriteNameToCreate || !favoriteIdToCreate) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetObjectName =
|
||||
favoriteTargetObjectMetadataItem?.nameSingular.replace('V2', '') ??
|
||||
'';
|
||||
|
||||
const result = await apolloClient.mutate({
|
||||
mutation: createOneMutation,
|
||||
variables: {
|
||||
input: {
|
||||
[favoriteNameToCreate]: favoriteIdToCreate,
|
||||
[`${targetObjectName}Id`]: favoriteTargetObjectId,
|
||||
position: favorites.length + 1,
|
||||
workspaceMember: currentWorkspaceMember?.id,
|
||||
// workspaceMember: currentWorkspaceMember?.id,
|
||||
workspaceMemberId: currentWorkspaceMember?.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -48,14 +55,19 @@ export const useFavorites = () => {
|
||||
|
||||
const newFavorite = {
|
||||
...additionalData,
|
||||
...createdFavorite[favoriteNameToCreate],
|
||||
...createdFavorite[targetObjectName],
|
||||
};
|
||||
|
||||
if (createdFavorite) {
|
||||
set(favoritesState, [...favorites, newFavorite]);
|
||||
}
|
||||
},
|
||||
[apolloClient, createOneMutation, currentWorkspaceMember?.id],
|
||||
[
|
||||
apolloClient,
|
||||
createOneMutation,
|
||||
currentWorkspaceMember?.id,
|
||||
favoriteTargetObjectMetadataItem,
|
||||
],
|
||||
);
|
||||
|
||||
const _updateFavoritePosition = useRecoilCallback(
|
||||
|
||||
@ -36,14 +36,16 @@ export const RecordShowPage = () => {
|
||||
objectMetadataId: string;
|
||||
}>();
|
||||
|
||||
const { favorites, createFavorite, deleteFavorite } = useFavorites();
|
||||
|
||||
const { icons } = useLazyLoadIcons();
|
||||
|
||||
const { foundObjectMetadataItem } = useFindOneObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const { favorites, createFavorite, deleteFavorite } = useFavorites({
|
||||
objectNamePlural: foundObjectMetadataItem?.namePlural,
|
||||
});
|
||||
|
||||
const [, setEntityFields] = useRecoilState(
|
||||
entityFieldsFamilyState(objectMetadataId ?? ''),
|
||||
);
|
||||
@ -106,11 +108,7 @@ export const RecordShowPage = () => {
|
||||
recordId: object.id,
|
||||
}
|
||||
: {};
|
||||
createFavorite(
|
||||
objectNameSingular.replace('V2', ''),
|
||||
object.id,
|
||||
additionalData,
|
||||
);
|
||||
createFavorite(object.id, additionalData);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||
import { useRecordTableContextMenuEntries } from '@/object-record/hooks/useRecordTableContextMenuEntries';
|
||||
import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
|
||||
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
|
||||
import { useView } from '@/views/hooks/useView';
|
||||
@ -56,5 +57,13 @@ export const RecordTableEffect = () => {
|
||||
setAvailableTableColumns,
|
||||
]);
|
||||
|
||||
const { setActionBarEntries, setContextMenuEntries } =
|
||||
useRecordTableContextMenuEntries();
|
||||
|
||||
useEffect(() => {
|
||||
setActionBarEntries?.();
|
||||
setContextMenuEntries?.();
|
||||
}, [setActionBarEntries, setContextMenuEntries]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
@ -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(),
|
||||
},
|
||||
]);
|
||||
}),
|
||||
};
|
||||
};
|
||||
@ -36,7 +36,9 @@ export const usePersonTableContextMenuEntries = () => {
|
||||
|
||||
const { data } = useGetFavoritesQuery();
|
||||
const favorites = data?.findFavorites;
|
||||
const { createFavorite, deleteFavorite } = useFavorites();
|
||||
const { createFavorite, deleteFavorite } = useFavorites({
|
||||
objectNamePlural: 'people',
|
||||
});
|
||||
|
||||
const handleFavoriteButtonClick = useRecoilCallback(({ snapshot }) => () => {
|
||||
const selectedRowIds = snapshot
|
||||
|
||||
@ -13,7 +13,7 @@ export type AvatarSize = 'xl' | 'lg' | 'md' | 'sm' | 'xs';
|
||||
export type AvatarProps = {
|
||||
avatarUrl: string | null | undefined;
|
||||
size?: AvatarSize;
|
||||
placeholder: string;
|
||||
placeholder: string | undefined;
|
||||
colorId?: string;
|
||||
type?: AvatarType;
|
||||
onClick?: () => void;
|
||||
@ -118,11 +118,11 @@ export const Avatar = ({
|
||||
placeholder={placeholder}
|
||||
size={size}
|
||||
type={type}
|
||||
colorId={colorId}
|
||||
colorId={colorId ?? ''}
|
||||
onClick={onClick}
|
||||
>
|
||||
{(noAvatarUrl || isInvalidAvatarUrl) &&
|
||||
placeholder[0]?.toLocaleUpperCase()}
|
||||
placeholder?.[0]?.toLocaleUpperCase()}
|
||||
</StyledAvatar>
|
||||
);
|
||||
};
|
||||
|
||||
@ -31,7 +31,9 @@ import { companyShowFieldDefinitions } from './constants/companyShowFieldDefinit
|
||||
|
||||
export const CompanyShow = () => {
|
||||
const companyId = useParams().companyId ?? '';
|
||||
const { createFavorite, deleteFavorite } = useFavorites();
|
||||
const { createFavorite, deleteFavorite } = useFavorites({
|
||||
objectNamePlural: 'companies',
|
||||
});
|
||||
const navigate = useNavigate();
|
||||
const { data, loading } = useCompanyQuery(companyId);
|
||||
const company = data?.findUniqueCompany;
|
||||
|
||||
@ -34,7 +34,9 @@ import { personShowFieldDefinition } from './constants/personShowFieldDefinition
|
||||
|
||||
export const PersonShow = () => {
|
||||
const personId = useParams().personId ?? '';
|
||||
const { createFavorite, deleteFavorite } = useFavorites();
|
||||
const { createFavorite, deleteFavorite } = useFavorites({
|
||||
objectNamePlural: 'peopleV2',
|
||||
});
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { data, loading } = usePersonQuery(personId);
|
||||
|
||||
@ -125,11 +125,10 @@ export const seedCompanyFieldMetadata = async (
|
||||
},
|
||||
description: 'The company name',
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
isNullable: false,
|
||||
isNullable: true,
|
||||
isSystem: false,
|
||||
defaultValue: { value: '' },
|
||||
},
|
||||
|
||||
// Scalar Fields
|
||||
{
|
||||
id: SeedCompanyFieldMetadataIds.DomainName,
|
||||
|
||||
@ -135,7 +135,7 @@ export const seedFavoriteFieldMetadata = async (
|
||||
targetColumnMap: {},
|
||||
description: 'Favorite workspace member',
|
||||
icon: 'IconCircleUser',
|
||||
isNullable: false,
|
||||
isNullable: true,
|
||||
isSystem: false,
|
||||
defaultValue: undefined,
|
||||
},
|
||||
@ -151,7 +151,7 @@ export const seedFavoriteFieldMetadata = async (
|
||||
targetColumnMap: {},
|
||||
description: 'Foreign key for workspace member',
|
||||
icon: undefined,
|
||||
isNullable: false,
|
||||
isNullable: true,
|
||||
isSystem: true,
|
||||
defaultValue: undefined,
|
||||
},
|
||||
@ -185,7 +185,7 @@ export const seedFavoriteFieldMetadata = async (
|
||||
targetColumnMap: {},
|
||||
description: 'Foreign key for person',
|
||||
icon: undefined,
|
||||
isNullable: false,
|
||||
isNullable: true,
|
||||
isSystem: true,
|
||||
defaultValue: undefined,
|
||||
},
|
||||
@ -217,7 +217,7 @@ export const seedFavoriteFieldMetadata = async (
|
||||
targetColumnMap: {},
|
||||
description: 'Foreign key for company',
|
||||
icon: undefined,
|
||||
isNullable: false,
|
||||
isNullable: true,
|
||||
isSystem: true,
|
||||
defaultValue: undefined,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user