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:
@ -1,10 +1,13 @@
|
||||
import { useCallback } from 'react';
|
||||
import { ApolloClient, useMutation } from '@apollo/client';
|
||||
import { ApolloClient, useApolloClient, useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
|
||||
import { SYNC_REMOTE_TABLE } from '@/databases/graphql/mutations/syncRemoteTable';
|
||||
import { GET_MANY_REMOTE_TABLES } from '@/databases/graphql/queries/findManyRemoteTables';
|
||||
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
|
||||
import { useFindManyObjectMetadataItems } from '@/object-metadata/hooks/useFindManyObjectMetadataItems';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useFindManyRecordsQuery } from '@/object-record/hooks/useFindManyRecordsQuery';
|
||||
import {
|
||||
RemoteTableInput,
|
||||
SyncRemoteTableMutation,
|
||||
@ -13,6 +16,14 @@ import {
|
||||
|
||||
export const useSyncRemoteTable = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const { refetch: refetchObjectMetadataItems } =
|
||||
useFindManyObjectMetadataItems();
|
||||
|
||||
const { findManyRecordsQuery: findManyViewsQuery } = useFindManyRecordsQuery({
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
});
|
||||
|
||||
const [mutate] = useMutation<
|
||||
SyncRemoteTableMutation,
|
||||
@ -23,15 +34,24 @@ export const useSyncRemoteTable = () => {
|
||||
|
||||
const syncRemoteTable = useCallback(
|
||||
async (input: RemoteTableInput) => {
|
||||
return await mutate({
|
||||
const remoteTable = await mutate({
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [getOperationName(GET_MANY_REMOTE_TABLES) ?? ''],
|
||||
});
|
||||
|
||||
// TODO: we should return the tables with the columns and store in cache instead of refetching
|
||||
await refetchObjectMetadataItems();
|
||||
await apolloClient.query({
|
||||
query: findManyViewsQuery,
|
||||
fetchPolicy: 'network-only',
|
||||
});
|
||||
|
||||
return remoteTable;
|
||||
},
|
||||
[mutate],
|
||||
[apolloClient, findManyViewsQuery, mutate, refetchObjectMetadataItems],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@ -5,6 +5,7 @@ import { getOperationName } from '@apollo/client/utilities';
|
||||
import { UNSYNC_REMOTE_TABLE } from '@/databases/graphql/mutations/unsyncRemoteTable';
|
||||
import { GET_MANY_REMOTE_TABLES } from '@/databases/graphql/queries/findManyRemoteTables';
|
||||
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
|
||||
import { useFindManyObjectMetadataItems } from '@/object-metadata/hooks/useFindManyObjectMetadataItems';
|
||||
import {
|
||||
RemoteTableInput,
|
||||
UnsyncRemoteTableMutation,
|
||||
@ -13,6 +14,8 @@ import {
|
||||
|
||||
export const useUnsyncRemoteTable = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
const { refetch: refetchObjectMetadataItems } =
|
||||
useFindManyObjectMetadataItems();
|
||||
|
||||
const [mutate] = useMutation<
|
||||
UnsyncRemoteTableMutation,
|
||||
@ -23,15 +26,19 @@ export const useUnsyncRemoteTable = () => {
|
||||
|
||||
const unsyncRemoteTable = useCallback(
|
||||
async (input: RemoteTableInput) => {
|
||||
return await mutate({
|
||||
const remoteTable = await mutate({
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [getOperationName(GET_MANY_REMOTE_TABLES) ?? ''],
|
||||
});
|
||||
|
||||
await refetchObjectMetadataItems();
|
||||
|
||||
return remoteTable;
|
||||
},
|
||||
[mutate],
|
||||
[mutate, refetchObjectMetadataItems],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@ -28,7 +28,7 @@ export const useFindManyObjectMetadataItems = ({
|
||||
|
||||
const { enqueueSnackBar } = useSnackBar();
|
||||
|
||||
const { data, loading, error } = useQuery<
|
||||
const { data, loading, error, refetch } = useQuery<
|
||||
ObjectMetadataItemsQuery,
|
||||
ObjectMetadataItemsQueryVariables
|
||||
>(FIND_MANY_OBJECT_METADATA_ITEMS, {
|
||||
@ -59,5 +59,6 @@ export const useFindManyObjectMetadataItems = ({
|
||||
objectMetadataItems,
|
||||
loading,
|
||||
error,
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
|
||||
@ -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,
|
||||
],
|
||||
);
|
||||
|
||||
@ -22,6 +22,7 @@ type SettingsObjectFieldItemTableRowProps = {
|
||||
fieldMetadataItem: FieldMetadataItem;
|
||||
identifierType?: Nullable<FieldIdentifierType>;
|
||||
variant?: 'field-type' | 'identifier';
|
||||
isRemoteObjectField?: boolean;
|
||||
};
|
||||
|
||||
export const StyledObjectFieldTableRow = styled(TableRow)`
|
||||
@ -43,6 +44,7 @@ export const SettingsObjectFieldItemTableRow = ({
|
||||
fieldMetadataItem,
|
||||
identifierType,
|
||||
variant = 'field-type',
|
||||
isRemoteObjectField,
|
||||
}: SettingsObjectFieldItemTableRowProps) => {
|
||||
const theme = useTheme();
|
||||
const { getIcon } = useIcons();
|
||||
@ -76,7 +78,11 @@ export const SettingsObjectFieldItemTableRow = ({
|
||||
</StyledNameTableCell>
|
||||
<TableCell>
|
||||
{variant === 'field-type' &&
|
||||
(fieldMetadataItem.isCustom ? 'Custom' : 'Standard')}
|
||||
(isRemoteObjectField
|
||||
? 'Remote'
|
||||
: fieldMetadataItem.isCustom
|
||||
? 'Custom'
|
||||
: 'Standard')}
|
||||
{variant === 'identifier' &&
|
||||
!!identifierType &&
|
||||
(identifierType === 'label' ? 'Record text' : 'Record image')}
|
||||
|
||||
@ -4,7 +4,8 @@ import styled from '@emotion/styled';
|
||||
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { SettingsDataModelIsCustomTag } from '@/settings/data-model/objects/SettingsDataModelIsCustomTag';
|
||||
import { SettingsDataModelObjectTypeTag } from '@/settings/data-model/objects/SettingsDataModelObjectTypeTag';
|
||||
import { getObjectTypeLabel } from '@/settings/data-model/utils/getObjectTypeLabel';
|
||||
import { useIcons } from '@/ui/display/icon/hooks/useIcons';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
@ -42,6 +43,7 @@ export const SettingsObjectItemTableRow = ({
|
||||
});
|
||||
const { getIcon } = useIcons();
|
||||
const Icon = getIcon(objectItem.icon);
|
||||
const objectTypeLabel = getObjectTypeLabel(objectItem);
|
||||
|
||||
return (
|
||||
<StyledObjectTableRow key={objectItem.namePlural} onClick={onClick}>
|
||||
@ -52,7 +54,7 @@ export const SettingsObjectItemTableRow = ({
|
||||
{objectItem.labelPlural}
|
||||
</StyledNameTableCell>
|
||||
<TableCell>
|
||||
<SettingsDataModelIsCustomTag isCustom={objectItem.isCustom} />
|
||||
<SettingsDataModelObjectTypeTag objectTypeLabel={objectTypeLabel} />
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
{objectItem.fields.filter((field) => !field.isSystem).length}
|
||||
|
||||
@ -2,8 +2,10 @@ import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconArchive, IconDotsVertical, IconPencil } from 'twenty-ui';
|
||||
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { SettingsSummaryCard } from '@/settings/components/SettingsSummaryCard';
|
||||
import { SettingsDataModelIsCustomTag } from '@/settings/data-model/objects/SettingsDataModelIsCustomTag';
|
||||
import { SettingsDataModelObjectTypeTag } from '@/settings/data-model/objects/SettingsDataModelObjectTypeTag';
|
||||
import { getObjectTypeLabel } from '@/settings/data-model/utils/getObjectTypeLabel';
|
||||
import { useIcons } from '@/ui/display/icon/hooks/useIcons';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
@ -13,14 +15,14 @@ import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
|
||||
type SettingsObjectSummaryCardProps = {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
iconKey?: string;
|
||||
isCustom: boolean;
|
||||
name: string;
|
||||
onDeactivate: () => void;
|
||||
onEdit: () => void;
|
||||
};
|
||||
|
||||
const StyledIsCustomTag = styled(SettingsDataModelIsCustomTag)`
|
||||
const StyledObjectTypeTag = styled(SettingsDataModelObjectTypeTag)`
|
||||
box-sizing: border-box;
|
||||
height: ${({ theme }) => theme.spacing(6)};
|
||||
`;
|
||||
@ -28,8 +30,8 @@ const StyledIsCustomTag = styled(SettingsDataModelIsCustomTag)`
|
||||
const dropdownId = 'settings-object-edit-about-menu-dropdown';
|
||||
|
||||
export const SettingsObjectSummaryCard = ({
|
||||
objectMetadataItem,
|
||||
iconKey = '',
|
||||
isCustom,
|
||||
name,
|
||||
onDeactivate,
|
||||
onEdit,
|
||||
@ -50,6 +52,8 @@ export const SettingsObjectSummaryCard = ({
|
||||
closeDropdown();
|
||||
};
|
||||
|
||||
const objectTypeLabel = getObjectTypeLabel(objectMetadataItem);
|
||||
|
||||
return (
|
||||
<SettingsSummaryCard
|
||||
title={
|
||||
@ -60,7 +64,7 @@ export const SettingsObjectSummaryCard = ({
|
||||
}
|
||||
rightComponent={
|
||||
<>
|
||||
<StyledIsCustomTag isCustom={isCustom} />
|
||||
<StyledObjectTypeTag objectTypeLabel={objectTypeLabel} />
|
||||
<Dropdown
|
||||
dropdownId={dropdownId}
|
||||
clickableComponent={
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
|
||||
type SettingsDataModelIsCustomTagProps = {
|
||||
className?: string;
|
||||
isCustom?: boolean;
|
||||
};
|
||||
|
||||
export const SettingsDataModelIsCustomTag = ({
|
||||
className,
|
||||
isCustom,
|
||||
}: SettingsDataModelIsCustomTagProps) => (
|
||||
<Tag
|
||||
className={className}
|
||||
color={isCustom ? 'orange' : 'blue'}
|
||||
text={isCustom ? 'Custom' : 'Standard'}
|
||||
weight="medium"
|
||||
/>
|
||||
);
|
||||
@ -2,15 +2,13 @@ import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { SettingsDataModelIsCustomTag } from '@/settings/data-model/objects/SettingsDataModelIsCustomTag';
|
||||
import { SettingsDataModelObjectTypeTag } from '@/settings/data-model/objects/SettingsDataModelObjectTypeTag';
|
||||
import { getObjectTypeLabel } from '@/settings/data-model/utils/getObjectTypeLabel';
|
||||
import { useIcons } from '@/ui/display/icon/hooks/useIcons';
|
||||
|
||||
export type SettingsDataModelObjectSummaryProps = {
|
||||
className?: string;
|
||||
objectMetadataItem: Pick<
|
||||
ObjectMetadataItem,
|
||||
'icon' | 'isCustom' | 'labelPlural'
|
||||
>;
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
};
|
||||
|
||||
const StyledObjectSummary = styled.div`
|
||||
@ -35,6 +33,7 @@ export const SettingsDataModelObjectSummary = ({
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
const ObjectIcon = getIcon(objectMetadataItem.icon);
|
||||
const objectTypeLabel = getObjectTypeLabel(objectMetadataItem);
|
||||
|
||||
return (
|
||||
<StyledObjectSummary className={className}>
|
||||
@ -42,7 +41,7 @@ export const SettingsDataModelObjectSummary = ({
|
||||
<ObjectIcon size={theme.icon.size.sm} stroke={theme.icon.stroke.md} />
|
||||
{objectMetadataItem.labelPlural}
|
||||
</StyledObjectName>
|
||||
<SettingsDataModelIsCustomTag isCustom={objectMetadataItem.isCustom} />
|
||||
<SettingsDataModelObjectTypeTag objectTypeLabel={objectTypeLabel} />
|
||||
</StyledObjectSummary>
|
||||
);
|
||||
};
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
import { ObjectTypeLabel } from '@/settings/data-model/utils/getObjectTypeLabel';
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
|
||||
type SettingsDataModelObjectTypeTagProps = {
|
||||
objectTypeLabel: ObjectTypeLabel;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const SettingsDataModelObjectTypeTag = ({
|
||||
className,
|
||||
objectTypeLabel,
|
||||
}: SettingsDataModelObjectTypeTagProps) => {
|
||||
return (
|
||||
<Tag
|
||||
className={className}
|
||||
color={objectTypeLabel.labelColor}
|
||||
text={objectTypeLabel.labelText}
|
||||
weight="medium"
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,39 @@
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
|
||||
export type ObjectTypeLabel =
|
||||
| StandardObjectTypeLabel
|
||||
| CustomObjectTypeLabel
|
||||
| RemoteObjectTypeLabel;
|
||||
|
||||
type StandardObjectTypeLabel = {
|
||||
labelText: 'Standard';
|
||||
labelColor: 'blue';
|
||||
};
|
||||
|
||||
type CustomObjectTypeLabel = {
|
||||
labelText: 'Custom';
|
||||
labelColor: 'orange';
|
||||
};
|
||||
|
||||
type RemoteObjectTypeLabel = {
|
||||
labelText: 'Remote';
|
||||
labelColor: 'green';
|
||||
};
|
||||
|
||||
export const getObjectTypeLabel = (
|
||||
objectMetadataItem: ObjectMetadataItem,
|
||||
): ObjectTypeLabel =>
|
||||
objectMetadataItem.isCustom
|
||||
? {
|
||||
labelText: 'Custom',
|
||||
labelColor: 'orange',
|
||||
}
|
||||
: objectMetadataItem.isRemote
|
||||
? {
|
||||
labelText: 'Remote',
|
||||
labelColor: 'green',
|
||||
}
|
||||
: {
|
||||
labelText: 'Standard',
|
||||
labelColor: 'blue',
|
||||
};
|
||||
@ -63,7 +63,7 @@ export const SettingsIntegrationDatabaseTablesListCard = ({
|
||||
});
|
||||
}
|
||||
},
|
||||
[connectionId, syncRemoteTable, items, unsyncRemoteTable],
|
||||
[items, syncRemoteTable, connectionId, unsyncRemoteTable],
|
||||
);
|
||||
|
||||
const rowRightComponent = useCallback(
|
||||
|
||||
Reference in New Issue
Block a user