feat: detach records from Relation field card in Show Page (#3350)

* feat: detach records from Relation field card in Show Page

Closes #3128

* Fix TS

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Thaïs
2024-01-12 08:10:42 -03:00
committed by GitHub
parent d0ed9ee2e0
commit 0dc39db314
4 changed files with 110 additions and 15 deletions

View File

@ -30,7 +30,7 @@ module.exports = {
patterns: [
{
group: ['@tabler/icons-react'],
message: 'Icon imports are only allowed for `@/ui/icon`',
message: 'Icon imports are only allowed for `@/ui/display/icon`',
},
{
group: ['react-hotkeys-web-hook'],

View File

@ -1,52 +1,146 @@
import { useContext } from 'react';
import { css } from '@emotion/react';
import styled from '@emotion/styled';
import { LightIconButton, MenuItem } from 'tsup.ui.index';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { FieldDisplay } from '@/object-record/field/components/FieldDisplay';
import { FieldContext } from '@/object-record/field/contexts/FieldContext';
import { usePersistField } from '@/object-record/field/hooks/usePersistField';
import { FieldRelationMetadata } from '@/object-record/field/types/FieldMetadata';
import { useFieldContext } from '@/object-record/hooks/useFieldContext';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { IconDotsVertical, IconUnlink } from '@/ui/display/icon';
import { CardContent } from '@/ui/layout/card/components/CardContent';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
const StyledCardContent = styled(CardContent)`
const StyledCardContent = styled(CardContent)<{
isDropdownOpen?: boolean;
}>`
align-items: center;
justify-content: space-between;
gap: ${({ theme }) => theme.spacing(1)};
display: flex;
height: ${({ theme }) => theme.spacing(10)};
padding: ${({ theme }) => theme.spacing(0, 2, 0, 3)};
${({ isDropdownOpen, theme }) =>
isDropdownOpen
? ''
: css`
.displayOnHover {
opacity: 0;
pointer-events: none;
transition: opacity ${theme.animation.duration.instant}s ease;
}
`}
&:hover {
.displayOnHover {
opacity: 1;
pointer-events: auto;
}
}
`;
type RecordRelationFieldCardContentProps = {
divider?: boolean;
relationRecordId: string;
relationRecord: ObjectRecord;
};
export const RecordRelationFieldCardContent = ({
divider,
relationRecordId,
relationRecord,
}: RecordRelationFieldCardContentProps) => {
const { fieldDefinition } = useContext(FieldContext);
const { relationObjectMetadataNameSingular } =
fieldDefinition.metadata as FieldRelationMetadata;
const { labelIdentifierFieldMetadata: relationLabelIdentifierFieldMetadata } =
useObjectMetadataItem({
objectNameSingular: relationObjectMetadataNameSingular,
});
const {
relationFieldMetadataId,
relationObjectMetadataNameSingular,
relationType,
} = fieldDefinition.metadata as FieldRelationMetadata;
const isToOneObject = relationType === 'TO_ONE_OBJECT';
const {
labelIdentifierFieldMetadata: relationLabelIdentifierFieldMetadata,
objectMetadataItem: relationObjectMetadataItem,
} = useObjectMetadataItem({
objectNameSingular: relationObjectMetadataNameSingular,
});
const persistField = usePersistField();
const { updateOneRecord: updateOneRelationRecord } = useUpdateOneRecord({
objectNameSingular: relationObjectMetadataNameSingular,
});
const { FieldContextProvider } = useFieldContext({
fieldMetadataName: relationLabelIdentifierFieldMetadata?.name || '',
fieldPosition: 0,
isLabelIdentifier: true,
objectNameSingular: relationObjectMetadataNameSingular,
objectRecordId: relationRecordId,
objectRecordId: relationRecord.id,
});
const dropdownScopeId = `record-field-card-menu-${relationRecord.id}`;
const { closeDropdown, isDropdownOpen } = useDropdown(dropdownScopeId);
if (!FieldContextProvider) return null;
const handleDetach = () => {
closeDropdown();
const relationFieldMetadataItem = relationObjectMetadataItem.fields.find(
({ id }) => id === relationFieldMetadataId,
);
if (!relationFieldMetadataItem?.name) return;
if (isToOneObject) {
persistField(null);
return;
}
updateOneRelationRecord({
idToUpdate: relationRecord.id,
updateOneRecordInput: {
[`${relationFieldMetadataItem.name}Id`]: null,
[relationFieldMetadataItem.name]: null,
},
});
};
return (
<StyledCardContent divider={divider}>
<StyledCardContent isDropdownOpen={isDropdownOpen} divider={divider}>
<FieldContextProvider>
<FieldDisplay />
</FieldContextProvider>
<DropdownScope dropdownScopeId={dropdownScopeId}>
<Dropdown
dropdownId={dropdownScopeId}
dropdownPlacement="right-start"
clickableComponent={
<LightIconButton
className="displayOnHover"
Icon={IconDotsVertical}
accent="tertiary"
/>
}
dropdownComponents={
<DropdownMenuItemsContainer>
<MenuItem
LeftIcon={IconUnlink}
text="Detach"
onClick={handleDetach}
/>
</DropdownMenuItemsContainer>
}
dropdownHotkeyScope={{
scope: dropdownScopeId,
}}
/>
</DropdownScope>
</StyledCardContent>
);
};

View File

@ -183,7 +183,7 @@ export const RecordRelationFieldCardSection = () => {
}, [setRelationPickerSearchFilter]);
const persistField = usePersistField();
const { updateOneRecord } = useUpdateOneRecord({
const { updateOneRecord: updateOneRelationRecord } = useUpdateOneRecord({
objectNameSingular: relationObjectMetadataNameSingular,
});
@ -201,7 +201,7 @@ export const RecordRelationFieldCardSection = () => {
if (!relationFieldMetadataItem?.name) return;
updateOneRecord({
updateOneRelationRecord({
idToUpdate: selectedRelationEntity.id,
updateOneRecordInput: {
[`${relationFieldMetadataItem.name}Id`]: entityId,
@ -267,7 +267,7 @@ export const RecordRelationFieldCardSection = () => {
<RecordRelationFieldCardContent
key={`${relationRecord.id}${relationLabelIdentifierFieldMetadata?.id}`}
divider={index < relationRecords.length - 1}
relationRecordId={relationRecord.id}
relationRecord={relationRecord}
/>
))}
</Card>

View File

@ -108,6 +108,7 @@ export {
IconTextSize,
IconTimelineEvent,
IconTrash,
IconUnlink,
IconUpload,
IconUser,
IconUserCircle,