@datarobot/design-system 29.7.5 → 29.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/datetime-range-picker/datetime-range-picker-panel.d.ts +2 -2
- package/cjs/datetime-range-picker/datetime-range-picker-panel.js +3 -1
- package/cjs/datetime-range-picker/datetime-range-picker.d.ts +1 -1
- package/cjs/datetime-range-picker/helpers.d.ts +8 -0
- package/cjs/datetime-range-picker/helpers.js +40 -1
- package/cjs/multiselect-searchable-list/multiselect-searchable-list.js +7 -1
- package/cjs/multiselect-searchable-list/selected-items-board.js +12 -1
- package/cjs/scheduler/index.d.ts +2 -2
- package/cjs/scheduler/index.js +6 -0
- package/cjs/scheduler/utils.d.ts +4 -0
- package/cjs/scheduler/utils.js +87 -0
- package/cjs/scheduler/utils.test.js +149 -0
- package/cjs/zoom-controls/zoom-controls.js +3 -3
- package/esm/datetime-range-picker/datetime-range-picker-panel.d.ts +2 -2
- package/esm/datetime-range-picker/datetime-range-picker-panel.js +4 -2
- package/esm/datetime-range-picker/datetime-range-picker.d.ts +1 -1
- package/esm/datetime-range-picker/helpers.d.ts +8 -0
- package/esm/datetime-range-picker/helpers.js +38 -1
- package/esm/multiselect-searchable-list/multiselect-searchable-list.js +7 -1
- package/esm/multiselect-searchable-list/selected-items-board.js +12 -1
- package/esm/scheduler/index.d.ts +2 -2
- package/esm/scheduler/index.js +2 -2
- package/esm/scheduler/utils.d.ts +4 -0
- package/esm/scheduler/utils.js +87 -1
- package/esm/scheduler/utils.test.js +147 -0
- package/esm/zoom-controls/zoom-controls.js +3 -3
- package/js/139/139.min.js +1 -1
- package/js/244/244.min.js +1 -1
- package/js/633/633.min.js +1 -1
- package/js/784/784.min.js +1 -1
- package/js/86/86.min.js +1 -1
- package/js/bundle/bundle.js +173 -21
- package/js/bundle/bundle.min.js +1 -1
- package/js/bundle/index.d.ts +16 -4
- package/js/src_locales_es_419_translation_json/src_locales_es_419_translation_json.js +1 -1
- package/js/src_locales_fr_translation_json/src_locales_fr_translation_json.js +1 -1
- package/js/src_locales_ja_translation_json/src_locales_ja_translation_json.js +1 -1
- package/js/src_locales_ko_translation_json/src_locales_ko_translation_json.js +1 -1
- package/js/src_locales_pt_BR_translation_json/src_locales_pt_BR_translation_json.js +1 -1
- package/locales/es_419/translation.json +3 -3
- package/locales/fr/translation.json +3 -3
- package/locales/ja/translation.json +3 -3
- package/locales/ko/translation.json +3 -3
- package/locales/pt_BR/translation.json +3 -3
- package/package.json +1 -1
|
@@ -61,10 +61,10 @@ export type DateRangePickerPanelProps = {
|
|
|
61
61
|
timeFormat: string | boolean;
|
|
62
62
|
utcSuffix?: string;
|
|
63
63
|
validateOnClick?: ValidateOnClick;
|
|
64
|
-
validateOnChange
|
|
64
|
+
validateOnChange?: ValidateOnChange;
|
|
65
65
|
dateStartInputAriaLabel: string;
|
|
66
66
|
dateEndInputAriaLabel: string;
|
|
67
67
|
};
|
|
68
68
|
/** Represents the panel used to select two datetimes that make up a range. */
|
|
69
|
-
declare function DateRangePickerPanel({ buttonText, cancelButtonText, dateFormat, defaultEnd, defaultStart, initialDirection, initialViewMode, initialTargetInput, maxEnd, minStart, sameDateError, onSubmit, onDismiss, resetText, timeFormat, utcSuffix, validateOnClick: propValidateOnClick, validateOnChange, dateStartInputAriaLabel, dateEndInputAriaLabel, }: DateRangePickerPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
69
|
+
declare function DateRangePickerPanel({ buttonText, cancelButtonText, dateFormat, defaultEnd, defaultStart, initialDirection, initialViewMode, initialTargetInput, maxEnd, minStart, sameDateError, onSubmit, onDismiss, resetText, timeFormat, utcSuffix, validateOnClick: propValidateOnClick, validateOnChange: propValidateOnChange, dateStartInputAriaLabel, dateEndInputAriaLabel, }: DateRangePickerPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
70
70
|
export default DateRangePickerPanel;
|
|
@@ -98,12 +98,14 @@ function DateRangePickerPanel({
|
|
|
98
98
|
timeFormat,
|
|
99
99
|
utcSuffix,
|
|
100
100
|
validateOnClick: propValidateOnClick,
|
|
101
|
-
validateOnChange,
|
|
101
|
+
validateOnChange: propValidateOnChange,
|
|
102
102
|
dateStartInputAriaLabel,
|
|
103
103
|
dateEndInputAriaLabel
|
|
104
104
|
}) {
|
|
105
105
|
const defaultValidateOnClick = (0, _helpers.useValidateOnClick)();
|
|
106
|
+
const defaultValidateOnChange = (0, _helpers.useGetDateTimeValidityError)();
|
|
106
107
|
const validateOnClick = propValidateOnClick || defaultValidateOnClick;
|
|
108
|
+
const validateOnChange = propValidateOnChange || defaultValidateOnChange;
|
|
107
109
|
const dateTimeFormat = (0, _helpers.getDateTimeFormat)(dateFormat, timeFormat);
|
|
108
110
|
|
|
109
111
|
// Developer-provided datetimes might not always follow the exact date and time format they want to use.
|
|
@@ -24,7 +24,7 @@ export type InitialDirection = ValueOf<typeof INITIAL_DIRECTION>;
|
|
|
24
24
|
export type DateRangePickerProps = {
|
|
25
25
|
onUpdate: (updatedStart: Moment, updatedEnd: Moment) => void;
|
|
26
26
|
validateOnClick?: ValidateOnClick;
|
|
27
|
-
validateOnChange
|
|
27
|
+
validateOnChange?: ValidateOnChange;
|
|
28
28
|
start: Moment;
|
|
29
29
|
end: Moment;
|
|
30
30
|
minStart?: Moment;
|
|
@@ -23,6 +23,14 @@ export declare function useValidateOnClick(): ({ start, end, minStart, maxEnd, v
|
|
|
23
23
|
END_AFTER_MAX?: string | undefined;
|
|
24
24
|
};
|
|
25
25
|
};
|
|
26
|
+
/** Checks whether a string can be strictly parsed as a moment object following a provided datetime format
|
|
27
|
+
*
|
|
28
|
+
* @param {string} proposedDateTime
|
|
29
|
+
* @param {string} dateTimeFormat
|
|
30
|
+
* @returns {boolean}
|
|
31
|
+
*/
|
|
32
|
+
export declare function isValidDateTime(proposedDateTime: string, dateTimeFormat: string): boolean;
|
|
33
|
+
export declare function useGetDateTimeValidityError(): (dateTime: string, dateTimeFormat: string) => string | undefined;
|
|
26
34
|
export interface StringToMomentParams {
|
|
27
35
|
dateTimeFormat?: string;
|
|
28
36
|
strictParse?: boolean;
|
|
@@ -13,7 +13,9 @@ exports.getValidityFromErrors = getValidityFromErrors;
|
|
|
13
13
|
exports.isMonthRelatedToTimePicker = isMonthRelatedToTimePicker;
|
|
14
14
|
exports.isNavigationAvailableForMonthsView = isNavigationAvailableForMonthsView;
|
|
15
15
|
exports.isNavigationAvailableForYearsView = isNavigationAvailableForYearsView;
|
|
16
|
+
exports.isValidDateTime = isValidDateTime;
|
|
16
17
|
exports.truncateDateTimeToFormat = truncateDateTimeToFormat;
|
|
18
|
+
exports.useGetDateTimeValidityError = useGetDateTimeValidityError;
|
|
17
19
|
exports.useValidateOnClick = useValidateOnClick;
|
|
18
20
|
var _react = _interopRequireDefault(require("react"));
|
|
19
21
|
var _moment = _interopRequireDefault(require("moment"));
|
|
@@ -93,7 +95,7 @@ function useValidateOnClick() {
|
|
|
93
95
|
fieldName: VALIDATION_ENTITY[viewMode].end
|
|
94
96
|
});
|
|
95
97
|
}
|
|
96
|
-
if (start && end) {
|
|
98
|
+
if (start && end && end.isValid()) {
|
|
97
99
|
endErrors = (0, _omit.default)(endErrors, [_datetimeRangePickerPanel.DATE_RANGE_ERROR_TYPES.INVALID_END_DATE]);
|
|
98
100
|
}
|
|
99
101
|
if (sameDateError && start?.isSame(end)) {
|
|
@@ -108,6 +110,43 @@ function useValidateOnClick() {
|
|
|
108
110
|
};
|
|
109
111
|
};
|
|
110
112
|
}
|
|
113
|
+
|
|
114
|
+
/** Checks whether a string can be strictly parsed as a moment object following a provided datetime format
|
|
115
|
+
*
|
|
116
|
+
* @param {string} proposedDateTime
|
|
117
|
+
* @param {string} dateTimeFormat
|
|
118
|
+
* @returns {boolean}
|
|
119
|
+
*/
|
|
120
|
+
function isValidDateTime(proposedDateTime, dateTimeFormat) {
|
|
121
|
+
try {
|
|
122
|
+
convertStringToMoment(proposedDateTime, {
|
|
123
|
+
dateTimeFormat
|
|
124
|
+
})?.isValid();
|
|
125
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
126
|
+
} catch (err) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
function useGetDateTimeValidityError() {
|
|
132
|
+
const {
|
|
133
|
+
t
|
|
134
|
+
} = (0, _useTranslation.useTranslation)();
|
|
135
|
+
return function getDateTimeValidityError(dateTime, dateTimeFormat) {
|
|
136
|
+
if (_moment.default.isMoment(dateTime)) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (typeof dateTime === 'string') {
|
|
140
|
+
if (isValidDateTime(dateTime, dateTimeFormat)) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
return t('Must follow {{dateTimeFormat}} format', {
|
|
144
|
+
dateTimeFormat
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return t('Expected a datetime');
|
|
148
|
+
};
|
|
149
|
+
}
|
|
111
150
|
function getValidityFromErrors(errorMapping) {
|
|
112
151
|
let validityValues;
|
|
113
152
|
if ((0, _isEmpty.default)(errorMapping)) {
|
|
@@ -34,6 +34,12 @@ const MultiselectSearchableList = ({
|
|
|
34
34
|
const {
|
|
35
35
|
t
|
|
36
36
|
} = (0, _useTranslation.useTranslation)();
|
|
37
|
+
const getSelectedItemsMessageDefault = itemsLength => itemsLength === 1 ? t('{{itemsLength}} item selected', {
|
|
38
|
+
itemsLength
|
|
39
|
+
}) : t('{{itemsLength}} items selected', {
|
|
40
|
+
itemsLength
|
|
41
|
+
});
|
|
42
|
+
const selectedItemsMessageFn = selectedItemsMessage || getSelectedItemsMessageDefault;
|
|
37
43
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
38
44
|
className: "multiselect-items-list",
|
|
39
45
|
"test-id": "multiselect-items-list",
|
|
@@ -49,7 +55,7 @@ const MultiselectSearchableList = ({
|
|
|
49
55
|
listKey: ({
|
|
50
56
|
id
|
|
51
57
|
}) => id,
|
|
52
|
-
header:
|
|
58
|
+
header: selectedItemsMessageFn(selectedItems.length),
|
|
53
59
|
onItemRemove: onSelectToggle,
|
|
54
60
|
onClearAll: onClearAll,
|
|
55
61
|
clearAllText: clearAllText ?? t('Clear all'),
|
|
@@ -8,6 +8,7 @@ var _react = _interopRequireWildcard(require("react"));
|
|
|
8
8
|
var _faChevronDown = require("@fortawesome/free-solid-svg-icons/faChevronDown");
|
|
9
9
|
var _faChevronUp = require("@fortawesome/free-solid-svg-icons/faChevronUp");
|
|
10
10
|
var _faCircleXmark = require("@fortawesome/free-solid-svg-icons/faCircleXmark");
|
|
11
|
+
var _useTranslation = require("../hooks/use-translation");
|
|
11
12
|
var _fontAwesomeIcon = require("../font-awesome-icon");
|
|
12
13
|
var _button = require("../button");
|
|
13
14
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -23,9 +24,18 @@ function SelectedItemsBoard({
|
|
|
23
24
|
clearAllText,
|
|
24
25
|
removeText
|
|
25
26
|
}) {
|
|
27
|
+
const {
|
|
28
|
+
t
|
|
29
|
+
} = (0, _useTranslation.useTranslation)();
|
|
26
30
|
const [isExpanded, toggleExpanded] = (0, _react.useState)(true);
|
|
31
|
+
const getSelectedItemsMessageDefault = itemsLength => itemsLength === 1 ? t('{{itemsLength}} item selected', {
|
|
32
|
+
itemsLength
|
|
33
|
+
}) : t('{{itemsLength}} items selected', {
|
|
34
|
+
itemsLength
|
|
35
|
+
});
|
|
36
|
+
|
|
27
37
|
// not in default props because it depends on items length
|
|
28
|
-
const headerContent = header || getDefaultHeaderText?.(items.length);
|
|
38
|
+
const headerContent = header || getDefaultHeaderText?.(items.length) || getSelectedItemsMessageDefault(items.length);
|
|
29
39
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
30
40
|
className: "selected-items-board",
|
|
31
41
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("header", {
|
|
@@ -47,6 +57,7 @@ function SelectedItemsBoard({
|
|
|
47
57
|
"test-id": "selected-items-board-item-label",
|
|
48
58
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
49
59
|
className: "item-display-label",
|
|
60
|
+
"test-id": item?.testId,
|
|
50
61
|
children: displayLabel(item, index)
|
|
51
62
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
|
|
52
63
|
testId: "selected-items-board-remove-item-btn",
|
package/cjs/scheduler/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Scheduler } from './scheduler';
|
|
2
2
|
import { DEFAULT_SCHEDULE, FREQUENCIES, DEFAULT_SCHEDULES, SWITCHER_TYPES, TAB_KEYS } from './constants';
|
|
3
|
-
import { getFrequency } from './utils';
|
|
3
|
+
import { getFrequency, useGetScheduleString } from './utils';
|
|
4
4
|
export type { ScheduleValidity, Schedule, DateItem, Months, LabelTexts, Frequency, } from './constants';
|
|
5
5
|
export type { SchedulerProps } from './scheduler';
|
|
6
|
-
export { Scheduler, getFrequency, DEFAULT_SCHEDULE, FREQUENCIES, DEFAULT_SCHEDULES, SWITCHER_TYPES, TAB_KEYS, };
|
|
6
|
+
export { Scheduler, getFrequency, useGetScheduleString, DEFAULT_SCHEDULE, FREQUENCIES, DEFAULT_SCHEDULES, SWITCHER_TYPES, TAB_KEYS, };
|
package/cjs/scheduler/index.js
CHANGED
|
@@ -45,6 +45,12 @@ Object.defineProperty(exports, "getFrequency", {
|
|
|
45
45
|
return _utils.getFrequency;
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
|
+
Object.defineProperty(exports, "useGetScheduleString", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () {
|
|
51
|
+
return _utils.useGetScheduleString;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
48
54
|
var _scheduler = require("./scheduler");
|
|
49
55
|
var _constants = require("./constants");
|
|
50
56
|
var _utils = require("./utils");
|
package/cjs/scheduler/utils.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { Frequency, Schedule, ScheduleValidity } from './constants';
|
|
2
2
|
export declare const stringToArrayOfNumbersOrAll: (value?: string | number) => (number | "*")[];
|
|
3
3
|
export declare function useArrayOfRangedNumbersOrAllValidator(): ({ min, max, values, allowAll, }: ScheduleValidity) => ScheduleValidity | undefined;
|
|
4
|
+
export declare function useGetScheduleString(schedule: Schedule, stringOptions?: {
|
|
5
|
+
complexScheduleString?: string | null;
|
|
6
|
+
timeStandardString?: string | null;
|
|
7
|
+
}): string | null;
|
|
4
8
|
export declare function getFrequency({ minute, hour, month, dayOfMonth, dayOfWeek, }: Schedule): Frequency | undefined;
|
package/cjs/scheduler/utils.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.getFrequency = getFrequency;
|
|
7
7
|
exports.stringToArrayOfNumbersOrAll = void 0;
|
|
8
8
|
exports.useArrayOfRangedNumbersOrAllValidator = useArrayOfRangedNumbersOrAllValidator;
|
|
9
|
+
exports.useGetScheduleString = useGetScheduleString;
|
|
9
10
|
var _message = require("../message");
|
|
10
11
|
var _useTranslation = require("../hooks/use-translation");
|
|
11
12
|
var _constants = require("./constants");
|
|
@@ -62,6 +63,92 @@ function useArrayOfRangedNumbersOrAllValidator() {
|
|
|
62
63
|
return validity;
|
|
63
64
|
};
|
|
64
65
|
}
|
|
66
|
+
function useGetScheduleString(schedule, stringOptions = {}) {
|
|
67
|
+
const {
|
|
68
|
+
t
|
|
69
|
+
} = (0, _useTranslation.useTranslation)();
|
|
70
|
+
const {
|
|
71
|
+
complexScheduleString = t('Complex schedule'),
|
|
72
|
+
timeStandardString = t('(UTC)')
|
|
73
|
+
} = stringOptions;
|
|
74
|
+
const scheduleStringTimeStandard = timeStandardString ? ` ${timeStandardString}` : '';
|
|
75
|
+
const months = (0, _constants.useMonths)();
|
|
76
|
+
const daysOfWeek = (0, _constants.useDaysOfWeek)();
|
|
77
|
+
switch (getFrequency(schedule)) {
|
|
78
|
+
case _constants.FREQUENCIES.HOURLY:
|
|
79
|
+
return schedule?.minute?.[0] === 1 ? t('Hourly at {{minutes}} minute past the hour', {
|
|
80
|
+
minutes: schedule.minute[0].toString()
|
|
81
|
+
}) : t('Hourly at {{minutes}} minutes past the hour', {
|
|
82
|
+
minutes: schedule?.minute?.[0].toString()
|
|
83
|
+
});
|
|
84
|
+
case _constants.FREQUENCIES.DAILY:
|
|
85
|
+
return `${t('Daily at {{hour}}:{{minutes}}', {
|
|
86
|
+
hour: schedule?.hour?.[0].toString().padStart(2, '0'),
|
|
87
|
+
minutes: schedule?.minute?.[0].toString().padStart(2, '0')
|
|
88
|
+
})}${scheduleStringTimeStandard}`;
|
|
89
|
+
case _constants.FREQUENCIES.WEEKLY:
|
|
90
|
+
{
|
|
91
|
+
const options = {
|
|
92
|
+
hour: schedule?.hour?.[0].toString().padStart(2, '0'),
|
|
93
|
+
minutes: schedule?.minute?.[0].toString().padStart(2, '0'),
|
|
94
|
+
day: daysOfWeek.find(d => d.index === schedule?.dayOfWeek?.[0])?.label
|
|
95
|
+
};
|
|
96
|
+
const weeklyString = schedule?.dayOfWeek?.length === 1 ? t('Weekly on {{day}} at {{hour}}:{{minutes}}', {
|
|
97
|
+
...options
|
|
98
|
+
}) : t('Weekly on multiple days at {{hour}}:{{minutes}}', {
|
|
99
|
+
...options
|
|
100
|
+
});
|
|
101
|
+
return `${weeklyString}${scheduleStringTimeStandard}`;
|
|
102
|
+
}
|
|
103
|
+
case _constants.FREQUENCIES.MONTHLY:
|
|
104
|
+
{
|
|
105
|
+
const options = {
|
|
106
|
+
hour: schedule?.hour?.[0].toString().padStart(2, '0'),
|
|
107
|
+
minutes: schedule?.minute?.[0].toString().padStart(2, '0'),
|
|
108
|
+
day: schedule?.dayOfMonth?.[0],
|
|
109
|
+
days: schedule?.dayOfMonth?.join(', ') // day 1, 2, 3
|
|
110
|
+
};
|
|
111
|
+
const monthlyString = schedule?.dayOfMonth?.length === 1 ? t('Monthly on day {{day}} at {{hour}}:{{minutes}}', {
|
|
112
|
+
...options
|
|
113
|
+
}) : t('Monthly on days {{days}} at {{hour}}:{{minutes}}', {
|
|
114
|
+
...options
|
|
115
|
+
});
|
|
116
|
+
return `${monthlyString}${scheduleStringTimeStandard}`;
|
|
117
|
+
}
|
|
118
|
+
case _constants.FREQUENCIES.QUARTERLY:
|
|
119
|
+
{
|
|
120
|
+
const options = {
|
|
121
|
+
hour: schedule?.hour?.[0].toString().padStart(2, '0'),
|
|
122
|
+
minutes: schedule?.minute?.[0].toString().padStart(2, '0'),
|
|
123
|
+
day: schedule?.dayOfMonth?.[0],
|
|
124
|
+
days: schedule?.dayOfMonth?.join(', ') // day 1, 2, 3
|
|
125
|
+
};
|
|
126
|
+
const quarterlyString = schedule?.dayOfMonth?.length === 1 ? t('Quarterly on day {{day}} at {{hour}}:{{minutes}}', {
|
|
127
|
+
...options
|
|
128
|
+
}) : t('Quarterly on days {{days}} at {{hour}}:{{minutes}}', {
|
|
129
|
+
...options
|
|
130
|
+
});
|
|
131
|
+
return `${quarterlyString}${scheduleStringTimeStandard}`;
|
|
132
|
+
}
|
|
133
|
+
case _constants.FREQUENCIES.YEARLY:
|
|
134
|
+
{
|
|
135
|
+
const options = {
|
|
136
|
+
hour: schedule?.hour?.[0].toString().padStart(2, '0'),
|
|
137
|
+
minutes: schedule?.minute?.[0].toString().padStart(2, '0'),
|
|
138
|
+
day: schedule?.dayOfMonth?.[0],
|
|
139
|
+
month: Object.values(months).find(m => m.index === schedule?.month?.[0])?.label
|
|
140
|
+
};
|
|
141
|
+
const yearlyString = Math.max(schedule?.month?.length ?? 0, schedule?.dayOfMonth?.length ?? 0) ? t('Yearly on {{month}} {{day}} at {{hour}}:{{minutes}}', {
|
|
142
|
+
...options
|
|
143
|
+
}) : t('Yearly on multiple dates at {{hour}}:{{minutes}}', {
|
|
144
|
+
...options
|
|
145
|
+
});
|
|
146
|
+
return `${yearlyString}${scheduleStringTimeStandard}`;
|
|
147
|
+
}
|
|
148
|
+
default:
|
|
149
|
+
return complexScheduleString;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
65
152
|
function hasSameItems(arr1, arr2) {
|
|
66
153
|
return arr1.length === arr2?.length && arr1.every(item1 => {
|
|
67
154
|
return arr2.find(item2 => item2 === item1);
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _react = require("@testing-library/react");
|
|
4
|
+
var _utils = require("./utils");
|
|
5
|
+
describe('useGetScheduleString', function () {
|
|
6
|
+
describe('Schedule strings', function () {
|
|
7
|
+
const createSchedule = (partialSchedule = {}) => ({
|
|
8
|
+
minute: ['*'],
|
|
9
|
+
hour: ['*'],
|
|
10
|
+
dayOfMonth: ['*'],
|
|
11
|
+
month: ['*'],
|
|
12
|
+
dayOfWeek: ['*'],
|
|
13
|
+
...partialSchedule
|
|
14
|
+
});
|
|
15
|
+
const testSchedules = [{
|
|
16
|
+
schedule: createSchedule({
|
|
17
|
+
minute: [15, 45],
|
|
18
|
+
month: [1, 4, 8, 12]
|
|
19
|
+
}),
|
|
20
|
+
expectedScheduleString: 'Complex schedule',
|
|
21
|
+
hasTimeStandard: false
|
|
22
|
+
}, {
|
|
23
|
+
schedule: createSchedule({
|
|
24
|
+
minute: [1]
|
|
25
|
+
}),
|
|
26
|
+
expectedScheduleString: 'Hourly at 1 minute past the hour',
|
|
27
|
+
hasTimeStandard: false
|
|
28
|
+
}, {
|
|
29
|
+
schedule: createSchedule({
|
|
30
|
+
minute: [5]
|
|
31
|
+
}),
|
|
32
|
+
expectedScheduleString: 'Hourly at 5 minutes past the hour',
|
|
33
|
+
hasTimeStandard: false
|
|
34
|
+
}, {
|
|
35
|
+
schedule: createSchedule({
|
|
36
|
+
hour: [12],
|
|
37
|
+
minute: [30]
|
|
38
|
+
}),
|
|
39
|
+
expectedScheduleString: 'Daily at 12:30',
|
|
40
|
+
hasTimeStandard: true
|
|
41
|
+
}, {
|
|
42
|
+
schedule: createSchedule({
|
|
43
|
+
dayOfWeek: [1],
|
|
44
|
+
hour: [12],
|
|
45
|
+
minute: [30]
|
|
46
|
+
}),
|
|
47
|
+
expectedScheduleString: 'Weekly on Monday at 12:30',
|
|
48
|
+
hasTimeStandard: true
|
|
49
|
+
}, {
|
|
50
|
+
schedule: createSchedule({
|
|
51
|
+
dayOfWeek: [1, 2],
|
|
52
|
+
hour: [12],
|
|
53
|
+
minute: [30]
|
|
54
|
+
}),
|
|
55
|
+
expectedScheduleString: 'Weekly on multiple days at 12:30',
|
|
56
|
+
hasTimeStandard: true
|
|
57
|
+
}, {
|
|
58
|
+
schedule: createSchedule({
|
|
59
|
+
dayOfMonth: [1],
|
|
60
|
+
hour: [6],
|
|
61
|
+
minute: [45]
|
|
62
|
+
}),
|
|
63
|
+
expectedScheduleString: 'Monthly on day 1 at 06:45',
|
|
64
|
+
hasTimeStandard: true
|
|
65
|
+
}, {
|
|
66
|
+
schedule: createSchedule({
|
|
67
|
+
dayOfMonth: [1, 2],
|
|
68
|
+
hour: [6],
|
|
69
|
+
minute: [45]
|
|
70
|
+
}),
|
|
71
|
+
expectedScheduleString: 'Monthly on days 1, 2 at 06:45',
|
|
72
|
+
hasTimeStandard: true
|
|
73
|
+
}, {
|
|
74
|
+
schedule: createSchedule({
|
|
75
|
+
month: [1, 4, 7, 10],
|
|
76
|
+
dayOfMonth: [1],
|
|
77
|
+
hour: [1],
|
|
78
|
+
minute: [30]
|
|
79
|
+
}),
|
|
80
|
+
expectedScheduleString: 'Quarterly on day 1 at 01:30',
|
|
81
|
+
hasTimeStandard: true
|
|
82
|
+
}, {
|
|
83
|
+
schedule: createSchedule({
|
|
84
|
+
month: [1, 4, 7, 10],
|
|
85
|
+
dayOfMonth: [1, 15],
|
|
86
|
+
hour: [1],
|
|
87
|
+
minute: [30]
|
|
88
|
+
}),
|
|
89
|
+
expectedScheduleString: 'Quarterly on days 1, 15 at 01:30',
|
|
90
|
+
hasTimeStandard: true
|
|
91
|
+
}, {
|
|
92
|
+
schedule: createSchedule({
|
|
93
|
+
dayOfMonth: [1],
|
|
94
|
+
month: [6],
|
|
95
|
+
hour: [17],
|
|
96
|
+
minute: [0]
|
|
97
|
+
}),
|
|
98
|
+
expectedScheduleString: 'Yearly on June 1 at 17:00',
|
|
99
|
+
hasTimeStandard: true
|
|
100
|
+
}];
|
|
101
|
+
describe('Default time standard (UTC)', function () {
|
|
102
|
+
testSchedules.forEach(function ({
|
|
103
|
+
schedule,
|
|
104
|
+
expectedScheduleString,
|
|
105
|
+
hasTimeStandard
|
|
106
|
+
}) {
|
|
107
|
+
const expectedString = `${expectedScheduleString}${hasTimeStandard ? ' (UTC)' : ''}`;
|
|
108
|
+
it(`should generate "${expectedString}"`, function () {
|
|
109
|
+
const {
|
|
110
|
+
result
|
|
111
|
+
} = (0, _react.renderHook)(() => (0, _utils.useGetScheduleString)(schedule));
|
|
112
|
+
expect(result.current).toBe(`${expectedString}`);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('Alternate time standard (EST)', function () {
|
|
117
|
+
testSchedules.forEach(function ({
|
|
118
|
+
schedule,
|
|
119
|
+
expectedScheduleString,
|
|
120
|
+
hasTimeStandard
|
|
121
|
+
}) {
|
|
122
|
+
const expectedString = `${expectedScheduleString}${hasTimeStandard ? ' (EST)' : ''}`;
|
|
123
|
+
it(`should generate "${expectedString}"`, function () {
|
|
124
|
+
const {
|
|
125
|
+
result
|
|
126
|
+
} = (0, _react.renderHook)(() => (0, _utils.useGetScheduleString)(schedule, {
|
|
127
|
+
timeStandardString: '(EST)'
|
|
128
|
+
}));
|
|
129
|
+
expect(result.current).toBe(`${expectedString}`);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe('No time standard (locale time)', function () {
|
|
134
|
+
testSchedules.forEach(function ({
|
|
135
|
+
schedule,
|
|
136
|
+
expectedScheduleString
|
|
137
|
+
}) {
|
|
138
|
+
it(`should generate "${expectedScheduleString}"`, function () {
|
|
139
|
+
const {
|
|
140
|
+
result
|
|
141
|
+
} = (0, _react.renderHook)(() => (0, _utils.useGetScheduleString)(schedule, {
|
|
142
|
+
timeStandardString: null
|
|
143
|
+
}));
|
|
144
|
+
expect(result.current).toBe(expectedScheduleString);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
@@ -39,9 +39,9 @@ function ZoomControls({
|
|
|
39
39
|
const {
|
|
40
40
|
t
|
|
41
41
|
} = (0, _useTranslation.useTranslation)();
|
|
42
|
-
const zoomInTextWithDefault = zoomInText ?? t('Zoom
|
|
43
|
-
const zoomOutTextWithDefault = zoomOutText ?? t('Zoom
|
|
44
|
-
const resetTextWithDefault = resetText ?? t('Reset
|
|
42
|
+
const zoomInTextWithDefault = zoomInText ?? t('Zoom in');
|
|
43
|
+
const zoomOutTextWithDefault = zoomOutText ?? t('Zoom out');
|
|
44
|
+
const resetTextWithDefault = resetText ?? t('Reset zoom');
|
|
45
45
|
if (hidden) {
|
|
46
46
|
return null;
|
|
47
47
|
}
|
|
@@ -61,10 +61,10 @@ export type DateRangePickerPanelProps = {
|
|
|
61
61
|
timeFormat: string | boolean;
|
|
62
62
|
utcSuffix?: string;
|
|
63
63
|
validateOnClick?: ValidateOnClick;
|
|
64
|
-
validateOnChange
|
|
64
|
+
validateOnChange?: ValidateOnChange;
|
|
65
65
|
dateStartInputAriaLabel: string;
|
|
66
66
|
dateEndInputAriaLabel: string;
|
|
67
67
|
};
|
|
68
68
|
/** Represents the panel used to select two datetimes that make up a range. */
|
|
69
|
-
declare function DateRangePickerPanel({ buttonText, cancelButtonText, dateFormat, defaultEnd, defaultStart, initialDirection, initialViewMode, initialTargetInput, maxEnd, minStart, sameDateError, onSubmit, onDismiss, resetText, timeFormat, utcSuffix, validateOnClick: propValidateOnClick, validateOnChange, dateStartInputAriaLabel, dateEndInputAriaLabel, }: DateRangePickerPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
69
|
+
declare function DateRangePickerPanel({ buttonText, cancelButtonText, dateFormat, defaultEnd, defaultStart, initialDirection, initialViewMode, initialTargetInput, maxEnd, minStart, sameDateError, onSubmit, onDismiss, resetText, timeFormat, utcSuffix, validateOnClick: propValidateOnClick, validateOnChange: propValidateOnChange, dateStartInputAriaLabel, dateEndInputAriaLabel, }: DateRangePickerPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
70
70
|
export default DateRangePickerPanel;
|
|
@@ -7,7 +7,7 @@ import { ValidityMessages } from '../form-field';
|
|
|
7
7
|
import DateRangeSingleDatePicker from './date-range-single-date-picker';
|
|
8
8
|
import { VIEW_MODE_TYPE } from './datetime-range-picker';
|
|
9
9
|
import DateRangeSingleDatePickerInput from './date-range-single-date-picker-input';
|
|
10
|
-
import { getValidityFromErrors, customizeCalendarView, customizeRenderCalendarView, isMonthRelatedToTimePicker, isNavigationAvailableForMonthsView, isNavigationAvailableForYearsView, getLeftCalendarInitialView, getRightCalendarInitialView, truncateDateTimeToFormat, convertStringToMoment, getDateTimeFormat, useValidateOnClick } from './helpers';
|
|
10
|
+
import { getValidityFromErrors, customizeCalendarView, customizeRenderCalendarView, isMonthRelatedToTimePicker, isNavigationAvailableForMonthsView, isNavigationAvailableForYearsView, getLeftCalendarInitialView, getRightCalendarInitialView, truncateDateTimeToFormat, convertStringToMoment, getDateTimeFormat, useValidateOnClick, useGetDateTimeValidityError } from './helpers';
|
|
11
11
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
12
12
|
export let DATE_RANGE_ERROR_TYPES = /*#__PURE__*/function (DATE_RANGE_ERROR_TYPES) {
|
|
13
13
|
DATE_RANGE_ERROR_TYPES["INVALID_DATETIME"] = "INVALID_DATETIME";
|
|
@@ -90,12 +90,14 @@ function DateRangePickerPanel({
|
|
|
90
90
|
timeFormat,
|
|
91
91
|
utcSuffix,
|
|
92
92
|
validateOnClick: propValidateOnClick,
|
|
93
|
-
validateOnChange,
|
|
93
|
+
validateOnChange: propValidateOnChange,
|
|
94
94
|
dateStartInputAriaLabel,
|
|
95
95
|
dateEndInputAriaLabel
|
|
96
96
|
}) {
|
|
97
97
|
const defaultValidateOnClick = useValidateOnClick();
|
|
98
|
+
const defaultValidateOnChange = useGetDateTimeValidityError();
|
|
98
99
|
const validateOnClick = propValidateOnClick || defaultValidateOnClick;
|
|
100
|
+
const validateOnChange = propValidateOnChange || defaultValidateOnChange;
|
|
99
101
|
const dateTimeFormat = getDateTimeFormat(dateFormat, timeFormat);
|
|
100
102
|
|
|
101
103
|
// Developer-provided datetimes might not always follow the exact date and time format they want to use.
|
|
@@ -24,7 +24,7 @@ export type InitialDirection = ValueOf<typeof INITIAL_DIRECTION>;
|
|
|
24
24
|
export type DateRangePickerProps = {
|
|
25
25
|
onUpdate: (updatedStart: Moment, updatedEnd: Moment) => void;
|
|
26
26
|
validateOnClick?: ValidateOnClick;
|
|
27
|
-
validateOnChange
|
|
27
|
+
validateOnChange?: ValidateOnChange;
|
|
28
28
|
start: Moment;
|
|
29
29
|
end: Moment;
|
|
30
30
|
minStart?: Moment;
|
|
@@ -23,6 +23,14 @@ export declare function useValidateOnClick(): ({ start, end, minStart, maxEnd, v
|
|
|
23
23
|
END_AFTER_MAX?: string | undefined;
|
|
24
24
|
};
|
|
25
25
|
};
|
|
26
|
+
/** Checks whether a string can be strictly parsed as a moment object following a provided datetime format
|
|
27
|
+
*
|
|
28
|
+
* @param {string} proposedDateTime
|
|
29
|
+
* @param {string} dateTimeFormat
|
|
30
|
+
* @returns {boolean}
|
|
31
|
+
*/
|
|
32
|
+
export declare function isValidDateTime(proposedDateTime: string, dateTimeFormat: string): boolean;
|
|
33
|
+
export declare function useGetDateTimeValidityError(): (dateTime: string, dateTimeFormat: string) => string | undefined;
|
|
26
34
|
export interface StringToMomentParams {
|
|
27
35
|
dateTimeFormat?: string;
|
|
28
36
|
strictParse?: boolean;
|
|
@@ -75,7 +75,7 @@ export function useValidateOnClick() {
|
|
|
75
75
|
fieldName: VALIDATION_ENTITY[viewMode].end
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
|
-
if (start && end) {
|
|
78
|
+
if (start && end && end.isValid()) {
|
|
79
79
|
endErrors = omit(endErrors, [DATE_RANGE_ERROR_TYPES.INVALID_END_DATE]);
|
|
80
80
|
}
|
|
81
81
|
if (sameDateError && start?.isSame(end)) {
|
|
@@ -90,6 +90,43 @@ export function useValidateOnClick() {
|
|
|
90
90
|
};
|
|
91
91
|
};
|
|
92
92
|
}
|
|
93
|
+
|
|
94
|
+
/** Checks whether a string can be strictly parsed as a moment object following a provided datetime format
|
|
95
|
+
*
|
|
96
|
+
* @param {string} proposedDateTime
|
|
97
|
+
* @param {string} dateTimeFormat
|
|
98
|
+
* @returns {boolean}
|
|
99
|
+
*/
|
|
100
|
+
export function isValidDateTime(proposedDateTime, dateTimeFormat) {
|
|
101
|
+
try {
|
|
102
|
+
convertStringToMoment(proposedDateTime, {
|
|
103
|
+
dateTimeFormat
|
|
104
|
+
})?.isValid();
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
106
|
+
} catch (err) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
export function useGetDateTimeValidityError() {
|
|
112
|
+
const {
|
|
113
|
+
t
|
|
114
|
+
} = useTranslation();
|
|
115
|
+
return function getDateTimeValidityError(dateTime, dateTimeFormat) {
|
|
116
|
+
if (moment.isMoment(dateTime)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (typeof dateTime === 'string') {
|
|
120
|
+
if (isValidDateTime(dateTime, dateTimeFormat)) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
return t('Must follow {{dateTimeFormat}} format', {
|
|
124
|
+
dateTimeFormat
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return t('Expected a datetime');
|
|
128
|
+
};
|
|
129
|
+
}
|
|
93
130
|
export function getValidityFromErrors(errorMapping) {
|
|
94
131
|
let validityValues;
|
|
95
132
|
if (isEmpty(errorMapping)) {
|
|
@@ -27,6 +27,12 @@ const MultiselectSearchableList = ({
|
|
|
27
27
|
const {
|
|
28
28
|
t
|
|
29
29
|
} = useTranslation();
|
|
30
|
+
const getSelectedItemsMessageDefault = itemsLength => itemsLength === 1 ? t('{{itemsLength}} item selected', {
|
|
31
|
+
itemsLength
|
|
32
|
+
}) : t('{{itemsLength}} items selected', {
|
|
33
|
+
itemsLength
|
|
34
|
+
});
|
|
35
|
+
const selectedItemsMessageFn = selectedItemsMessage || getSelectedItemsMessageDefault;
|
|
30
36
|
return /*#__PURE__*/_jsx("div", {
|
|
31
37
|
className: "multiselect-items-list",
|
|
32
38
|
"test-id": "multiselect-items-list",
|
|
@@ -42,7 +48,7 @@ const MultiselectSearchableList = ({
|
|
|
42
48
|
listKey: ({
|
|
43
49
|
id
|
|
44
50
|
}) => id,
|
|
45
|
-
header:
|
|
51
|
+
header: selectedItemsMessageFn(selectedItems.length),
|
|
46
52
|
onItemRemove: onSelectToggle,
|
|
47
53
|
onClearAll: onClearAll,
|
|
48
54
|
clearAllText: clearAllText ?? t('Clear all'),
|
|
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import { faChevronDown } from '@fortawesome/free-solid-svg-icons/faChevronDown';
|
|
3
3
|
import { faChevronUp } from '@fortawesome/free-solid-svg-icons/faChevronUp';
|
|
4
4
|
import { faCircleXmark } from '@fortawesome/free-solid-svg-icons/faCircleXmark';
|
|
5
|
+
import { useTranslation } from '../hooks/use-translation';
|
|
5
6
|
import { FontAwesomeIcon } from '../font-awesome-icon';
|
|
6
7
|
import { Button, ACCENT_TYPES } from '../button';
|
|
7
8
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
@@ -16,9 +17,18 @@ export default function SelectedItemsBoard({
|
|
|
16
17
|
clearAllText,
|
|
17
18
|
removeText
|
|
18
19
|
}) {
|
|
20
|
+
const {
|
|
21
|
+
t
|
|
22
|
+
} = useTranslation();
|
|
19
23
|
const [isExpanded, toggleExpanded] = useState(true);
|
|
24
|
+
const getSelectedItemsMessageDefault = itemsLength => itemsLength === 1 ? t('{{itemsLength}} item selected', {
|
|
25
|
+
itemsLength
|
|
26
|
+
}) : t('{{itemsLength}} items selected', {
|
|
27
|
+
itemsLength
|
|
28
|
+
});
|
|
29
|
+
|
|
20
30
|
// not in default props because it depends on items length
|
|
21
|
-
const headerContent = header || getDefaultHeaderText?.(items.length);
|
|
31
|
+
const headerContent = header || getDefaultHeaderText?.(items.length) || getSelectedItemsMessageDefault(items.length);
|
|
22
32
|
return /*#__PURE__*/_jsxs("div", {
|
|
23
33
|
className: "selected-items-board",
|
|
24
34
|
children: [/*#__PURE__*/_jsx("header", {
|
|
@@ -40,6 +50,7 @@ export default function SelectedItemsBoard({
|
|
|
40
50
|
"test-id": "selected-items-board-item-label",
|
|
41
51
|
children: [/*#__PURE__*/_jsx("div", {
|
|
42
52
|
className: "item-display-label",
|
|
53
|
+
"test-id": item?.testId,
|
|
43
54
|
children: displayLabel(item, index)
|
|
44
55
|
}), /*#__PURE__*/_jsx(Button, {
|
|
45
56
|
testId: "selected-items-board-remove-item-btn",
|
package/esm/scheduler/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Scheduler } from './scheduler';
|
|
2
2
|
import { DEFAULT_SCHEDULE, FREQUENCIES, DEFAULT_SCHEDULES, SWITCHER_TYPES, TAB_KEYS } from './constants';
|
|
3
|
-
import { getFrequency } from './utils';
|
|
3
|
+
import { getFrequency, useGetScheduleString } from './utils';
|
|
4
4
|
export type { ScheduleValidity, Schedule, DateItem, Months, LabelTexts, Frequency, } from './constants';
|
|
5
5
|
export type { SchedulerProps } from './scheduler';
|
|
6
|
-
export { Scheduler, getFrequency, DEFAULT_SCHEDULE, FREQUENCIES, DEFAULT_SCHEDULES, SWITCHER_TYPES, TAB_KEYS, };
|
|
6
|
+
export { Scheduler, getFrequency, useGetScheduleString, DEFAULT_SCHEDULE, FREQUENCIES, DEFAULT_SCHEDULES, SWITCHER_TYPES, TAB_KEYS, };
|