Fix remote object read-only + remove relations (#4921)
- Set `readOnly` boolean in table row context. Preventing updates and deletion - Show page is null for remote objects. No need for complicated design since this is temporary? - Relation creations are now behind a feature flag for remote objects - Refetch objects and views after syncing objects --------- Co-authored-by: Thomas Trompette <thomast@twenty.com>
This commit is contained in:
@ -106,7 +106,21 @@ export const useRecordActionBar = ({
|
||||
recordIndexId: objectMetadataItem.namePlural,
|
||||
});
|
||||
|
||||
const isRemoteObject = objectMetadataItem.isRemote;
|
||||
|
||||
const baseActions: ContextMenuEntry[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
label: `${progress === undefined ? `Export` : `Export (${progress}%)`}`,
|
||||
Icon: IconFileExport,
|
||||
accent: 'default',
|
||||
onClick: () => download(),
|
||||
},
|
||||
],
|
||||
[download, progress],
|
||||
);
|
||||
|
||||
const deletionActions: ContextMenuEntry[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
label: 'Delete',
|
||||
@ -130,17 +144,9 @@ export const useRecordActionBar = ({
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: `${progress === undefined ? `Export` : `Export (${progress}%)`}`,
|
||||
Icon: IconFileExport,
|
||||
accent: 'default',
|
||||
onClick: () => download(),
|
||||
},
|
||||
],
|
||||
[
|
||||
handleDeleteClick,
|
||||
download,
|
||||
progress,
|
||||
selectedRecordIds,
|
||||
isDeleteRecordsModalOpen,
|
||||
setIsDeleteRecordsModalOpen,
|
||||
@ -160,8 +166,9 @@ export const useRecordActionBar = ({
|
||||
return {
|
||||
setContextMenuEntries: useCallback(() => {
|
||||
setContextMenuEntries([
|
||||
...(isRemoteObject ? [] : deletionActions),
|
||||
...baseActions,
|
||||
...(isFavorite && hasOnlyOneRecordSelected
|
||||
...(!isRemoteObject && isFavorite && hasOnlyOneRecordSelected
|
||||
? [
|
||||
{
|
||||
label: 'Remove from favorites',
|
||||
@ -170,7 +177,7 @@ export const useRecordActionBar = ({
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(!isFavorite && hasOnlyOneRecordSelected
|
||||
...(!isRemoteObject && !isFavorite && hasOnlyOneRecordSelected
|
||||
? [
|
||||
{
|
||||
label: 'Add to favorites',
|
||||
@ -182,9 +189,11 @@ export const useRecordActionBar = ({
|
||||
]);
|
||||
}, [
|
||||
baseActions,
|
||||
deletionActions,
|
||||
handleFavoriteButtonClick,
|
||||
hasOnlyOneRecordSelected,
|
||||
isFavorite,
|
||||
isRemoteObject,
|
||||
setContextMenuEntries,
|
||||
]),
|
||||
|
||||
@ -209,12 +218,15 @@ export const useRecordActionBar = ({
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(isRemoteObject ? [] : deletionActions),
|
||||
...baseActions,
|
||||
]);
|
||||
}, [
|
||||
baseActions,
|
||||
dataExecuteQuickActionOnmentEnabled,
|
||||
deletionActions,
|
||||
handleExecuteQuickActionOnClick,
|
||||
isRemoteObject,
|
||||
setActionBarEntriesState,
|
||||
]),
|
||||
};
|
||||
|
||||
@ -47,6 +47,7 @@ type FieldInputProps = {
|
||||
onEscape?: FieldInputEvent;
|
||||
onTab?: FieldInputEvent;
|
||||
onShiftTab?: FieldInputEvent;
|
||||
isReadOnly?: boolean;
|
||||
};
|
||||
|
||||
export const FieldInput = ({
|
||||
@ -58,6 +59,7 @@ export const FieldInput = ({
|
||||
onShiftTab,
|
||||
onTab,
|
||||
onClickOutside,
|
||||
isReadOnly,
|
||||
}: FieldInputProps) => {
|
||||
const { fieldDefinition } = useContext(FieldContext);
|
||||
|
||||
@ -136,7 +138,7 @@ export const FieldInput = ({
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : isFieldBoolean(fieldDefinition) ? (
|
||||
<BooleanFieldInput onSubmit={onSubmit} />
|
||||
<BooleanFieldInput onSubmit={onSubmit} readonly={isReadOnly} />
|
||||
) : isFieldRating(fieldDefinition) ? (
|
||||
<RatingFieldInput onSubmit={onSubmit} />
|
||||
) : isFieldSelect(fieldDefinition) ? (
|
||||
|
||||
@ -92,6 +92,7 @@ export const RecordInlineCell = ({ readonly }: RecordInlineCellProps) => {
|
||||
onTab={handleTab}
|
||||
onShiftTab={handleShiftTab}
|
||||
onClickOutside={handleClickOutside}
|
||||
isReadOnly={readonly}
|
||||
/>
|
||||
}
|
||||
displayModeContent={<FieldDisplay />}
|
||||
|
||||
@ -47,6 +47,7 @@ export const RecordTableRow = ({ recordId, rowIndex }: RecordTableRowProps) => {
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
}) + recordId,
|
||||
isSelected: currentRowSelected,
|
||||
isReadOnly: objectMetadataItem.isRemote ?? false,
|
||||
}}
|
||||
>
|
||||
<tr
|
||||
|
||||
@ -5,6 +5,7 @@ type RecordTableRowContextProps = {
|
||||
recordId: string;
|
||||
rowIndex: number;
|
||||
isSelected: boolean;
|
||||
isReadOnly: boolean;
|
||||
};
|
||||
|
||||
export const RecordTableRowContext = createContext<RecordTableRowContextProps>(
|
||||
|
||||
@ -4,6 +4,7 @@ import { FieldDisplay } from '@/object-record/record-field/components/FieldDispl
|
||||
import { FieldInput } from '@/object-record/record-field/components/FieldInput';
|
||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||
import { FieldInputEvent } from '@/object-record/record-field/types/FieldInputEvent';
|
||||
import { RecordTableRowContext } from '@/object-record/record-table/contexts/RecordTableRowContext';
|
||||
import { useRecordTableMoveFocus } from '@/object-record/record-table/hooks/useRecordTableMoveFocus';
|
||||
import { RecordTableCellContainer } from '@/object-record/record-table/record-table-cell/components/RecordTableCellContainer';
|
||||
import { useCloseRecordTableCell } from '@/object-record/record-table/record-table-cell/hooks/useCloseRecordTableCell';
|
||||
@ -21,6 +22,7 @@ export const RecordTableCell = ({
|
||||
const { moveLeft, moveRight, moveDown } = useRecordTableMoveFocus();
|
||||
|
||||
const { entityId, fieldDefinition } = useContext(FieldContext);
|
||||
const { isReadOnly } = useContext(RecordTableRowContext);
|
||||
|
||||
const handleEnter: FieldInputEvent = (persistField) => {
|
||||
upsertRecord(persistField);
|
||||
@ -78,6 +80,7 @@ export const RecordTableCell = ({
|
||||
onShiftTab={handleShiftTab}
|
||||
onSubmit={handleSubmit}
|
||||
onTab={handleTab}
|
||||
isReadOnly={isReadOnly}
|
||||
/>
|
||||
}
|
||||
nonEditModeContent={<FieldDisplay />}
|
||||
|
||||
@ -90,7 +90,7 @@ export const RecordTableCellContainer = ({
|
||||
openTableCell();
|
||||
};
|
||||
|
||||
const { isSelected } = useContext(RecordTableRowContext);
|
||||
const { isSelected, isReadOnly } = useContext(RecordTableRowContext);
|
||||
|
||||
const setContextMenuPosition = useSetRecoilState(contextMenuPositionState);
|
||||
const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState);
|
||||
@ -146,7 +146,8 @@ export const RecordTableCellContainer = ({
|
||||
hasSoftFocus &&
|
||||
!isCurrentTableCellInEditMode &&
|
||||
!editModeContentOnly &&
|
||||
(!isFirstColumn || !isEmpty);
|
||||
(!isFirstColumn || !isEmpty) &&
|
||||
!isReadOnly;
|
||||
|
||||
return (
|
||||
<StyledTd
|
||||
|
||||
@ -23,7 +23,7 @@ export const DEFAULT_CELL_SCOPE: HotkeyScope = {
|
||||
};
|
||||
|
||||
export const useOpenRecordTableCell = () => {
|
||||
const { pathToShowPage } = useContext(RecordTableRowContext);
|
||||
const { pathToShowPage, isReadOnly } = useContext(RecordTableRowContext);
|
||||
|
||||
const { setCurrentTableCellInEditMode } = useCurrentTableCellEditMode();
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
@ -46,6 +46,10 @@ export const useOpenRecordTableCell = () => {
|
||||
|
||||
const openTableCell = useRecoilCallback(
|
||||
() => (options?: { initialValue?: string }) => {
|
||||
if (isReadOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isFirstColumnCell && !isEmpty) {
|
||||
leaveTableFocus();
|
||||
navigate(pathToShowPage);
|
||||
@ -70,15 +74,16 @@ export const useOpenRecordTableCell = () => {
|
||||
}
|
||||
},
|
||||
[
|
||||
isReadOnly,
|
||||
isFirstColumnCell,
|
||||
isEmpty,
|
||||
leaveTableFocus,
|
||||
navigate,
|
||||
pathToShowPage,
|
||||
setDragSelectionStartEnabled,
|
||||
setCurrentTableCellInEditMode,
|
||||
initFieldInputDraftValue,
|
||||
customCellHotkeyScope,
|
||||
leaveTableFocus,
|
||||
navigate,
|
||||
pathToShowPage,
|
||||
setHotkeyScope,
|
||||
],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user