Fix Date/DateTime/Relation field forms (#19463)
https://discord.com/channels/1130383047699738754/1486025695481168102 On Date and DateTime, picker doesn't open when clicking. On Relation, No record option can't be selected. Introduce the "null", to break relation.
This commit is contained in:
+64
-47
@@ -18,8 +18,14 @@ import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotke
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
|
||||
import { isStandaloneVariableString } from '@/workflow/utils/isStandaloneVariableString';
|
||||
import {
|
||||
FloatingPortal,
|
||||
autoUpdate,
|
||||
flip,
|
||||
offset,
|
||||
useFloating,
|
||||
} from '@floating-ui/react';
|
||||
import { styled } from '@linaria/react';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useId, useRef, useState } from 'react';
|
||||
import { Temporal } from 'temporal-polyfill';
|
||||
import { Key } from 'ts-key-enum';
|
||||
@@ -27,10 +33,8 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { type Nullable } from 'twenty-ui/utilities';
|
||||
|
||||
const StyledDateInputAbsoluteContainer = styled.div`
|
||||
position: absolute;
|
||||
top: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
const FORM_DATE_FIELD_PICKER_CLICK_OUTSIDE_ID =
|
||||
'form-date-field-picker-floating';
|
||||
|
||||
const StyledDateInputTextContainer = styled.div<{ isReadonly?: boolean }>`
|
||||
align-items: center;
|
||||
@@ -49,9 +53,10 @@ const StyledDateInputTextContainer = styled.div<{ isReadonly?: boolean }>`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledDateInputContainer = styled.div`
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
const StyledDatePickerInputWrapper = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
`;
|
||||
|
||||
type DraftValue =
|
||||
@@ -98,6 +103,16 @@ export const FormDateFieldInput = ({
|
||||
|
||||
const datePickerWrapperRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const displayDatePicker =
|
||||
draftValue.type === 'static' && draftValue.mode === 'edit';
|
||||
|
||||
const { refs, floatingStyles } = useFloating({
|
||||
open: displayDatePicker,
|
||||
placement: 'bottom-start',
|
||||
middleware: [offset(4), flip()],
|
||||
whileElementsMounted: autoUpdate,
|
||||
});
|
||||
|
||||
const persistDate = (newDate: Nullable<string>) => {
|
||||
if (!isDefined(newDate)) {
|
||||
onChange(null);
|
||||
@@ -109,9 +124,6 @@ export const FormDateFieldInput = ({
|
||||
const { closeDropdown: closeDropdownMonthSelect } = useCloseDropdown();
|
||||
const { closeDropdown: closeDropdownYearSelect } = useCloseDropdown();
|
||||
|
||||
const displayDatePicker =
|
||||
draftValue.type === 'static' && draftValue.mode === 'edit';
|
||||
|
||||
useListenClickOutside({
|
||||
refs: [datePickerWrapperRef],
|
||||
listenerId: 'FormDateFieldInputBase',
|
||||
@@ -124,6 +136,7 @@ export const FormDateFieldInput = ({
|
||||
},
|
||||
enabled: displayDatePicker,
|
||||
excludedClickOutsideIds: [
|
||||
FORM_DATE_FIELD_PICKER_CLICK_OUTSIDE_ID,
|
||||
MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID,
|
||||
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
|
||||
],
|
||||
@@ -235,9 +248,7 @@ export const FormDateFieldInput = ({
|
||||
: Temporal.PlainDate.from(defaultValue).toString();
|
||||
|
||||
const plainDateValue =
|
||||
draftValue.type === 'static' && isNonEmptyString(draftValue.value)
|
||||
? draftValue.value
|
||||
: plainDateValueFromProps;
|
||||
draftValue.type === 'static' ? draftValue.value : plainDateValueFromProps;
|
||||
|
||||
const handleMaskedDatePointerDownCapture = () => {
|
||||
if (readonly) {
|
||||
@@ -256,13 +267,13 @@ export const FormDateFieldInput = ({
|
||||
{label ? <InputLabel>{label}</InputLabel> : null}
|
||||
|
||||
<FormFieldInputRowContainer>
|
||||
<FormFieldInputInnerContainer
|
||||
ref={datePickerWrapperRef}
|
||||
formFieldInputInstanceId={instanceId}
|
||||
hasRightElement={isDefined(VariablePicker) && !readonly}
|
||||
>
|
||||
{draftValue.type === 'static' ? (
|
||||
<>
|
||||
<StyledDatePickerInputWrapper ref={datePickerWrapperRef}>
|
||||
<FormFieldInputInnerContainer
|
||||
ref={refs.setReference}
|
||||
formFieldInputInstanceId={instanceId}
|
||||
hasRightElement={isDefined(VariablePicker) && !readonly}
|
||||
>
|
||||
{draftValue.type === 'static' ? (
|
||||
<StyledDateInputTextContainer
|
||||
isReadonly={readonly === true}
|
||||
onPointerDownCapture={handleMaskedDatePointerDownCapture}
|
||||
@@ -273,32 +284,38 @@ export const FormDateFieldInput = ({
|
||||
readonly={readonly}
|
||||
/>
|
||||
</StyledDateInputTextContainer>
|
||||
{draftValue.mode === 'edit' && !readonly ? (
|
||||
<StyledDateInputContainer>
|
||||
<StyledDateInputAbsoluteContainer>
|
||||
<OverlayContainer>
|
||||
<DatePicker
|
||||
instanceId={instanceId}
|
||||
plainDateString={plainDateValue}
|
||||
onChange={handlePickerChange}
|
||||
onClose={handlePickerMouseSelect}
|
||||
onEnter={handlePickerEnter}
|
||||
onEscape={handlePickerEscape}
|
||||
onClear={handlePickerClear}
|
||||
hideHeaderInput
|
||||
/>
|
||||
</OverlayContainer>
|
||||
</StyledDateInputAbsoluteContainer>
|
||||
</StyledDateInputContainer>
|
||||
) : null}
|
||||
</>
|
||||
) : (
|
||||
<VariableChipStandalone
|
||||
rawVariableName={draftValue.value}
|
||||
onRemove={readonly ? undefined : handleUnlinkVariable}
|
||||
/>
|
||||
)}
|
||||
</FormFieldInputInnerContainer>
|
||||
) : (
|
||||
<VariableChipStandalone
|
||||
rawVariableName={draftValue.value}
|
||||
onRemove={readonly ? undefined : handleUnlinkVariable}
|
||||
/>
|
||||
)}
|
||||
</FormFieldInputInnerContainer>
|
||||
</StyledDatePickerInputWrapper>
|
||||
{draftValue.type === 'static' &&
|
||||
draftValue.mode === 'edit' &&
|
||||
!readonly ? (
|
||||
<FloatingPortal>
|
||||
<div
|
||||
ref={refs.setFloating}
|
||||
style={floatingStyles}
|
||||
data-click-outside-id={FORM_DATE_FIELD_PICKER_CLICK_OUTSIDE_ID}
|
||||
>
|
||||
<OverlayContainer>
|
||||
<DatePicker
|
||||
instanceId={instanceId}
|
||||
plainDateString={plainDateValue}
|
||||
onChange={handlePickerChange}
|
||||
onClose={handlePickerMouseSelect}
|
||||
onEnter={handlePickerEnter}
|
||||
onEscape={handlePickerEscape}
|
||||
onClear={handlePickerClear}
|
||||
hideHeaderInput
|
||||
/>
|
||||
</OverlayContainer>
|
||||
</div>
|
||||
</FloatingPortal>
|
||||
) : null}
|
||||
{VariablePicker && !readonly ? (
|
||||
<VariablePicker
|
||||
instanceId={instanceId}
|
||||
|
||||
+76
-49
@@ -18,27 +18,37 @@ import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotke
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
|
||||
import { isStandaloneVariableString } from '@/workflow/utils/isStandaloneVariableString';
|
||||
import {
|
||||
FloatingPortal,
|
||||
autoUpdate,
|
||||
flip,
|
||||
offset,
|
||||
useFloating,
|
||||
} from '@floating-ui/react';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useId, useRef, useState } from 'react';
|
||||
import { Temporal } from 'temporal-polyfill';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { type Nullable } from 'twenty-ui/utilities';
|
||||
|
||||
const StyledDateInputAbsoluteContainer = styled.div`
|
||||
position: absolute;
|
||||
top: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
const FORM_DATE_TIME_FIELD_PICKER_CLICK_OUTSIDE_ID =
|
||||
'form-date-time-field-picker-floating';
|
||||
|
||||
const StyledDateInputTextContainer = styled.div`
|
||||
const StyledDateInputTextContainer = styled.div<{ isReadonly?: boolean }>`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
pointer-events: ${({ isReadonly }) => (isReadonly ? 'none' : 'auto')};
|
||||
user-select: ${({ isReadonly }) => (isReadonly ? 'none' : 'auto')};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledDateInputContainer = styled.div`
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
const StyledDatePickerInputWrapper = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
`;
|
||||
|
||||
type DraftValue =
|
||||
@@ -87,6 +97,16 @@ export const FormDateTimeFieldInput = ({
|
||||
|
||||
const datePickerWrapperRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const displayDatePicker =
|
||||
draftValue.type === 'static' && draftValue.mode === 'edit';
|
||||
|
||||
const { refs, floatingStyles } = useFloating({
|
||||
open: displayDatePicker,
|
||||
placement: 'bottom-start',
|
||||
middleware: [offset(4), flip()],
|
||||
whileElementsMounted: autoUpdate,
|
||||
});
|
||||
|
||||
const persistDate = (newDate: Nullable<Temporal.ZonedDateTime>) => {
|
||||
if (!isDefined(newDate)) {
|
||||
onChange(null);
|
||||
@@ -100,9 +120,6 @@ export const FormDateTimeFieldInput = ({
|
||||
const { closeDropdown: closeDropdownMonthSelect } = useCloseDropdown();
|
||||
const { closeDropdown: closeDropdownYearSelect } = useCloseDropdown();
|
||||
|
||||
const displayDatePicker =
|
||||
draftValue.type === 'static' && draftValue.mode === 'edit';
|
||||
|
||||
useListenClickOutside({
|
||||
refs: [datePickerWrapperRef],
|
||||
listenerId: 'FormDateTimeFieldInputBase',
|
||||
@@ -115,6 +132,7 @@ export const FormDateTimeFieldInput = ({
|
||||
},
|
||||
enabled: displayDatePicker,
|
||||
excludedClickOutsideIds: [
|
||||
FORM_DATE_TIME_FIELD_PICKER_CLICK_OUTSIDE_ID,
|
||||
MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID,
|
||||
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
|
||||
],
|
||||
@@ -170,7 +188,7 @@ export const FormDateTimeFieldInput = ({
|
||||
persistDate(newDate);
|
||||
};
|
||||
|
||||
const handleInputFocus = () => {
|
||||
const handleOpenPicker = () => {
|
||||
setDraftValue({
|
||||
type: 'static',
|
||||
mode: 'edit',
|
||||
@@ -241,49 +259,58 @@ export const FormDateTimeFieldInput = ({
|
||||
{label ? <InputLabel>{label}</InputLabel> : null}
|
||||
|
||||
<FormFieldInputRowContainer>
|
||||
<FormFieldInputInnerContainer
|
||||
ref={datePickerWrapperRef}
|
||||
formFieldInputInstanceId={instanceId}
|
||||
hasRightElement={isDefined(VariablePicker) && !readonly}
|
||||
>
|
||||
{draftValue.type === 'static' ? (
|
||||
<>
|
||||
<StyledDateInputTextContainer>
|
||||
<StyledDatePickerInputWrapper ref={datePickerWrapperRef}>
|
||||
<FormFieldInputInnerContainer
|
||||
ref={refs.setReference}
|
||||
formFieldInputInstanceId={instanceId}
|
||||
hasRightElement={isDefined(VariablePicker) && !readonly}
|
||||
>
|
||||
{draftValue.type === 'static' ? (
|
||||
<StyledDateInputTextContainer
|
||||
isReadonly={readonly === true}
|
||||
onPointerDownCapture={handleOpenPicker}
|
||||
>
|
||||
<DateTimePickerInput
|
||||
date={dateValue}
|
||||
onChange={handleInputChange}
|
||||
onFocus={handleInputFocus}
|
||||
onFocus={handleOpenPicker}
|
||||
readonly={readonly}
|
||||
timeZone={timeZone}
|
||||
/>
|
||||
</StyledDateInputTextContainer>
|
||||
{draftValue.mode === 'edit' ? (
|
||||
<StyledDateInputContainer>
|
||||
<StyledDateInputAbsoluteContainer>
|
||||
<OverlayContainer>
|
||||
<DateTimePicker
|
||||
instanceId={instanceId}
|
||||
date={dateValue}
|
||||
onChange={handlePickerChange}
|
||||
onClose={handlePickerMouseSelect}
|
||||
onEnter={handlePickerEnter}
|
||||
onEscape={handlePickerEscape}
|
||||
onClear={handlePickerClear}
|
||||
hideHeaderInput
|
||||
timeZone={timeZone}
|
||||
/>
|
||||
</OverlayContainer>
|
||||
</StyledDateInputAbsoluteContainer>
|
||||
</StyledDateInputContainer>
|
||||
) : null}
|
||||
</>
|
||||
) : (
|
||||
<VariableChipStandalone
|
||||
rawVariableName={draftValue.value}
|
||||
onRemove={readonly ? undefined : handleUnlinkVariable}
|
||||
/>
|
||||
)}
|
||||
</FormFieldInputInnerContainer>
|
||||
) : (
|
||||
<VariableChipStandalone
|
||||
rawVariableName={draftValue.value}
|
||||
onRemove={readonly ? undefined : handleUnlinkVariable}
|
||||
/>
|
||||
)}
|
||||
</FormFieldInputInnerContainer>
|
||||
</StyledDatePickerInputWrapper>
|
||||
{draftValue.type === 'static' && draftValue.mode === 'edit' ? (
|
||||
<FloatingPortal>
|
||||
<div
|
||||
ref={refs.setFloating}
|
||||
style={floatingStyles}
|
||||
data-click-outside-id={
|
||||
FORM_DATE_TIME_FIELD_PICKER_CLICK_OUTSIDE_ID
|
||||
}
|
||||
>
|
||||
<OverlayContainer>
|
||||
<DateTimePicker
|
||||
instanceId={instanceId}
|
||||
date={dateValue}
|
||||
onChange={handlePickerChange}
|
||||
onClose={handlePickerMouseSelect}
|
||||
onEnter={handlePickerEnter}
|
||||
onEscape={handlePickerEscape}
|
||||
onClear={handlePickerClear}
|
||||
hideHeaderInput
|
||||
timeZone={timeZone}
|
||||
/>
|
||||
</OverlayContainer>
|
||||
</div>
|
||||
</FloatingPortal>
|
||||
) : null}
|
||||
{VariablePicker && !readonly ? (
|
||||
<VariablePicker
|
||||
instanceId={instanceId}
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import { type JsonValue } from 'type-fest';
|
||||
export type FormRelationToOneFieldInputProps = {
|
||||
label?: string;
|
||||
objectNameSingular?: string;
|
||||
defaultValue?: FieldRelationValue<FieldRelationToOneValue> | string;
|
||||
defaultValue?: FieldRelationValue<FieldRelationToOneValue> | string | null;
|
||||
onChange: (value: JsonValue) => void;
|
||||
onClear?: () => void;
|
||||
readonly?: boolean;
|
||||
|
||||
+23
-1
@@ -8,8 +8,9 @@ import { VariableChipStandalone } from '@/object-record/record-field/ui/form-typ
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isStandaloneVariableString } from '@/workflow/utils/isStandaloneVariableString';
|
||||
import { styled } from '@linaria/react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IconForbid } from 'twenty-ui/display';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledRecordChipContainer = styled.div`
|
||||
@@ -20,6 +21,14 @@ const StyledPlaceholderContainer = styled.div`
|
||||
margin: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledNoRecordContainer = styled.div`
|
||||
align-items: center;
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
display: flex;
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
margin: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
type FormSingleRecordFieldChipProps = {
|
||||
draftValue:
|
||||
| {
|
||||
@@ -29,6 +38,10 @@ type FormSingleRecordFieldChipProps = {
|
||||
| {
|
||||
type: 'variable';
|
||||
value: Variable;
|
||||
}
|
||||
| {
|
||||
type: 'no-record';
|
||||
value: null;
|
||||
};
|
||||
selectedRecord?: ObjectRecord;
|
||||
objectNameSingular: string;
|
||||
@@ -56,6 +69,15 @@ export const FormSingleRecordFieldChip = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (draftValue.type === 'no-record') {
|
||||
return (
|
||||
<StyledNoRecordContainer>
|
||||
<IconForbid size={12} />
|
||||
{t`No record`}
|
||||
</StyledNoRecordContainer>
|
||||
);
|
||||
}
|
||||
|
||||
if (draftValue.type === 'static' && isDefined(selectedRecord)) {
|
||||
return (
|
||||
<StyledRecordChipContainer>
|
||||
|
||||
+30
-18
@@ -16,7 +16,6 @@ import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSe
|
||||
import { isStandaloneVariableString } from '@/workflow/utils/isStandaloneVariableString';
|
||||
import { styled } from '@linaria/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useCallback, useContext, useId } from 'react';
|
||||
import { CustomError, isDefined, isValidUuid } from 'twenty-shared/utils';
|
||||
import { IconChevronDown, IconForbid } from 'twenty-ui/display';
|
||||
@@ -45,11 +44,15 @@ type FormSingleRecordPickerValue =
|
||||
| {
|
||||
type: 'variable';
|
||||
value: Variable;
|
||||
}
|
||||
| {
|
||||
type: 'no-record';
|
||||
value: null;
|
||||
};
|
||||
|
||||
export type FormSingleRecordPickerProps = {
|
||||
label?: string;
|
||||
defaultValue?: RecordId | Variable;
|
||||
defaultValue?: RecordId | Variable | null;
|
||||
onChange: (value: RecordId | Variable | null) => void;
|
||||
onClear?: () => void;
|
||||
objectNameSingulars: string[];
|
||||
@@ -70,17 +73,12 @@ export const FormSingleRecordPicker = ({
|
||||
}: FormSingleRecordPickerProps) => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const draftValue: FormSingleRecordPickerValue = isStandaloneVariableString(
|
||||
defaultValue,
|
||||
)
|
||||
? {
|
||||
type: 'variable',
|
||||
value: defaultValue,
|
||||
}
|
||||
: {
|
||||
type: 'static',
|
||||
value: (defaultValue as string | undefined) ?? '',
|
||||
};
|
||||
const draftValue: FormSingleRecordPickerValue =
|
||||
defaultValue === null
|
||||
? { type: 'no-record', value: null }
|
||||
: isStandaloneVariableString(defaultValue)
|
||||
? { type: 'variable', value: defaultValue }
|
||||
: { type: 'static', value: (defaultValue as string | undefined) ?? '' };
|
||||
|
||||
if (objectNameSingulars.length === 0) {
|
||||
throw new CustomError(
|
||||
@@ -117,13 +115,22 @@ export const FormSingleRecordPicker = ({
|
||||
const handleMorphItemSelected = (
|
||||
selectedMorphItem: RecordPickerPickableMorphItem | null | undefined,
|
||||
) => {
|
||||
if (!isNonEmptyString(selectedMorphItem?.recordId)) {
|
||||
onClear?.();
|
||||
if (!isDefined(selectedMorphItem) || selectedMorphItem === null) {
|
||||
if (defaultValue === null) {
|
||||
onClear?.();
|
||||
} else {
|
||||
onChange(null);
|
||||
}
|
||||
closeDropdown(dropdownId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
onChange(selectedMorphItem.recordId);
|
||||
if (defaultValue === selectedMorphItem.recordId) {
|
||||
onClear?.();
|
||||
} else {
|
||||
onChange(selectedMorphItem.recordId);
|
||||
}
|
||||
closeDropdown(dropdownId);
|
||||
};
|
||||
|
||||
@@ -142,8 +149,13 @@ export const FormSingleRecordPicker = ({
|
||||
);
|
||||
|
||||
const handleOpenDropdown = () => {
|
||||
if (defaultValue === null) {
|
||||
setSingleRecordPickerSelectedId(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
isDefined(draftValue?.value) &&
|
||||
isDefined(draftValue.value) &&
|
||||
!isStandaloneVariableString(draftValue.value)
|
||||
) {
|
||||
setSingleRecordPickerSelectedId(draftValue.value);
|
||||
@@ -208,7 +220,7 @@ export const FormSingleRecordPicker = ({
|
||||
focusId={dropdownId}
|
||||
componentInstanceId={dropdownId}
|
||||
EmptyIcon={IconForbid}
|
||||
emptyLabel={t`No records`}
|
||||
emptyLabel={t`No record`}
|
||||
onCancel={() => closeDropdown(dropdownId)}
|
||||
onMorphItemSelected={handleMorphItemSelected}
|
||||
objectNameSingulars={objectNameSingulars}
|
||||
|
||||
+4
-1
@@ -65,7 +65,9 @@ export const UpdateMultipleRecordsForm = ({
|
||||
const value = values[fieldNameOrRelationIdName];
|
||||
|
||||
const handleValueChange = (newValue: any) => {
|
||||
if (isUpdateRecordValueEmpty(newValue)) {
|
||||
if (newValue === null) {
|
||||
onChange(fieldNameOrRelationIdName, null);
|
||||
} else if (isUpdateRecordValueEmpty(newValue)) {
|
||||
onChange(fieldNameOrRelationIdName, undefined);
|
||||
} else {
|
||||
onChange(fieldNameOrRelationIdName, newValue);
|
||||
@@ -79,6 +81,7 @@ export const UpdateMultipleRecordsForm = ({
|
||||
field={fieldDefinition}
|
||||
defaultValue={value}
|
||||
onChange={handleValueChange}
|
||||
onClear={() => onChange(fieldNameOrRelationIdName, undefined)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
+6
-2
@@ -100,9 +100,13 @@ export const DatePickerInput = ({
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(date) && internalDate !== date) {
|
||||
if (internalDate !== date) {
|
||||
setInternalDate(date);
|
||||
setValue(parsePlainDateToDateInputString(date));
|
||||
if (isDefined(date)) {
|
||||
setValue(parsePlainDateToDateInputString(date));
|
||||
} else {
|
||||
setValue('');
|
||||
}
|
||||
}
|
||||
}, [date, internalDate, parsePlainDateToDateInputString, setValue]);
|
||||
|
||||
|
||||
+1
@@ -138,6 +138,7 @@ export const DateTimePickerInput = ({
|
||||
setInternalDate(date);
|
||||
|
||||
if (!isDefined(date)) {
|
||||
setValue('');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user