diff --git a/libs/sdk-backend-tiger/src/convertors/fromBackend/ExportDefinitionsConverter.ts b/libs/sdk-backend-tiger/src/convertors/fromBackend/ExportDefinitionsConverter.ts index 61e64670f95..c71462cc1ba 100644 --- a/libs/sdk-backend-tiger/src/convertors/fromBackend/ExportDefinitionsConverter.ts +++ b/libs/sdk-backend-tiger/src/convertors/fromBackend/ExportDefinitionsConverter.ts @@ -20,6 +20,12 @@ import { convertUserIdentifier } from "./UsersConverter.js"; import { cloneWithSanitizedIds } from "./IdSanitization.js"; import isEmpty from "lodash/isEmpty.js"; +type MetadataObjectDefinition = { + widget?: string; + title?: string; + filters?: FilterContextItem[]; +}; + export const convertExportDefinitionMdObject = ( exportDefinitionOut: JsonApiExportDefinitionOutWithLinks, included: JsonApiExportDefinitionOutIncludes[] = [], @@ -72,7 +78,7 @@ export const convertInlineExportDefinitionMdObject = ( id, uri: id, ref: idRef(id, "exportDefinition"), - title: (exportDefinitionOut.requestPayload.metadata as any).title ?? "", + title: (exportDefinitionOut.requestPayload.metadata as MetadataObjectDefinition).title ?? "", description: "", tags: [], requestPayload: request, @@ -86,7 +92,7 @@ const convertExportDefinitionRequestPayload = ( exportRequest: VisualExportRequest | TabularExportRequest, ): IExportDefinitionRequestPayload => { if (isTabularRequest(exportRequest)) { - const { widget } = (exportRequest.metadata as { widget?: string }) ?? {}; + const { widget } = (exportRequest.metadata as MetadataObjectDefinition) ?? {}; const filters = exportRequest.visualizationObjectCustomFilters as IFilter[]; const filtersObj = filters ? { filters: filters.map(cloneWithSanitizedIds) } : {}; @@ -113,7 +119,7 @@ const convertExportDefinitionRequestPayload = ( ...settingsObj, }; } else { - const filters = (exportRequest.metadata as any)?.filters as FilterContextItem[]; + const filters = (exportRequest.metadata as MetadataObjectDefinition)?.filters; const filtersObj = filters ? { filters } : {}; return { diff --git a/libs/sdk-ui-kit/api/sdk-ui-kit.api.md b/libs/sdk-ui-kit/api/sdk-ui-kit.api.md index 4ce6544934f..f2f66ab90dd 100644 --- a/libs/sdk-ui-kit/api/sdk-ui-kit.api.md +++ b/libs/sdk-ui-kit/api/sdk-ui-kit.api.md @@ -4170,7 +4170,7 @@ export interface ITimepickerOwnProps { // (undocumented) skipNormalizeTime?: boolean; // (undocumented) - time: Date; + time: Date | null; // (undocumented) timeAnchor?: number; // (undocumented) @@ -4429,7 +4429,7 @@ export class MultiSelectListItem extends PureComponent; // @internal -export function normalizeTime(time: Date, date?: Date, timeAnchor?: number): Date; +export function normalizeTime(time?: Date, date?: Date, timeAnchor?: number): Date; // @internal (undocumented) export const NumericInput: React_2.FC; diff --git a/libs/sdk-ui-kit/src/Datepicker/Datepicker.tsx b/libs/sdk-ui-kit/src/Datepicker/Datepicker.tsx index a4018786ec4..a0919102edd 100644 --- a/libs/sdk-ui-kit/src/Datepicker/Datepicker.tsx +++ b/libs/sdk-ui-kit/src/Datepicker/Datepicker.tsx @@ -183,7 +183,7 @@ export class WrappedDatePicker extends React.PureComponent nextProps.date || props.date < nextProps.date) { - const selectedDate = this.updateDate(nextProps.date); + const selectedDate = this.updateDate(nextProps.date || new Date()); this.setState({ selectedDate }); this.setState({ monthDate: selectedDate }); this.setState({ inputValue: formatDate(selectedDate, props.dateFormat) }); diff --git a/libs/sdk-ui-kit/src/RecurrenceForm/DateTime.tsx b/libs/sdk-ui-kit/src/RecurrenceForm/DateTime.tsx index 57ecbd61d67..6cdbaad2912 100644 --- a/libs/sdk-ui-kit/src/RecurrenceForm/DateTime.tsx +++ b/libs/sdk-ui-kit/src/RecurrenceForm/DateTime.tsx @@ -8,26 +8,26 @@ import { DEFAULT_DROPDOWN_ZINDEX, MAX_VISIBLE_TIME_ITEMS_COUNT, TIME_ANCHOR } fr interface IDateTimeProps { label: string; - date: Date; + date: Date | null; locale?: string; timezone?: string; weekStart?: WeekStart; dateFormat?: string; timeFormat?: string; - onDateChange: (date: Date) => void; + onDateChange: (date: Date | null, valid: boolean) => void; } export const DateTime: React.FC = (props) => { const { label, date, dateFormat, locale, timezone, onDateChange, weekStart, timeFormat } = props; - const handleDateChange = (selectedDate: Date) => { + const handleDateChange = (selectedDate: Date | null) => { const newDate = normalizeTime(date, selectedDate, TIME_ANCHOR); - onDateChange(newDate); + onDateChange(newDate, !!selectedDate); }; - const handleTimeChange = (selectedTime: Date) => { + const handleTimeChange = (selectedTime: Date | null) => { const newDate = normalizeTime(selectedTime, date, TIME_ANCHOR); - onDateChange(newDate); + onDateChange(newDate, !!selectedTime); }; return ( @@ -40,7 +40,6 @@ export const DateTime: React.FC = (props) => { dateFormat={dateFormat} locale={locale} placeholder={dateFormat} - resetOnInvalidValue={true} onChange={handleDateChange} weekStart={weekStart} /> diff --git a/libs/sdk-ui-kit/src/RecurrenceForm/RecurrenceForm.tsx b/libs/sdk-ui-kit/src/RecurrenceForm/RecurrenceForm.tsx index 9433e04a695..265e7c0721f 100644 --- a/libs/sdk-ui-kit/src/RecurrenceForm/RecurrenceForm.tsx +++ b/libs/sdk-ui-kit/src/RecurrenceForm/RecurrenceForm.tsx @@ -64,10 +64,14 @@ const RecurrenceFormCore: React.FC = (props) => { ); const onDateChange = useCallback( - (date: Date) => { + (date: Date, valid: boolean) => { setDateValue(date); const newExpression = constructCronExpression(date, recurrenceType, cronExpression, weekStart); - onChange(newExpression, date, isCronExpressionValid(newExpression, allowHourlyRecurrence)); + onChange( + newExpression, + date, + valid && isCronExpressionValid(newExpression, allowHourlyRecurrence), + ); }, [cronExpression, onChange, recurrenceType, weekStart, allowHourlyRecurrence], ); diff --git a/libs/sdk-ui-kit/src/Timepicker/Timepicker.tsx b/libs/sdk-ui-kit/src/Timepicker/Timepicker.tsx index 5d8030fe886..b5ba1502231 100644 --- a/libs/sdk-ui-kit/src/Timepicker/Timepicker.tsx +++ b/libs/sdk-ui-kit/src/Timepicker/Timepicker.tsx @@ -23,7 +23,7 @@ export { normalizeTime, formatTime }; * @internal */ export interface ITimepickerOwnProps { - time: Date; + time: Date | null; className?: string; maxVisibleItemsCount?: number; onChange?: (selectedTime: Date) => void; diff --git a/libs/sdk-ui-kit/src/Timepicker/utils/timeUtilities.ts b/libs/sdk-ui-kit/src/Timepicker/utils/timeUtilities.ts index 0cdd12c7313..98e865be9cf 100644 --- a/libs/sdk-ui-kit/src/Timepicker/utils/timeUtilities.ts +++ b/libs/sdk-ui-kit/src/Timepicker/utils/timeUtilities.ts @@ -24,18 +24,18 @@ export function updateTime(h: number, m: number, date?: Date): Date { return selectedTime; } -function getNormalizedHourAndMinute(time: Date, timeAnchor = TIME_ANCHOR) { +function getNormalizedHourAndMinute(time?: Date, timeAnchor = TIME_ANCHOR) { let h: number; let m: number; - const hours = time.getHours(); - const minutes = time.getMinutes(); + const hours = time?.getHours() ?? 0; + const minutes = time?.getMinutes() ?? 0; // Do not shift time if it is exactly on the new hour (0 == 60 when timeAnchor is 60) if (minutes === 0 && timeAnchor === 60) { return { hours, minutes: 0 }; } - if (time.getMinutes() < timeAnchor) { + if (minutes < timeAnchor) { h = hours; m = timeAnchor; } else { @@ -56,7 +56,7 @@ function getNormalizedHourAndMinute(time: Date, timeAnchor = TIME_ANCHOR) { * return 8:00 if time is 7:35 * return 0:00 if time is 23:45 */ -export function normalizeTime(time: Date, date?: Date, timeAnchor = TIME_ANCHOR): Date { +export function normalizeTime(time?: Date, date?: Date, timeAnchor = TIME_ANCHOR): Date { const { hours, minutes } = getNormalizedHourAndMinute(time, timeAnchor); - return updateTime(hours, minutes, date); + return updateTime(hours, minutes, date || time); }