Do not override value for composite types address and links when entering input (#6502)
Closes #6434. We don't want to override the values of the records' address or links as they are composite field and it is costly to loose the data. We will need a more unified behaviour here - maybe introduce a Ctrl+Z option. --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -0,0 +1,6 @@
|
|||||||
|
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
|
export const FIELD_NOT_OVERWRITTEN_AT_DRAFT = [
|
||||||
|
FieldMetadataType.Address,
|
||||||
|
FieldMetadataType.Links,
|
||||||
|
];
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import { isUndefined } from '@sniptt/guards';
|
import { isUndefined } from '@sniptt/guards';
|
||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
|
import { FIELD_NOT_OVERWRITTEN_AT_DRAFT } from '@/object-record/constants/FieldsNotOverwrittenAtDraft';
|
||||||
import { recordFieldInputDraftValueComponentSelector } from '@/object-record/record-field/states/selectors/recordFieldInputDraftValueComponentSelector';
|
import { recordFieldInputDraftValueComponentSelector } from '@/object-record/record-field/states/selectors/recordFieldInputDraftValueComponentSelector';
|
||||||
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
|
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
|
||||||
import { FieldInputDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
|
import { FieldInputDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
|
||||||
@ -37,7 +38,10 @@ export const useInitDraftValueV2 = <FieldValue>() => {
|
|||||||
)
|
)
|
||||||
.getValue();
|
.getValue();
|
||||||
|
|
||||||
if (isUndefined(value)) {
|
if (
|
||||||
|
isUndefined(value) ||
|
||||||
|
FIELD_NOT_OVERWRITTEN_AT_DRAFT.includes(fieldDefinition.type)
|
||||||
|
) {
|
||||||
set(
|
set(
|
||||||
getDraftValueSelector(),
|
getDraftValueSelector(),
|
||||||
computeDraftValueFromFieldValue<FieldValue>({
|
computeDraftValueFromFieldValue<FieldValue>({
|
||||||
@ -48,7 +52,10 @@ export const useInitDraftValueV2 = <FieldValue>() => {
|
|||||||
} else {
|
} else {
|
||||||
set(
|
set(
|
||||||
getDraftValueSelector(),
|
getDraftValueSelector(),
|
||||||
computeDraftValueFromString<FieldValue>({ value, fieldDefinition }),
|
computeDraftValueFromString<FieldValue>({
|
||||||
|
value,
|
||||||
|
fieldDefinition,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,13 +1,7 @@
|
|||||||
import { useContext } from 'react';
|
import { useSetRecoilState } from 'recoil';
|
||||||
import { isUndefined } from '@sniptt/guards';
|
|
||||||
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
|
||||||
|
|
||||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
|
||||||
import { useRecordFieldInputStates } from '@/object-record/record-field/hooks/internal/useRecordFieldInputStates';
|
import { useRecordFieldInputStates } from '@/object-record/record-field/hooks/internal/useRecordFieldInputStates';
|
||||||
import { FieldInputDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
|
import { FieldInputDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
|
||||||
import { computeDraftValueFromFieldValue } from '@/object-record/record-field/utils/computeDraftValueFromFieldValue';
|
|
||||||
import { computeDraftValueFromString } from '@/object-record/record-field/utils/computeDraftValueFromString';
|
|
||||||
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
|
|
||||||
|
|
||||||
export const useRecordFieldInput = <FieldValue>(
|
export const useRecordFieldInput = <FieldValue>(
|
||||||
recordFieldInputId?: string,
|
recordFieldInputId?: string,
|
||||||
@ -15,40 +9,8 @@ export const useRecordFieldInput = <FieldValue>(
|
|||||||
const { scopeId, getDraftValueSelector } =
|
const { scopeId, getDraftValueSelector } =
|
||||||
useRecordFieldInputStates<FieldValue>(recordFieldInputId);
|
useRecordFieldInputStates<FieldValue>(recordFieldInputId);
|
||||||
|
|
||||||
const { entityId, fieldDefinition } = useContext(FieldContext);
|
|
||||||
|
|
||||||
const setDraftValue = useSetRecoilState(getDraftValueSelector());
|
const setDraftValue = useSetRecoilState(getDraftValueSelector());
|
||||||
|
|
||||||
const initDraftValue = useRecoilCallback(
|
|
||||||
({ set, snapshot }) =>
|
|
||||||
(value?: string) => {
|
|
||||||
const recordFieldValue = snapshot
|
|
||||||
.getLoadable(
|
|
||||||
recordStoreFamilySelector<FieldValue>({
|
|
||||||
recordId: entityId,
|
|
||||||
fieldName: fieldDefinition.metadata.fieldName,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
if (isUndefined(value)) {
|
|
||||||
set(
|
|
||||||
getDraftValueSelector(),
|
|
||||||
computeDraftValueFromFieldValue<FieldValue>({
|
|
||||||
fieldValue: recordFieldValue,
|
|
||||||
fieldDefinition,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
set(
|
|
||||||
getDraftValueSelector(),
|
|
||||||
computeDraftValueFromString<FieldValue>({ value, fieldDefinition }),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[entityId, fieldDefinition, getDraftValueSelector],
|
|
||||||
);
|
|
||||||
|
|
||||||
const isDraftValueEmpty = (
|
const isDraftValueEmpty = (
|
||||||
value: FieldInputDraftValue<FieldValue> | undefined,
|
value: FieldInputDraftValue<FieldValue> | undefined,
|
||||||
) => {
|
) => {
|
||||||
@ -67,7 +29,6 @@ export const useRecordFieldInput = <FieldValue>(
|
|||||||
scopeId,
|
scopeId,
|
||||||
setDraftValue,
|
setDraftValue,
|
||||||
getDraftValueSelector,
|
getDraftValueSelector,
|
||||||
initDraftValue,
|
|
||||||
isDraftValueEmpty,
|
isDraftValueEmpty,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,12 +2,15 @@ import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode';
|
|||||||
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
|
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
|
||||||
import { FieldInputDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
|
import { FieldInputDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
|
||||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||||
|
import { isFieldAddress } from '@/object-record/record-field/types/guards/isFieldAddress';
|
||||||
import { isFieldCurrency } from '@/object-record/record-field/types/guards/isFieldCurrency';
|
import { isFieldCurrency } from '@/object-record/record-field/types/guards/isFieldCurrency';
|
||||||
import { isFieldDateTime } from '@/object-record/record-field/types/guards/isFieldDateTime';
|
import { isFieldDateTime } from '@/object-record/record-field/types/guards/isFieldDateTime';
|
||||||
import { isFieldEmail } from '@/object-record/record-field/types/guards/isFieldEmail';
|
import { isFieldEmail } from '@/object-record/record-field/types/guards/isFieldEmail';
|
||||||
import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName';
|
import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName';
|
||||||
import { isFieldLink } from '@/object-record/record-field/types/guards/isFieldLink';
|
import { isFieldLink } from '@/object-record/record-field/types/guards/isFieldLink';
|
||||||
|
import { isFieldLinks } from '@/object-record/record-field/types/guards/isFieldLinks';
|
||||||
import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
|
import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
|
||||||
|
import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation';
|
||||||
import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText';
|
import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText';
|
||||||
import { isFieldUuid } from '@/object-record/record-field/types/guards/isFieldUuid';
|
import { isFieldUuid } from '@/object-record/record-field/types/guards/isFieldUuid';
|
||||||
|
|
||||||
@ -19,18 +22,20 @@ type computeDraftValueFromStringParams = {
|
|||||||
export const computeDraftValueFromString = <FieldValue>({
|
export const computeDraftValueFromString = <FieldValue>({
|
||||||
fieldDefinition,
|
fieldDefinition,
|
||||||
value,
|
value,
|
||||||
}: computeDraftValueFromStringParams): FieldInputDraftValue<FieldValue> => {
|
}: computeDraftValueFromStringParams):
|
||||||
|
| FieldInputDraftValue<FieldValue>
|
||||||
|
| undefined => {
|
||||||
// Todo: improve typing
|
// Todo: improve typing
|
||||||
if (
|
if (
|
||||||
isFieldUuid(fieldDefinition) ||
|
isFieldUuid(fieldDefinition) ||
|
||||||
isFieldText(fieldDefinition) ||
|
isFieldText(fieldDefinition) ||
|
||||||
isFieldDateTime(fieldDefinition) ||
|
isFieldDateTime(fieldDefinition) ||
|
||||||
isFieldNumber(fieldDefinition) ||
|
isFieldNumber(fieldDefinition) ||
|
||||||
isFieldEmail(fieldDefinition)
|
isFieldEmail(fieldDefinition) ||
|
||||||
|
isFieldRelation(fieldDefinition)
|
||||||
) {
|
) {
|
||||||
return value as FieldInputDraftValue<FieldValue>;
|
return value as FieldInputDraftValue<FieldValue>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFieldLink(fieldDefinition)) {
|
if (isFieldLink(fieldDefinition)) {
|
||||||
return { url: value, label: value } as FieldInputDraftValue<FieldValue>;
|
return { url: value, label: value } as FieldInputDraftValue<FieldValue>;
|
||||||
}
|
}
|
||||||
@ -49,5 +54,17 @@ export const computeDraftValueFromString = <FieldValue>({
|
|||||||
} as FieldInputDraftValue<FieldValue>;
|
} as FieldInputDraftValue<FieldValue>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isFieldAddress(fieldDefinition)) {
|
||||||
|
return {
|
||||||
|
addressStreet1: value,
|
||||||
|
} as FieldInputDraftValue<FieldValue>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFieldLinks(fieldDefinition)) {
|
||||||
|
return {
|
||||||
|
primaryLinkUrl: value,
|
||||||
|
} as FieldInputDraftValue<FieldValue>;
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error(`Record field type not supported : ${fieldDefinition.type}}`);
|
throw new Error(`Record field type not supported : ${fieldDefinition.type}}`);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,11 +2,12 @@ import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode';
|
|||||||
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
|
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
|
||||||
import { FieldInputDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
|
import { FieldInputDraftValue } from '@/object-record/record-field/types/FieldInputDraftValue';
|
||||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||||
|
import { isFieldAddress } from '@/object-record/record-field/types/guards/isFieldAddress';
|
||||||
import { isFieldCurrency } from '@/object-record/record-field/types/guards/isFieldCurrency';
|
import { isFieldCurrency } from '@/object-record/record-field/types/guards/isFieldCurrency';
|
||||||
import { isFieldDateTime } from '@/object-record/record-field/types/guards/isFieldDateTime';
|
import { isFieldDateTime } from '@/object-record/record-field/types/guards/isFieldDateTime';
|
||||||
import { isFieldEmail } from '@/object-record/record-field/types/guards/isFieldEmail';
|
import { isFieldEmail } from '@/object-record/record-field/types/guards/isFieldEmail';
|
||||||
import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName';
|
import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName';
|
||||||
import { isFieldLink } from '@/object-record/record-field/types/guards/isFieldLink';
|
import { isFieldLinks } from '@/object-record/record-field/types/guards/isFieldLinks';
|
||||||
import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
|
import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
|
||||||
import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson';
|
import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson';
|
||||||
import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation';
|
import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation';
|
||||||
@ -33,8 +34,22 @@ export const computeEmptyDraftValue = <FieldValue>({
|
|||||||
return '' as FieldInputDraftValue<FieldValue>;
|
return '' as FieldInputDraftValue<FieldValue>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFieldLink(fieldDefinition)) {
|
if (isFieldLinks(fieldDefinition)) {
|
||||||
return { url: '', label: '' } as FieldInputDraftValue<FieldValue>;
|
return {
|
||||||
|
primaryLinkUrl: '',
|
||||||
|
primaryLinkLabel: '',
|
||||||
|
} as FieldInputDraftValue<FieldValue>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFieldAddress(fieldDefinition)) {
|
||||||
|
return {
|
||||||
|
addressStreet1: '',
|
||||||
|
addressStreet2: '',
|
||||||
|
addressCity: '',
|
||||||
|
addressState: '',
|
||||||
|
addressCountry: '',
|
||||||
|
addressPostcode: '',
|
||||||
|
} as FieldInputDraftValue<FieldValue>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFieldCurrency(fieldDefinition)) {
|
if (isFieldCurrency(fieldDefinition)) {
|
||||||
|
|||||||
@ -2,11 +2,11 @@ import { useContext } from 'react';
|
|||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||||
import { useRecordFieldInput } from '@/object-record/record-field/hooks/useRecordFieldInput';
|
|
||||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
|
import { useInitDraftValueV2 } from '@/object-record/record-field/hooks/useInitDraftValueV2';
|
||||||
import { isInlineCellInEditModeScopedState } from '../states/isInlineCellInEditModeScopedState';
|
import { isInlineCellInEditModeScopedState } from '../states/isInlineCellInEditModeScopedState';
|
||||||
import { InlineCellHotkeyScope } from '../types/InlineCellHotkeyScope';
|
import { InlineCellHotkeyScope } from '../types/InlineCellHotkeyScope';
|
||||||
|
|
||||||
@ -26,9 +26,7 @@ export const useInlineCell = () => {
|
|||||||
goBackToPreviousHotkeyScope,
|
goBackToPreviousHotkeyScope,
|
||||||
} = usePreviousHotkeyScope();
|
} = usePreviousHotkeyScope();
|
||||||
|
|
||||||
const { initDraftValue: initFieldInputDraftValue } = useRecordFieldInput(
|
const initFieldInputDraftValue = useInitDraftValueV2();
|
||||||
`${entityId}-${fieldDefinition?.metadata?.fieldName}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
const closeInlineCell = () => {
|
const closeInlineCell = () => {
|
||||||
setIsInlineCellInEditMode(false);
|
setIsInlineCellInEditMode(false);
|
||||||
@ -38,7 +36,7 @@ export const useInlineCell = () => {
|
|||||||
|
|
||||||
const openInlineCell = (customEditHotkeyScopeForField?: HotkeyScope) => {
|
const openInlineCell = (customEditHotkeyScopeForField?: HotkeyScope) => {
|
||||||
setIsInlineCellInEditMode(true);
|
setIsInlineCellInEditMode(true);
|
||||||
initFieldInputDraftValue();
|
initFieldInputDraftValue({ entityId, fieldDefinition });
|
||||||
|
|
||||||
if (isDefined(customEditHotkeyScopeForField)) {
|
if (isDefined(customEditHotkeyScopeForField)) {
|
||||||
setHotkeyScopeAndMemorizePreviousScope(
|
setHotkeyScopeAndMemorizePreviousScope(
|
||||||
|
|||||||
@ -1,76 +0,0 @@
|
|||||||
import { MemoryRouter } from 'react-router-dom';
|
|
||||||
import { act, renderHook, waitFor } from '@testing-library/react';
|
|
||||||
import { RecoilRoot } from 'recoil';
|
|
||||||
|
|
||||||
import { textfieldDefinition } from '@/object-record/record-field/__mocks__/fieldDefinitions';
|
|
||||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
|
||||||
import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
|
|
||||||
import { RecordTableRowContext } from '@/object-record/record-table/contexts/RecordTableRowContext';
|
|
||||||
import {
|
|
||||||
recordTableCell,
|
|
||||||
recordTableRow,
|
|
||||||
} from '@/object-record/record-table/record-table-cell/hooks/__mocks__/cell';
|
|
||||||
import { useOpenRecordTableCell } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCell';
|
|
||||||
import { RecordTableScope } from '@/object-record/record-table/scopes/RecordTableScope';
|
|
||||||
import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope';
|
|
||||||
import { useDragSelect } from '@/ui/utilities/drag-select/hooks/useDragSelect';
|
|
||||||
|
|
||||||
const setHotkeyScope = jest.fn();
|
|
||||||
|
|
||||||
jest.mock('@/ui/utilities/hotkey/hooks/useSetHotkeyScope', () => ({
|
|
||||||
useSetHotkeyScope: () => setHotkeyScope,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const onColumnsChange = jest.fn();
|
|
||||||
const scopeId = 'scopeId';
|
|
||||||
|
|
||||||
const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
|
||||||
<RecoilRoot>
|
|
||||||
<RecordTableScope
|
|
||||||
recordTableScopeId={scopeId}
|
|
||||||
onColumnsChange={onColumnsChange}
|
|
||||||
>
|
|
||||||
<FieldContext.Provider
|
|
||||||
value={{
|
|
||||||
fieldDefinition: textfieldDefinition,
|
|
||||||
entityId: 'entityId',
|
|
||||||
hotkeyScope: TableHotkeyScope.Table,
|
|
||||||
isLabelIdentifier: false,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<RecordTableRowContext.Provider value={recordTableRow}>
|
|
||||||
<RecordTableCellContext.Provider value={recordTableCell}>
|
|
||||||
<MemoryRouter initialEntries={['/one', '/two']} initialIndex={1}>
|
|
||||||
{children}
|
|
||||||
</MemoryRouter>
|
|
||||||
</RecordTableCellContext.Provider>
|
|
||||||
</RecordTableRowContext.Provider>
|
|
||||||
</FieldContext.Provider>
|
|
||||||
</RecordTableScope>
|
|
||||||
</RecoilRoot>
|
|
||||||
);
|
|
||||||
|
|
||||||
describe('useOpenRecordTableCell', () => {
|
|
||||||
it('should work as expected', async () => {
|
|
||||||
const { result } = renderHook(
|
|
||||||
() => {
|
|
||||||
return { ...useOpenRecordTableCell(), ...useDragSelect() };
|
|
||||||
},
|
|
||||||
{
|
|
||||||
wrapper: Wrapper,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result.current.isDragSelectionStartEnabled()).toBe(true);
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
result.current.openTableCell();
|
|
||||||
});
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(result.current.isDragSelectionStartEnabled()).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(setHotkeyScope).toHaveBeenCalledWith('cell-edit-mode', undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
import { useContext } from 'react';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import { useRecoilCallback } from 'recoil';
|
|
||||||
|
|
||||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
|
||||||
import { useIsFieldEmpty } from '@/object-record/record-field/hooks/useIsFieldEmpty';
|
|
||||||
import { useRecordFieldInput } from '@/object-record/record-field/hooks/useRecordFieldInput';
|
|
||||||
import { SOFT_FOCUS_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/SoftFocusClickOutsideListenerId';
|
|
||||||
import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
|
|
||||||
import { RecordTableRowContext } from '@/object-record/record-table/contexts/RecordTableRowContext';
|
|
||||||
import { useLeaveTableFocus } from '@/object-record/record-table/hooks/internal/useLeaveTableFocus';
|
|
||||||
import { useDragSelect } from '@/ui/utilities/drag-select/hooks/useDragSelect';
|
|
||||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
|
||||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
|
||||||
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
|
|
||||||
import { isDefined } from '~/utils/isDefined';
|
|
||||||
|
|
||||||
import { CellHotkeyScopeContext } from '../../contexts/CellHotkeyScopeContext';
|
|
||||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
|
||||||
|
|
||||||
import { useCurrentTableCellEditMode } from './useCurrentTableCellEditMode';
|
|
||||||
|
|
||||||
export const DEFAULT_CELL_SCOPE: HotkeyScope = {
|
|
||||||
scope: TableHotkeyScope.CellEditMode,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useOpenRecordTableCell = () => {
|
|
||||||
const { pathToShowPage, isReadOnly } = useContext(RecordTableRowContext);
|
|
||||||
|
|
||||||
const { setCurrentTableCellInEditMode } = useCurrentTableCellEditMode();
|
|
||||||
const setHotkeyScope = useSetHotkeyScope();
|
|
||||||
const { setDragSelectionStartEnabled } = useDragSelect();
|
|
||||||
|
|
||||||
const customCellHotkeyScope = useContext(CellHotkeyScopeContext);
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const leaveTableFocus = useLeaveTableFocus();
|
|
||||||
const { toggleClickOutsideListener } = useClickOutsideListener(
|
|
||||||
SOFT_FOCUS_CLICK_OUTSIDE_LISTENER_ID,
|
|
||||||
);
|
|
||||||
|
|
||||||
const { columnIndex } = useContext(RecordTableCellContext);
|
|
||||||
const isFirstColumnCell = columnIndex === 0;
|
|
||||||
const isEmpty = useIsFieldEmpty();
|
|
||||||
|
|
||||||
const { entityId, fieldDefinition } = useContext(FieldContext);
|
|
||||||
|
|
||||||
const { initDraftValue: initFieldInputDraftValue } = useRecordFieldInput(
|
|
||||||
`${entityId}-${fieldDefinition?.metadata?.fieldName}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
const openTableCell = useRecoilCallback(
|
|
||||||
() => (options?: { initialValue?: string }) => {
|
|
||||||
if (isReadOnly) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isFirstColumnCell && !isEmpty) {
|
|
||||||
leaveTableFocus();
|
|
||||||
navigate(pathToShowPage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setDragSelectionStartEnabled(false);
|
|
||||||
setCurrentTableCellInEditMode();
|
|
||||||
|
|
||||||
initFieldInputDraftValue(options?.initialValue);
|
|
||||||
toggleClickOutsideListener(false);
|
|
||||||
|
|
||||||
if (isDefined(customCellHotkeyScope)) {
|
|
||||||
setHotkeyScope(
|
|
||||||
customCellHotkeyScope.scope,
|
|
||||||
customCellHotkeyScope.customScopes,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
setHotkeyScope(
|
|
||||||
DEFAULT_CELL_SCOPE.scope,
|
|
||||||
DEFAULT_CELL_SCOPE.customScopes,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[
|
|
||||||
isReadOnly,
|
|
||||||
isFirstColumnCell,
|
|
||||||
isEmpty,
|
|
||||||
setDragSelectionStartEnabled,
|
|
||||||
setCurrentTableCellInEditMode,
|
|
||||||
initFieldInputDraftValue,
|
|
||||||
toggleClickOutsideListener,
|
|
||||||
customCellHotkeyScope,
|
|
||||||
leaveTableFocus,
|
|
||||||
navigate,
|
|
||||||
pathToShowPage,
|
|
||||||
setHotkeyScope,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
openTableCell,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -5,7 +5,7 @@ import { v4 } from 'uuid';
|
|||||||
import { RecordIndexContainer } from '@/object-record/record-index/components/RecordIndexContainer';
|
import { RecordIndexContainer } from '@/object-record/record-index/components/RecordIndexContainer';
|
||||||
import { RecordIndexPageHeader } from '@/object-record/record-index/components/RecordIndexPageHeader';
|
import { RecordIndexPageHeader } from '@/object-record/record-index/components/RecordIndexPageHeader';
|
||||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||||
import { DEFAULT_CELL_SCOPE } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCell';
|
import { DEFAULT_CELL_SCOPE } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2';
|
||||||
import { useSelectedTableCellEditMode } from '@/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode';
|
import { useSelectedTableCellEditMode } from '@/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode';
|
||||||
import { PageBody } from '@/ui/layout/page/PageBody';
|
import { PageBody } from '@/ui/layout/page/PageBody';
|
||||||
import { PageContainer } from '@/ui/layout/page/PageContainer';
|
import { PageContainer } from '@/ui/layout/page/PageContainer';
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ModuleRef } from '@nestjs/core';
|
import { ModuleRef } from '@nestjs/core';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { DataSeedDemoWorkspaceModule } from 'src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module';
|
import { DataSeedDemoWorkspaceModule } from 'src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module';
|
||||||
import { DataSeedDemoWorkspaceJob } from 'src/database/commands/data-seed-demo-workspace/jobs/data-seed-demo-workspace.job';
|
import { DataSeedDemoWorkspaceJob } from 'src/database/commands/data-seed-demo-workspace/jobs/data-seed-demo-workspace.job';
|
||||||
@ -11,6 +12,7 @@ import { StripeModule } from 'src/engine/core-modules/billing/stripe/stripe.modu
|
|||||||
import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user-workspace.module';
|
import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user-workspace.module';
|
||||||
import { UserModule } from 'src/engine/core-modules/user/user.module';
|
import { UserModule } from 'src/engine/core-modules/user/user.module';
|
||||||
import { HandleWorkspaceMemberDeletedJob } from 'src/engine/core-modules/workspace/handle-workspace-member-deleted.job';
|
import { HandleWorkspaceMemberDeletedJob } from 'src/engine/core-modules/workspace/handle-workspace-member-deleted.job';
|
||||||
|
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module';
|
import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module';
|
||||||
import { EmailSenderJob } from 'src/engine/integrations/email/email-sender.job';
|
import { EmailSenderJob } from 'src/engine/integrations/email/email-sender.job';
|
||||||
import { EmailModule } from 'src/engine/integrations/email/email.module';
|
import { EmailModule } from 'src/engine/integrations/email/email.module';
|
||||||
@ -27,6 +29,7 @@ import { WorkflowModule } from 'src/modules/workflow/workflow.module';
|
|||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([Workspace], 'core'),
|
||||||
DataSourceModule,
|
DataSourceModule,
|
||||||
ObjectMetadataModule,
|
ObjectMetadataModule,
|
||||||
TypeORMModule,
|
TypeORMModule,
|
||||||
|
|||||||
Reference in New Issue
Block a user