[BUGFIX] Account owner should not be clickable & [Refactor] Chip.tsx links (#10359)

# Introduction

closes #10196 
Initially fixing the `Account Owner` record field value should not be
clickable and redirects on current page bug.
This has been fixed computing whereas the current filed is a workspace
member dynamically rendering a stale Chip components instead of an
interactive one

## Refactor
Refactored the `AvatarChip` `to` props logic to be scoped to lower level
scope `Chip`.
Now we have `LinkChip` `Chip`, `LinkAvatarChip` and `AvatarChip` all
exported from twenty-ui.

The caller has to determine which one to call from the design system

## New rule regarding chip links
As discussed with @charlesBochet and @FelixMalfait 
A chip link will now ***always*** have `to` defined. ( and optionally an
`onClick` ).
`ChipLinks` cannot be used as buttons anymore

## Factorization
Deleted the `RecordIndexRecordChip.tsx` file ( aka
`RecordIdentifierChip` component ) that was duplicating some logic,
refactored the `RecordChip` in order to handle what was covered by
`RecordIdentifierChip`

## Conclusion
As always any suggestions are more than welcomed ! Took few opinionated
decision/refactor regarding nested long ternaries rendering `ReactNode`
elements

## Misc


https://github.com/user-attachments/assets/8ef11fb2-7ba6-4e96-bd59-b0be5a425156

---------

Co-authored-by: Mohammed Razak <mohammedrazak2001@gmail.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
Paul Rastoin
2025-02-25 15:36:17 +01:00
committed by GitHub
parent fc0e98b53e
commit 89e11b4626
24 changed files with 387 additions and 302 deletions

View File

@ -1,4 +1,10 @@
import { AvatarChip, AvatarChipVariant } from 'twenty-ui';
import {
AvatarChip,
AvatarChipVariant,
ChipSize,
LinkAvatarChip,
isModifiedEvent,
} from 'twenty-ui';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { getLinkToShowPage } from '@/object-metadata/utils/getLinkToShowPage';
@ -6,14 +12,16 @@ import { useRecordChipData } from '@/object-record/hooks/useRecordChipData';
import { recordIndexOpenRecordInSelector } from '@/object-record/record-index/states/selectors/recordIndexOpenRecordInSelector';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { MouseEvent } from 'react';
import { useRecoilValue } from 'recoil';
export type RecordChipProps = {
objectNameSingular: string;
record: ObjectRecord;
className?: string;
variant?: AvatarChipVariant;
forceDisableClick?: boolean;
maxWidth?: number;
to?: string | undefined;
size?: ChipSize;
};
export const RecordChip = ({
@ -21,6 +29,10 @@ export const RecordChip = ({
record,
className,
variant,
maxWidth,
to,
size,
forceDisableClick = false,
}: RecordChipProps) => {
const { recordChipData } = useRecordChipData({
objectNameSingular,
@ -33,30 +45,52 @@ export const RecordChip = ({
recordIndexOpenRecordInSelector,
);
const handleClick = (e: MouseEvent<Element>) => {
e.stopPropagation();
if (recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL) {
openRecordInCommandMenu({
recordId: record.id,
objectNameSingular,
});
}
};
// TODO temporary until we create a record show page for Workspaces members
if (forceDisableClick) {
return (
<AvatarChip
size={size}
maxWidth={maxWidth}
placeholderColorSeed={record.id}
name={recordChipData.name}
avatarType={recordChipData.avatarType}
avatarUrl={recordChipData.avatarUrl ?? ''}
className={className}
/>
);
}
const isSidePanelViewOpenRecordInType =
recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL;
const onClick = isSidePanelViewOpenRecordInType
? () =>
openRecordInCommandMenu({
recordId: record.id,
objectNameSingular,
})
: undefined;
return (
<AvatarChip
<LinkAvatarChip
size={size}
maxWidth={maxWidth}
placeholderColorSeed={record.id}
name={recordChipData.name}
avatarType={recordChipData.avatarType}
avatarUrl={recordChipData.avatarUrl ?? ''}
className={className}
variant={variant}
onClick={handleClick}
to={
recordIndexOpenRecordIn === ViewOpenRecordInType.RECORD_PAGE
? getLinkToShowPage(objectNameSingular, record)
: undefined
}
to={to ?? getLinkToShowPage(objectNameSingular, record)}
onClick={(clickEvent) => {
// TODO refactor wrapper event listener to avoid colliding events
clickEvent.stopPropagation();
const isModifiedEventResult = isModifiedEvent(clickEvent);
if (isSidePanelViewOpenRecordInType && !isModifiedEventResult) {
clickEvent.preventDefault();
onClick?.();
}
}}
/>
);
};