Right drawer to edit records (#5551)
This PR introduces a new side panel to edit records and the ability to minimize the side panel. The goal is leverage this sidepanel to be able to create records while being in another show page. I'm opening the PR for feedback since it involved refactoring and therefore already touches a lot of files, even though it was quick to implement. <img width="1503" alt="Screenshot 2024-05-23 at 17 41 37" src="https://github.com/twentyhq/twenty/assets/6399865/6f17e7a8-f4e9-4eb4-b392-c756db7198ac">
This commit is contained in:
@ -35,7 +35,6 @@ export const RecordIndexPage = () => {
|
||||
|
||||
const handleAddButtonClick = async () => {
|
||||
setPendingRecordId(v4());
|
||||
|
||||
setSelectedTableCellEditMode(-1, 0);
|
||||
setHotkeyScope(DEFAULT_CELL_SCOPE.scope, DEFAULT_CELL_SCOPE.customScopes);
|
||||
};
|
||||
|
||||
@ -1,17 +1,9 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { useIcons } from 'twenty-ui';
|
||||
|
||||
import { useFavorites } from '@/favorites/hooks/useFavorites';
|
||||
import { useLabelIdentifierFieldMetadataItem } from '@/object-metadata/hooks/useLabelIdentifierFieldMetadataItem';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
||||
import { RecordShowContainer } from '@/object-record/record-show/components/RecordShowContainer';
|
||||
import { findOneRecordForShowPageOperationSignatureFactory } from '@/object-record/record-show/graphql/operations/factories/findOneRecordForShowPageOperationSignatureFactory';
|
||||
import { useRecordShowPage } from '@/object-record/record-show/hooks/useRecordShowPage';
|
||||
import { RecordValueSetterEffect } from '@/object-record/record-store/components/RecordValueSetterEffect';
|
||||
import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { PageBody } from '@/ui/layout/page/PageBody';
|
||||
import { PageContainer } from '@/ui/layout/page/PageContainer';
|
||||
import { PageFavoriteButton } from '@/ui/layout/page/PageFavoriteButton';
|
||||
@ -19,93 +11,29 @@ import { PageHeader } from '@/ui/layout/page/PageHeader';
|
||||
import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddButton';
|
||||
import { ShowPageMoreButton } from '@/ui/layout/show-page/components/ShowPageMoreButton';
|
||||
import { PageTitle } from '@/ui/utilities/page-title/PageTitle';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const RecordShowPage = () => {
|
||||
const { objectNameSingular, objectRecordId } = useParams<{
|
||||
const parameters = useParams<{
|
||||
objectNameSingular: string;
|
||||
objectRecordId: string;
|
||||
}>();
|
||||
|
||||
if (!objectNameSingular) {
|
||||
throw new Error(`Object name is not defined`);
|
||||
}
|
||||
|
||||
if (!objectRecordId) {
|
||||
throw new Error(`Record id is not defined`);
|
||||
}
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
const {
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const { labelIdentifierFieldMetadataItem } =
|
||||
useLabelIdentifierFieldMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const { favorites, createFavorite, deleteFavorite } = useFavorites();
|
||||
|
||||
const setEntityFields = useSetRecoilState(
|
||||
recordStoreFamilyState(objectRecordId),
|
||||
);
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
const headerIcon = getIcon(objectMetadataItem?.icon);
|
||||
|
||||
const FIND_ONE_RECORD_FOR_SHOW_PAGE_OPERATION_SIGNATURE =
|
||||
findOneRecordForShowPageOperationSignatureFactory({ objectMetadataItem });
|
||||
|
||||
const { record, loading } = useFindOneRecord({
|
||||
objectRecordId,
|
||||
objectNameSingular,
|
||||
recordGqlFields: FIND_ONE_RECORD_FOR_SHOW_PAGE_OPERATION_SIGNATURE.fields,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!record) {
|
||||
return;
|
||||
}
|
||||
|
||||
setEntityFields(record);
|
||||
}, [record, setEntityFields]);
|
||||
|
||||
const correspondingFavorite = favorites.find(
|
||||
(favorite) => favorite.recordId === objectRecordId,
|
||||
headerIcon,
|
||||
loading,
|
||||
pageTitle,
|
||||
pageName,
|
||||
isFavorite,
|
||||
handleFavoriteButtonClick,
|
||||
record,
|
||||
objectMetadataItem,
|
||||
} = useRecordShowPage(
|
||||
parameters.objectNameSingular ?? '',
|
||||
parameters.objectRecordId ?? '',
|
||||
);
|
||||
|
||||
const isFavorite = isDefined(correspondingFavorite);
|
||||
|
||||
const handleFavoriteButtonClick = async () => {
|
||||
if (!objectNameSingular || !record) return;
|
||||
|
||||
if (isFavorite && isDefined(record)) {
|
||||
deleteFavorite(correspondingFavorite.id);
|
||||
} else {
|
||||
createFavorite(record, objectNameSingular);
|
||||
}
|
||||
};
|
||||
|
||||
const labelIdentifierFieldValue =
|
||||
record?.[labelIdentifierFieldMetadataItem?.name ?? ''];
|
||||
|
||||
const pageName =
|
||||
labelIdentifierFieldMetadataItem?.type === FieldMetadataType.FullName
|
||||
? [
|
||||
labelIdentifierFieldValue?.firstName,
|
||||
labelIdentifierFieldValue?.lastName,
|
||||
].join(' ')
|
||||
: isDefined(labelIdentifierFieldValue)
|
||||
? `${labelIdentifierFieldValue}`
|
||||
: '';
|
||||
|
||||
const pageTitle = pageName.trim()
|
||||
? `${pageName} - ${capitalize(objectNameSingular)}`
|
||||
: capitalize(objectNameSingular);
|
||||
|
||||
return (
|
||||
<RecordFieldValueSelectorContextProvider>
|
||||
<RecordValueSetterEffect recordId={objectRecordId} />
|
||||
|
||||
Reference in New Issue
Block a user