@gooddata/sdk-ui-kit 11.53.0-alpha.6 → 11.53.0
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/esm/@ui/UiGranteeRowControls/UiGranteeRowControls.d.ts +3 -1
- package/esm/@ui/UiGranteeRowControls/UiGranteeRowControls.d.ts.map +1 -1
- package/esm/@ui/UiGranteeRowControls/UiGranteeRowControls.js +2 -2
- package/esm/@ui/UiListbox/defaults/DefaultUiListboxInteractiveItemComponent.d.ts.map +1 -1
- package/esm/@ui/UiListbox/defaults/DefaultUiListboxInteractiveItemComponent.js +4 -2
- package/esm/@ui/UiPermissionMenu/UiPermissionMenu.d.ts +6 -1
- package/esm/@ui/UiPermissionMenu/UiPermissionMenu.d.ts.map +1 -1
- package/esm/@ui/UiPermissionMenu/UiPermissionMenu.js +5 -4
- package/esm/Timezone/TimezoneSelect.d.ts +14 -4
- package/esm/Timezone/TimezoneSelect.d.ts.map +1 -1
- package/esm/Timezone/TimezoneSelect.js +11 -4
- package/esm/Timezone/timezones.d.ts +3 -4
- package/esm/Timezone/timezones.d.ts.map +1 -1
- package/esm/Timezone/timezones.js +7 -5
- package/esm/sdk-ui-kit.d.ts +25 -9
- package/package.json +11 -11
- package/esm/RecurrenceForm/utils/simpleRecurrenceTypeMappingFn.test.d.ts +0 -2
- package/esm/RecurrenceForm/utils/simpleRecurrenceTypeMappingFn.test.d.ts.map +0 -1
- package/esm/RecurrenceForm/utils/simpleRecurrenceTypeMappingFn.test.js +0 -79
- package/esm/RecurrenceForm/utils/utils.test.d.ts +0 -2
- package/esm/RecurrenceForm/utils/utils.test.d.ts.map +0 -1
- package/esm/RecurrenceForm/utils/utils.test.js +0 -224
|
@@ -23,6 +23,8 @@ export interface IUiGranteeRowControlsProps {
|
|
|
23
23
|
disabledLevels?: ReadonlyArray<PermissionMenuLevel>;
|
|
24
24
|
/** Tooltip shown on disabled level rows in place of the level's info text. */
|
|
25
25
|
disabledTooltip?: string;
|
|
26
|
+
/** Per-level override of `disabledTooltip` — see {@link UiPermissionMenu}. */
|
|
27
|
+
disabledLevelTooltips?: Partial<Record<PermissionMenuLevel, string>>;
|
|
26
28
|
onLabelsChange: (selectedIds: string[]) => void;
|
|
27
29
|
onPermissionChange: (level: PermissionMenuLevel) => void;
|
|
28
30
|
onRemoveAccess?: () => void;
|
|
@@ -44,5 +46,5 @@ export interface IUiGranteeRowControlsProps {
|
|
|
44
46
|
*
|
|
45
47
|
* @internal
|
|
46
48
|
*/
|
|
47
|
-
export declare function UiGranteeRowControls({ labels, selectedLabelIds, permissionLevel, effectivePermission, disabledLevels, disabledTooltip, onLabelsChange, onPermissionChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, isDisabled, dataTestId }: IUiGranteeRowControlsProps): import("react/jsx-runtime").JSX.Element;
|
|
49
|
+
export declare function UiGranteeRowControls({ labels, selectedLabelIds, permissionLevel, effectivePermission, disabledLevels, disabledTooltip, disabledLevelTooltips, onLabelsChange, onPermissionChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, isDisabled, dataTestId }: IUiGranteeRowControlsProps): import("react/jsx-runtime").JSX.Element;
|
|
48
50
|
//# sourceMappingURL=UiGranteeRowControls.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UiGranteeRowControls.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiGranteeRowControls/UiGranteeRowControls.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAMpE,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACxF,OAAO,EACH,KAAK,mBAAmB,EAG3B,MAAM,yCAAyC,CAAC;AAcjD;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACvC,mDAAmD;IACnD,MAAM,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC9C,gBAAgB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC,8EAA4E;IAC5E,eAAe,EAAE,wBAAwB,CAAC;IAC1C;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,wBAAwB,CAAC;IAC/C,wFAAsF;IACtF,cAAc,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IACpD,8EAA8E;IAC9E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACzD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,2DAA2D;IAC3D,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,EACjC,MAAM,EACN,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,UAAU,EACV,UAAU,EACb,EAAE,0BAA0B,
|
|
1
|
+
{"version":3,"file":"UiGranteeRowControls.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiGranteeRowControls/UiGranteeRowControls.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAMpE,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACxF,OAAO,EACH,KAAK,mBAAmB,EAG3B,MAAM,yCAAyC,CAAC;AAcjD;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACvC,mDAAmD;IACnD,MAAM,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC9C,gBAAgB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC,8EAA4E;IAC5E,eAAe,EAAE,wBAAwB,CAAC;IAC1C;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,wBAAwB,CAAC;IAC/C,wFAAsF;IACtF,cAAc,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IACpD,8EAA8E;IAC9E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gFAA8E;IAC9E,qBAAqB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,CAAC;IACrE,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACzD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,2DAA2D;IAC3D,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,EACjC,MAAM,EACN,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,UAAU,EACV,UAAU,EACb,EAAE,0BAA0B,2CAyD5B"}
|
|
@@ -23,7 +23,7 @@ const EFFECTIVE_PERMISSION_TOOLTIP = {
|
|
|
23
23
|
*
|
|
24
24
|
* @internal
|
|
25
25
|
*/
|
|
26
|
-
export function UiGranteeRowControls({ labels, selectedLabelIds, permissionLevel, effectivePermission, disabledLevels, disabledTooltip, onLabelsChange, onPermissionChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, isDisabled, dataTestId, }) {
|
|
26
|
+
export function UiGranteeRowControls({ labels, selectedLabelIds, permissionLevel, effectivePermission, disabledLevels, disabledTooltip, disabledLevelTooltips, onLabelsChange, onPermissionChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, isDisabled, dataTestId, }) {
|
|
27
27
|
const intl = useIntl();
|
|
28
28
|
const hasLabels = labels.length > 0;
|
|
29
29
|
// The caller decides when inheritance drives the row (see the prop's contract) —
|
|
@@ -32,6 +32,6 @@ export function UiGranteeRowControls({ labels, selectedLabelIds, permissionLevel
|
|
|
32
32
|
const effectiveTooltip = inheritedTooltipMessage
|
|
33
33
|
? intl.formatMessage(inheritedTooltipMessage)
|
|
34
34
|
: undefined;
|
|
35
|
-
return (_jsxs("div", { className: b(), "data-testid": dataTestId, children: [effectiveTooltip ? (_jsx(UiTooltip, { triggerBy: ["hover", "focus"], content: effectiveTooltip, anchor: _jsx("span", { className: e("effective-warning"), role: "img", "aria-label": intl.formatMessage(olpPermissionMessages.effectivePermissionAriaLabel), tabIndex: 0, children: _jsx(UiIcon, { type: "warning", size: 16, color: "warning" }) }) })) : null, _jsx(UiPermissionMenu, { anchor: _jsx(UiButton, { label: intl.formatMessage(permissionLevelMessage(permissionLevel)), size: "small", variant: "dropdownInline", iconAfter: "navigateDown", isDisabled: isDisabled }), selectedLevel: permissionLevel, onPermissionChange: onPermissionChange, disabledLevels: disabledLevels, disabledTooltip: disabledTooltip, labels: hasLabels ? labels : undefined, selectedLabelIds: selectedLabelIds, onLabelsChange: onLabelsChange, onRemoveAccess: onRemoveAccess, isRemoveDisabled: isRemoveDisabled, removeDisabledTooltip: removeDisabledTooltip })
|
|
35
|
+
return (_jsxs("div", { className: b(), "data-testid": dataTestId, children: [effectiveTooltip ? (_jsx(UiTooltip, { triggerBy: ["hover", "focus"], content: effectiveTooltip, anchor: _jsx("span", { className: e("effective-warning"), role: "img", "aria-label": intl.formatMessage(olpPermissionMessages.effectivePermissionAriaLabel), tabIndex: 0, children: _jsx(UiIcon, { type: "warning", size: 16, color: "warning" }) }) })) : null, _jsx(UiPermissionMenu, { anchor: _jsx(UiButton, { label: intl.formatMessage(permissionLevelMessage(permissionLevel)), size: "small", variant: "dropdownInline", iconAfter: "navigateDown", isDisabled: isDisabled }), selectedLevel: permissionLevel, onPermissionChange: onPermissionChange, disabledLevels: disabledLevels, disabledTooltip: disabledTooltip, disabledLevelTooltips: disabledLevelTooltips, labels: hasLabels ? labels : undefined, selectedLabelIds: selectedLabelIds, onLabelsChange: onLabelsChange, onRemoveAccess: onRemoveAccess, isRemoveDisabled: isRemoveDisabled, removeDisabledTooltip: removeDisabledTooltip })
|
|
36
36
|
] }));
|
|
37
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultUiListboxInteractiveItemComponent.d.ts","sourceRoot":"","sources":["../../../../src/@ui/UiListbox/defaults/DefaultUiListboxInteractiveItemComponent.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,EAAE,KAAK,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAElE;;GAEG;AACH,wBAAgB,wCAAwC,CAAC,CAAC,EAAE,EACxD,IAAI,EACJ,SAAS,EACT,UAAU,EACV,SAAS,EACT,QAAQ,EACX,EAAE,8BAA8B,CAAC,CAAC,CAAC,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"DefaultUiListboxInteractiveItemComponent.d.ts","sourceRoot":"","sources":["../../../../src/@ui/UiListbox/defaults/DefaultUiListboxInteractiveItemComponent.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,EAAE,KAAK,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAElE;;GAEG;AACH,wBAAgB,wCAAwC,CAAC,CAAC,EAAE,EACxD,IAAI,EACJ,SAAS,EACT,UAAU,EACV,SAAS,EACT,QAAQ,EACX,EAAE,8BAA8B,CAAC,CAAC,CAAC,GAAG,SAAS,CAuC/C"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ShortenedText } from "../../../ShortenedText/ShortenedText.js";
|
|
3
3
|
import { UiIcon } from "../../UiIcon/UiIcon.js";
|
|
4
4
|
import { UiTooltip } from "../../UiTooltip/UiTooltip.js";
|
|
@@ -12,5 +12,7 @@ export function DefaultUiListboxInteractiveItemComponent({ item, isFocused, isSe
|
|
|
12
12
|
isSelected,
|
|
13
13
|
isCompact,
|
|
14
14
|
isDisabled: !!item.isDisabled,
|
|
15
|
-
}), onClick: item.isDisabled ? undefined : onSelect, children: [item.icon ? _jsx(UiIcon, { type: item.icon, size: 14, color: "complementary-7" }) : null, _jsx(ShortenedText, { className: e("item-title"), ellipsisPosition: "end", children: item.stringTitle }), item.tooltip ? (
|
|
15
|
+
}), onClick: item.isDisabled ? undefined : onSelect, children: [item.icon ? _jsx(UiIcon, { type: item.icon, size: 14, color: "complementary-7" }) : null, _jsx(ShortenedText, { className: e("item-title"), ellipsisPosition: "end", children: item.stringTitle }), item.tooltip ? (_jsxs(_Fragment, { children: [
|
|
16
|
+
_jsx(UiTooltip, { anchor: _jsx("div", { className: e("item-explanation"), children: _jsx(UiIcon, { type: "question", size: 14, color: "complementary-7" }) }), content: item.tooltip, triggerBy: ["hover"], accessibilityHidden: true, arrowPlacement: "left", optimalPlacement: true, width: 200, offset: 10 }), _jsx("span", { className: "sr-only", children: item.tooltip })
|
|
17
|
+
] })) : null] }));
|
|
16
18
|
}
|
|
@@ -33,6 +33,11 @@ export interface IUiPermissionMenuProps {
|
|
|
33
33
|
disabledLevels?: ReadonlyArray<PermissionMenuLevel>;
|
|
34
34
|
/** Tooltip shown on disabled level rows in place of the level's info text. */
|
|
35
35
|
disabledTooltip?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Per-level override of `disabledTooltip`, for menus whose disabled levels have
|
|
38
|
+
* different reasons (capped by the caller's own level vs. already inherited).
|
|
39
|
+
*/
|
|
40
|
+
disabledLevelTooltips?: Partial<Record<PermissionMenuLevel, string>>;
|
|
36
41
|
/**
|
|
37
42
|
* Non-empty enables a labels row that drills into {@link UiLabelsChecklist}
|
|
38
43
|
* within the menu — for rows whose menu hosts every action (no "⋯" menu).
|
|
@@ -64,5 +69,5 @@ export interface IUiPermissionMenuProps {
|
|
|
64
69
|
*
|
|
65
70
|
* @internal
|
|
66
71
|
*/
|
|
67
|
-
export declare function UiPermissionMenu({ anchor, selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, dataTestId }: IUiPermissionMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
72
|
+
export declare function UiPermissionMenu({ anchor, selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, disabledLevelTooltips, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, dataTestId }: IUiPermissionMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
68
73
|
//# sourceMappingURL=UiPermissionMenu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UiPermissionMenu.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiPermissionMenu/UiPermissionMenu.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,YAAY,EAAiC,MAAM,OAAO,CAAC;AAE7F,OAAO,EAAE,KAAK,iBAAiB,EAAW,MAAM,YAAY,CAAC;AAO7D,OAAO,EAAE,KAAK,sBAAsB,EAAqB,MAAM,2CAA2C,CAAC;AAM3G;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAQ5D;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,GAAG,iBAAiB,CAEpF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,4CAA4C;IAC5C,MAAM,EAAE,YAAY,CAAC;IACrB,qEAAmE;IACnE,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,oDAAoD;IACpD,kBAAkB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACzD;;;OAGG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IACpD,8EAA8E;IAC9E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC/C,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACzC,uEAAuE;IACvE,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACjD,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,2DAA2D;IAC3D,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAsBD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,EAC7B,MAAM,EACN,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,MAAM,EACN,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,UAAU,EACb,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"UiPermissionMenu.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiPermissionMenu/UiPermissionMenu.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,YAAY,EAAiC,MAAM,OAAO,CAAC;AAE7F,OAAO,EAAE,KAAK,iBAAiB,EAAW,MAAM,YAAY,CAAC;AAO7D,OAAO,EAAE,KAAK,sBAAsB,EAAqB,MAAM,2CAA2C,CAAC;AAM3G;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAQ5D;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,GAAG,iBAAiB,CAEpF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,4CAA4C;IAC5C,MAAM,EAAE,YAAY,CAAC;IACrB,qEAAmE;IACnE,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,oDAAoD;IACpD,kBAAkB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACzD;;;OAGG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IACpD,8EAA8E;IAC9E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,CAAC;IACrE;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC/C,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACzC,uEAAuE;IACvE,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACjD,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,2DAA2D;IAC3D,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAsBD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,EAC7B,MAAM,EACN,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,MAAM,EACN,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,UAAU,EACb,EAAE,sBAAsB,2CA0BxB"}
|
|
@@ -33,11 +33,11 @@ export function permissionLevelMessage(level) {
|
|
|
33
33
|
*
|
|
34
34
|
* @internal
|
|
35
35
|
*/
|
|
36
|
-
export function UiPermissionMenu({ anchor, selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, dataTestId, }) {
|
|
36
|
+
export function UiPermissionMenu({ anchor, selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, disabledLevelTooltips, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, dataTestId, }) {
|
|
37
37
|
const hasLabels = (labels?.length ?? 0) > 0;
|
|
38
|
-
return (_jsx(UiPopover, { anchor: anchor, anchorAccessibilityConfig: { ariaHaspopup: "menu" }, width: hasLabels ? 200 : 180, content: ({ onClose }) => (_jsx(MenuBody, { selectedLevel: selectedLevel, onPermissionChange: onPermissionChange, disabledLevels: disabledLevels, disabledTooltip: disabledTooltip, labels: labels, selectedLabelIds: selectedLabelIds, onLabelsChange: onLabelsChange, onRemoveAccess: onRemoveAccess, isRemoveDisabled: isRemoveDisabled, removeDisabledTooltip: removeDisabledTooltip, onClose: onClose, dataTestId: dataTestId })) }));
|
|
38
|
+
return (_jsx(UiPopover, { anchor: anchor, anchorAccessibilityConfig: { ariaHaspopup: "menu" }, width: hasLabels ? 200 : 180, content: ({ onClose }) => (_jsx(MenuBody, { selectedLevel: selectedLevel, onPermissionChange: onPermissionChange, disabledLevels: disabledLevels, disabledTooltip: disabledTooltip, disabledLevelTooltips: disabledLevelTooltips, labels: labels, selectedLabelIds: selectedLabelIds, onLabelsChange: onLabelsChange, onRemoveAccess: onRemoveAccess, isRemoveDisabled: isRemoveDisabled, removeDisabledTooltip: removeDisabledTooltip, onClose: onClose, dataTestId: dataTestId })) }));
|
|
39
39
|
}
|
|
40
|
-
function MenuBody({ selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, onClose, dataTestId, }) {
|
|
40
|
+
function MenuBody({ selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, disabledLevelTooltips, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, onClose, dataTestId, }) {
|
|
41
41
|
const intl = useIntl();
|
|
42
42
|
// Drill-in state — swaps the row list for the labels checklist. Local to the
|
|
43
43
|
// popover content, so it resets every time the menu opens. `origin` is what
|
|
@@ -60,7 +60,8 @@ function MenuBody({ selectedLevel, onPermissionChange, disabledLevels, disabledT
|
|
|
60
60
|
key: level,
|
|
61
61
|
label,
|
|
62
62
|
// A disabled level explains why it can't be picked instead of what it does.
|
|
63
|
-
|
|
63
|
+
// `||`, not `??`: an empty explanation must not suppress the info button.
|
|
64
|
+
tooltip: disabled ? (disabledLevelTooltips?.[level] ?? disabledTooltip) || tooltip : tooltip,
|
|
64
65
|
radioValue: level,
|
|
65
66
|
disabled,
|
|
66
67
|
onClick: disabled ? () => { } : choose(() => onPermissionChange(level)),
|
|
@@ -3,7 +3,7 @@ import { type IUiListboxItem } from "../@ui/UiListbox/types.js";
|
|
|
3
3
|
import { type IDropdownButtonRenderProps } from "../Dropdown/Dropdown.js";
|
|
4
4
|
/**
|
|
5
5
|
* Special item rendered above the divider in {@link TimezoneSelect}, ahead of the curated
|
|
6
|
-
* timezone list. Callers use these for entries like "Default
|
|
6
|
+
* timezone list. Callers use these for entries like "Default" or "Device time zone".
|
|
7
7
|
*
|
|
8
8
|
* @internal
|
|
9
9
|
*/
|
|
@@ -34,7 +34,7 @@ export interface ITimezoneSelectSpecialItem {
|
|
|
34
34
|
export interface ITimezoneSelectButtonRenderProps extends IDropdownButtonRenderProps {
|
|
35
35
|
/**
|
|
36
36
|
* Human-readable label of the current selection: the matching special item label,
|
|
37
|
-
* the
|
|
37
|
+
* the friendly name of the selected timezone (e.g. "Prague"),
|
|
38
38
|
* or the placeholder when nothing is selected.
|
|
39
39
|
*/
|
|
40
40
|
buttonLabel: string;
|
|
@@ -78,6 +78,16 @@ export interface ITimezoneSelectProps {
|
|
|
78
78
|
* Accessibility label of the search input and the listbox.
|
|
79
79
|
*/
|
|
80
80
|
ariaLabel: string;
|
|
81
|
+
/**
|
|
82
|
+
* Id of the default dropdown trigger, so a visible `<label htmlFor>` can be associated
|
|
83
|
+
* with it. Ignored when a custom trigger is rendered via `renderButton`.
|
|
84
|
+
*/
|
|
85
|
+
id?: string;
|
|
86
|
+
/**
|
|
87
|
+
* Ids of elements describing the default dropdown trigger (`aria-describedby`), e.g. an
|
|
88
|
+
* adjacent hint text. Ignored when a custom trigger is rendered via `renderButton`.
|
|
89
|
+
*/
|
|
90
|
+
ariaDescribedBy?: string;
|
|
81
91
|
/**
|
|
82
92
|
* Label shown when the search yields no results.
|
|
83
93
|
*/
|
|
@@ -107,10 +117,10 @@ export declare function buildListboxItems(specialItems: ITimezoneSelectSpecialIt
|
|
|
107
117
|
export declare function getSelectedItemId(value: string | undefined, specialItems: ITimezoneSelectSpecialItem[]): string | undefined;
|
|
108
118
|
/**
|
|
109
119
|
* Searchable dropdown for picking a timezone from the curated list, with optional special
|
|
110
|
-
* items (e.g. "Default
|
|
120
|
+
* items (e.g. "Default", "Device time zone") rendered above a divider.
|
|
111
121
|
*
|
|
112
122
|
* @internal
|
|
113
123
|
*/
|
|
114
|
-
export declare function TimezoneSelect({ value, onChange, specialItems, placeholder, searchPlaceholder, ariaLabel, noMatchLabel, isDisabled, header, showTooltip, renderButton }: ITimezoneSelectProps): ReactElement;
|
|
124
|
+
export declare function TimezoneSelect({ value, onChange, specialItems, placeholder, searchPlaceholder, ariaLabel, id, ariaDescribedBy, noMatchLabel, isDisabled, header, showTooltip, renderButton }: ITimezoneSelectProps): ReactElement;
|
|
115
125
|
export {};
|
|
116
126
|
//# sourceMappingURL=TimezoneSelect.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimezoneSelect.d.ts","sourceRoot":"","sources":["../../src/Timezone/TimezoneSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAC;AAE7E,OAAO,EAAkC,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"TimezoneSelect.d.ts","sourceRoot":"","sources":["../../src/Timezone/TimezoneSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAC;AAE7E,OAAO,EAAkC,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAMhG,OAAO,EAAY,KAAK,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAapF;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IACvC;;;OAGG;IACH,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC;IAEvB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,gCAAiC,SAAQ,0BAA0B;IAChF;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAE1B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACjC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAE3C;;OAEG;IACH,YAAY,CAAC,EAAE,0BAA0B,EAAE,CAAC;IAE5C;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,SAAS,CAAC;CACzE;AAED,KAAK,oBAAoB,GAAG,MAAM,GAAG,SAAS,CAAC;AAM/C,wBAAgB,iBAAiB,CAC7B,YAAY,EAAE,0BAA0B,EAAE,EAC1C,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,OAAO,GACrB,cAAc,CAAC,oBAAoB,CAAC,EAAE,CAqCxC;AAGD,wBAAgB,iBAAiB,CAC7B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,YAAY,EAAE,0BAA0B,EAAE,GAC3C,MAAM,GAAG,SAAS,CAMpB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,YAAiB,EACjB,WAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,EAAE,EACF,eAAe,EACf,YAAY,EACZ,UAAU,EACV,MAAM,EACN,WAAmB,EACnB,YAAY,EACf,EAAE,oBAAoB,GAAG,YAAY,CAsHrC"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
// (C) 2026 GoodData Corporation
|
|
3
3
|
import { useMemo, useState } from "react";
|
|
4
4
|
import { UiListbox } from "../@ui/UiListbox/UiListbox.js";
|
|
5
|
+
import { DETAILED_ANNOUNCEMENT_THRESHOLD, UiSearchResultsAnnouncement, } from "../@ui/UiSearchResultsAnnouncement/UiSearchResultsAnnouncement.js";
|
|
5
6
|
import { Dropdown } from "../Dropdown/Dropdown.js";
|
|
6
7
|
import { DropdownButton } from "../Dropdown/DropdownButton.js";
|
|
7
8
|
import { Input } from "../Form/Input.js";
|
|
@@ -59,11 +60,11 @@ export function getSelectedItemId(value, specialItems) {
|
|
|
59
60
|
}
|
|
60
61
|
/**
|
|
61
62
|
* Searchable dropdown for picking a timezone from the curated list, with optional special
|
|
62
|
-
* items (e.g. "Default
|
|
63
|
+
* items (e.g. "Default", "Device time zone") rendered above a divider.
|
|
63
64
|
*
|
|
64
65
|
* @internal
|
|
65
66
|
*/
|
|
66
|
-
export function TimezoneSelect({ value, onChange, specialItems = [], placeholder = "", searchPlaceholder, ariaLabel, noMatchLabel, isDisabled, header, showTooltip = false, renderButton, }) {
|
|
67
|
+
export function TimezoneSelect({ value, onChange, specialItems = [], placeholder = "", searchPlaceholder, ariaLabel, id, ariaDescribedBy, noMatchLabel, isDisabled, header, showTooltip = false, renderButton, }) {
|
|
67
68
|
const [searchString, setSearchString] = useState("");
|
|
68
69
|
const selectedSpecialItem = specialItems.find((item) => item.id === value);
|
|
69
70
|
const buttonLabel = selectedSpecialItem
|
|
@@ -73,12 +74,16 @@ export function TimezoneSelect({ value, onChange, specialItems = [], placeholder
|
|
|
73
74
|
: getTimezoneDisplayLabel(value);
|
|
74
75
|
const items = useMemo(() => buildListboxItems(specialItems, searchString, showTooltip), [specialItems, searchString, showTooltip]);
|
|
75
76
|
const hasNoMatchingData = items.length === 0;
|
|
77
|
+
// items may contain a separator between special items and the timezone list; only the
|
|
78
|
+
// interactive entries are search results worth announcing
|
|
79
|
+
const interactiveItems = useMemo(() => items.filter((item) => item.type === "interactive"), [items]);
|
|
76
80
|
return (_jsx(Dropdown, { closeOnParentScroll: true, closeOnOutsideClick: true, alignPoints: DROPDOWN_ALIGN_POINTS, className: "gd-timezone-select s-timezone-select", onOpenStateChanged: (isOpen) => {
|
|
77
81
|
if (!isOpen) {
|
|
78
82
|
setSearchString("");
|
|
79
83
|
}
|
|
80
|
-
}, renderButton: (renderProps) => renderButton ? (renderButton({ ...renderProps, buttonLabel, value, isDisabled })) : (_jsx(DropdownButton, { value: buttonLabel, isOpen: renderProps.isOpen, onClick: renderProps.toggleDropdown, disabled: isDisabled, dropdownId: renderProps.dropdownId, buttonRef: renderProps.buttonRef, accessibilityConfig: {
|
|
84
|
+
}, renderButton: (renderProps) => renderButton ? (renderButton({ ...renderProps, buttonLabel, value, isDisabled })) : (_jsx(DropdownButton, { value: buttonLabel, isOpen: renderProps.isOpen, onClick: renderProps.toggleDropdown, disabled: isDisabled, id: id, dropdownId: renderProps.dropdownId, buttonRef: renderProps.buttonRef, accessibilityConfig: {
|
|
81
85
|
ariaLabel,
|
|
86
|
+
ariaDescribedBy,
|
|
82
87
|
ariaExpanded: renderProps.isOpen,
|
|
83
88
|
popupType: "listbox",
|
|
84
89
|
}, className: "gd-timezone-select__button s-timezone-select-button customizable" })), renderBody: ({ closeDropdown, ariaAttributes }) => (_jsxs("div", { className: "gd-timezone-select__body s-timezone-select-body", children: [header, _jsx("div", { className: "gd-timezone-select__search s-timezone-select-search", children: _jsx(Input, { value: searchString, onChange: (newValue) => setSearchString(newValue.toString()), placeholder: searchPlaceholder, autofocus: true, clearOnEsc: true, isSearch: true, isSmall: true, onEscKeyPress: (event) => {
|
|
@@ -90,7 +95,9 @@ export function TimezoneSelect({ value, onChange, specialItems = [], placeholder
|
|
|
90
95
|
}
|
|
91
96
|
}, accessibilityConfig: {
|
|
92
97
|
ariaLabel,
|
|
93
|
-
} }) }),
|
|
98
|
+
} }) }), _jsx(UiSearchResultsAnnouncement, { totalResults: searchString ? interactiveItems.length : undefined, resultValues: interactiveItems.length <= DETAILED_ANNOUNCEMENT_THRESHOLD
|
|
99
|
+
? interactiveItems.map((item) => item.stringTitle)
|
|
100
|
+
: undefined }), hasNoMatchingData ? (_jsx(NoData, { hasNoMatchingData: true, notFoundLabel: noMatchLabel, noDataLabel: noMatchLabel })) : (_jsx(UiListbox
|
|
94
101
|
// remount when the filter changes so the focused index cannot point
|
|
95
102
|
// past the end of a shortened result list, which would break keyboard selection
|
|
96
103
|
, { width: DROPDOWN_BODY_WIDTH, maxHeight: LIST_MAX_HEIGHT, items: items, selectedItemId: getSelectedItemId(value, specialItems), onSelect: (item) => {
|
|
@@ -54,9 +54,8 @@ export declare function getTimezoneById(id: string | undefined): ITimezoneItem |
|
|
|
54
54
|
*/
|
|
55
55
|
export declare function getUserTimezone(): ITimezoneItem;
|
|
56
56
|
/**
|
|
57
|
-
* Returns the display label used by the timezone picker: the friendly name
|
|
58
|
-
*
|
|
59
|
-
* for zones outside the curated list, and the offset suffix is dropped when not known.
|
|
57
|
+
* Returns the display label used by the timezone picker: the friendly name, e.g. "Prague".
|
|
58
|
+
* The name falls back to the raw IANA ID for zones outside the curated list.
|
|
60
59
|
*
|
|
61
60
|
* The friendly name (not the IANA ID) is shown so the picker reads the same as the Home UI
|
|
62
61
|
* timezone settings — the id-to-name mapping is not visible to users anywhere.
|
|
@@ -66,7 +65,7 @@ export declare function getUserTimezone(): ITimezoneItem;
|
|
|
66
65
|
export declare function getTimezoneDisplayLabel(id: string): string;
|
|
67
66
|
/**
|
|
68
67
|
* Tests whether the timezone matches the search string. Matches on the picker display label
|
|
69
|
-
* (
|
|
68
|
+
* (the friendly name), the friendly title (offset + name) and the IANA ID, with underscores
|
|
70
69
|
* treated as spaces so that e.g. "Los Angeles" finds "America/Los_Angeles".
|
|
71
70
|
*
|
|
72
71
|
* @internal
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timezones.d.ts","sourceRoot":"","sources":["../../src/Timezone/timezones.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC1B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACtB;AAkJD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,MAAM,CAE1F;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,aAAa,EAAE,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAEjF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,aAAa,CAkB/C;AAED
|
|
1
|
+
{"version":3,"file":"timezones.d.ts","sourceRoot":"","sources":["../../src/Timezone/timezones.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC1B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACtB;AAkJD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,MAAM,CAE1F;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,aAAa,EAAE,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAEjF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,aAAa,CAkB/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAWtF;AAmBD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,CAAC,CAUzF;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,MAAM,UAWpD"}
|
|
@@ -183,9 +183,8 @@ export function getUserTimezone() {
|
|
|
183
183
|
TIMEZONE_DEFAULT);
|
|
184
184
|
}
|
|
185
185
|
/**
|
|
186
|
-
* Returns the display label used by the timezone picker: the friendly name
|
|
187
|
-
*
|
|
188
|
-
* for zones outside the curated list, and the offset suffix is dropped when not known.
|
|
186
|
+
* Returns the display label used by the timezone picker: the friendly name, e.g. "Prague".
|
|
187
|
+
* The name falls back to the raw IANA ID for zones outside the curated list.
|
|
189
188
|
*
|
|
190
189
|
* The friendly name (not the IANA ID) is shown so the picker reads the same as the Home UI
|
|
191
190
|
* timezone settings — the id-to-name mapping is not visible to users anywhere.
|
|
@@ -198,7 +197,7 @@ export function getTimezoneDisplayLabel(id) {
|
|
|
198
197
|
}
|
|
199
198
|
/**
|
|
200
199
|
* Tests whether the timezone matches the search string. Matches on the picker display label
|
|
201
|
-
* (
|
|
200
|
+
* (the friendly name), the friendly title (offset + name) and the IANA ID, with underscores
|
|
202
201
|
* treated as spaces so that e.g. "Los Angeles" finds "America/Los_Angeles".
|
|
203
202
|
*
|
|
204
203
|
* @internal
|
|
@@ -260,5 +259,8 @@ export function getCurrentTimeByTimezoneId(id) {
|
|
|
260
259
|
const date = new Date(dateTime);
|
|
261
260
|
const hours = date.getHours();
|
|
262
261
|
const minutes = date.getMinutes();
|
|
263
|
-
|
|
262
|
+
// guard against an unparsable date (NaN); zero is a valid hour/minute value
|
|
263
|
+
return Number.isNaN(hours) || Number.isNaN(minutes)
|
|
264
|
+
? ""
|
|
265
|
+
: `${("0" + hours).slice(-2)}:${("0" + minutes).slice(-2)}`;
|
|
264
266
|
}
|
package/esm/sdk-ui-kit.d.ts
CHANGED
|
@@ -1348,9 +1348,8 @@ export declare const getSiblingItems: <T extends IUiMenuItemData = object>(items
|
|
|
1348
1348
|
export declare function getTimezoneById(id: string | undefined): ITimezoneItem | undefined;
|
|
1349
1349
|
|
|
1350
1350
|
/**
|
|
1351
|
-
* Returns the display label used by the timezone picker: the friendly name
|
|
1352
|
-
*
|
|
1353
|
-
* for zones outside the curated list, and the offset suffix is dropped when not known.
|
|
1351
|
+
* Returns the display label used by the timezone picker: the friendly name, e.g. "Prague".
|
|
1352
|
+
* The name falls back to the raw IANA ID for zones outside the curated list.
|
|
1354
1353
|
*
|
|
1355
1354
|
* The friendly name (not the IANA ID) is shown so the picker reads the same as the Home UI
|
|
1356
1355
|
* timezone settings — the id-to-name mapping is not visible to users anywhere.
|
|
@@ -6351,7 +6350,7 @@ export declare interface ITimezoneItem {
|
|
|
6351
6350
|
export declare interface ITimezoneSelectButtonRenderProps extends IDropdownButtonRenderProps {
|
|
6352
6351
|
/**
|
|
6353
6352
|
* Human-readable label of the current selection: the matching special item label,
|
|
6354
|
-
* the
|
|
6353
|
+
* the friendly name of the selected timezone (e.g. "Prague"),
|
|
6355
6354
|
* or the placeholder when nothing is selected.
|
|
6356
6355
|
*/
|
|
6357
6356
|
buttonLabel: string;
|
|
@@ -6396,6 +6395,16 @@ export declare interface ITimezoneSelectProps {
|
|
|
6396
6395
|
* Accessibility label of the search input and the listbox.
|
|
6397
6396
|
*/
|
|
6398
6397
|
ariaLabel: string;
|
|
6398
|
+
/**
|
|
6399
|
+
* Id of the default dropdown trigger, so a visible `<label htmlFor>` can be associated
|
|
6400
|
+
* with it. Ignored when a custom trigger is rendered via `renderButton`.
|
|
6401
|
+
*/
|
|
6402
|
+
id?: string;
|
|
6403
|
+
/**
|
|
6404
|
+
* Ids of elements describing the default dropdown trigger (`aria-describedby`), e.g. an
|
|
6405
|
+
* adjacent hint text. Ignored when a custom trigger is rendered via `renderButton`.
|
|
6406
|
+
*/
|
|
6407
|
+
ariaDescribedBy?: string;
|
|
6399
6408
|
/**
|
|
6400
6409
|
* Label shown when the search yields no results.
|
|
6401
6410
|
*/
|
|
@@ -6423,7 +6432,7 @@ export declare interface ITimezoneSelectProps {
|
|
|
6423
6432
|
|
|
6424
6433
|
/**
|
|
6425
6434
|
* Special item rendered above the divider in {@link TimezoneSelect}, ahead of the curated
|
|
6426
|
-
* timezone list. Callers use these for entries like "Default
|
|
6435
|
+
* timezone list. Callers use these for entries like "Default" or "Device time zone".
|
|
6427
6436
|
*
|
|
6428
6437
|
* @internal
|
|
6429
6438
|
*/
|
|
@@ -7783,6 +7792,8 @@ export declare interface IUiGranteeRowControlsProps {
|
|
|
7783
7792
|
disabledLevels?: ReadonlyArray<PermissionMenuLevel>;
|
|
7784
7793
|
/** Tooltip shown on disabled level rows in place of the level's info text. */
|
|
7785
7794
|
disabledTooltip?: string;
|
|
7795
|
+
/** Per-level override of `disabledTooltip` — see {@link UiPermissionMenu}. */
|
|
7796
|
+
disabledLevelTooltips?: Partial<Record<PermissionMenuLevel, string>>;
|
|
7786
7797
|
onLabelsChange: (selectedIds: string[]) => void;
|
|
7787
7798
|
onPermissionChange: (level: PermissionMenuLevel) => void;
|
|
7788
7799
|
onRemoveAccess?: () => void;
|
|
@@ -8643,6 +8654,11 @@ export declare interface IUiPermissionMenuProps {
|
|
|
8643
8654
|
disabledLevels?: ReadonlyArray<PermissionMenuLevel>;
|
|
8644
8655
|
/** Tooltip shown on disabled level rows in place of the level's info text. */
|
|
8645
8656
|
disabledTooltip?: string;
|
|
8657
|
+
/**
|
|
8658
|
+
* Per-level override of `disabledTooltip`, for menus whose disabled levels have
|
|
8659
|
+
* different reasons (capped by the caller's own level vs. already inherited).
|
|
8660
|
+
*/
|
|
8661
|
+
disabledLevelTooltips?: Partial<Record<PermissionMenuLevel, string>>;
|
|
8646
8662
|
/**
|
|
8647
8663
|
* Non-empty enables a labels row that drills into {@link UiLabelsChecklist}
|
|
8648
8664
|
* within the menu — for rows whose menu hosts every action (no "⋯" menu).
|
|
@@ -10615,11 +10631,11 @@ export declare const Timepicker: NamedExoticComponent<ITimepickerOwnProps>;
|
|
|
10615
10631
|
|
|
10616
10632
|
/**
|
|
10617
10633
|
* Searchable dropdown for picking a timezone from the curated list, with optional special
|
|
10618
|
-
* items (e.g. "Default
|
|
10634
|
+
* items (e.g. "Default", "Device time zone") rendered above a divider.
|
|
10619
10635
|
*
|
|
10620
10636
|
* @internal
|
|
10621
10637
|
*/
|
|
10622
|
-
export declare function TimezoneSelect({ value, onChange, specialItems, placeholder, searchPlaceholder, ariaLabel, noMatchLabel, isDisabled, header, showTooltip, renderButton }: ITimezoneSelectProps): ReactElement;
|
|
10638
|
+
export declare function TimezoneSelect({ value, onChange, specialItems, placeholder, searchPlaceholder, ariaLabel, id, ariaDescribedBy, noMatchLabel, isDisabled, header, showTooltip, renderButton }: ITimezoneSelectProps): ReactElement;
|
|
10623
10639
|
|
|
10624
10640
|
/**
|
|
10625
10641
|
* @internal
|
|
@@ -11191,7 +11207,7 @@ export declare function UiGranteeRow({ kind, name, email, isPending, controls, d
|
|
|
11191
11207
|
*
|
|
11192
11208
|
* @internal
|
|
11193
11209
|
*/
|
|
11194
|
-
export declare function UiGranteeRowControls({ labels, selectedLabelIds, permissionLevel, effectivePermission, disabledLevels, disabledTooltip, onLabelsChange, onPermissionChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, isDisabled, dataTestId }: IUiGranteeRowControlsProps): JSX.Element;
|
|
11210
|
+
export declare function UiGranteeRowControls({ labels, selectedLabelIds, permissionLevel, effectivePermission, disabledLevels, disabledTooltip, disabledLevelTooltips, onLabelsChange, onPermissionChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, isDisabled, dataTestId }: IUiGranteeRowControlsProps): JSX.Element;
|
|
11195
11211
|
|
|
11196
11212
|
/**
|
|
11197
11213
|
* @internal
|
|
@@ -11368,7 +11384,7 @@ export declare type UiPaginationButtonSize = "small" | "large";
|
|
|
11368
11384
|
*
|
|
11369
11385
|
* @internal
|
|
11370
11386
|
*/
|
|
11371
|
-
export declare function UiPermissionMenu({ anchor, selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, dataTestId }: IUiPermissionMenuProps): JSX.Element;
|
|
11387
|
+
export declare function UiPermissionMenu({ anchor, selectedLevel, onPermissionChange, disabledLevels, disabledTooltip, disabledLevelTooltips, labels, selectedLabelIds, onLabelsChange, onRemoveAccess, isRemoveDisabled, removeDisabledTooltip, dataTestId }: IUiPermissionMenuProps): JSX.Element;
|
|
11372
11388
|
|
|
11373
11389
|
/**
|
|
11374
11390
|
* @internal
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gooddata/sdk-ui-kit",
|
|
3
|
-
"version": "11.53.0
|
|
3
|
+
"version": "11.53.0",
|
|
4
4
|
"description": "GoodData SDK - UI Building Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "GoodData Corporation",
|
|
@@ -78,11 +78,11 @@
|
|
|
78
78
|
"unified": "^11.0.5",
|
|
79
79
|
"uuid": "11.1.1",
|
|
80
80
|
"yaml": "2.8.3",
|
|
81
|
-
"@gooddata/sdk-
|
|
82
|
-
"@gooddata/sdk-
|
|
83
|
-
"@gooddata/sdk-ui": "11.53.0
|
|
84
|
-
"@gooddata/sdk-ui-theme-provider": "11.53.0
|
|
85
|
-
"@gooddata/util": "11.53.0
|
|
81
|
+
"@gooddata/sdk-backend-spi": "11.53.0",
|
|
82
|
+
"@gooddata/sdk-model": "11.53.0",
|
|
83
|
+
"@gooddata/sdk-ui": "11.53.0",
|
|
84
|
+
"@gooddata/sdk-ui-theme-provider": "11.53.0",
|
|
85
|
+
"@gooddata/util": "11.53.0"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
88
|
"@microsoft/api-documenter": "^7.17.0",
|
|
@@ -131,11 +131,11 @@
|
|
|
131
131
|
"typescript": "5.9.3",
|
|
132
132
|
"vitest": "4.1.8",
|
|
133
133
|
"vitest-dom": "0.1.1",
|
|
134
|
-
"@gooddata/
|
|
135
|
-
"@gooddata/
|
|
136
|
-
"@gooddata/
|
|
137
|
-
"@gooddata/
|
|
138
|
-
"@gooddata/
|
|
134
|
+
"@gooddata/eslint-config": "11.53.0",
|
|
135
|
+
"@gooddata/oxlint-config": "11.53.0",
|
|
136
|
+
"@gooddata/reference-workspace": "11.53.0",
|
|
137
|
+
"@gooddata/sdk-backend-mockingbird": "11.53.0",
|
|
138
|
+
"@gooddata/stylelint-config": "11.53.0"
|
|
139
139
|
},
|
|
140
140
|
"peerDependencies": {
|
|
141
141
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"simpleRecurrenceTypeMappingFn.test.d.ts","sourceRoot":"","sources":["../../../src/RecurrenceForm/utils/simpleRecurrenceTypeMappingFn.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
// (C) 2025-2026 GoodData Corporation
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
3
|
-
import { RECURRENCE_TYPES } from "../constants.js";
|
|
4
|
-
import { simpleRecurrenceTypeMappingFn } from "./simpleRecurrenceTypeMappingFn.js";
|
|
5
|
-
describe("simpleRecurrenceTypeMappingFn", () => {
|
|
6
|
-
it.each([
|
|
7
|
-
// Basic hourly patterns
|
|
8
|
-
["0 0 * ? * *", true, "Monday", RECURRENCE_TYPES.HOURLY, "hourly pattern when allowed"],
|
|
9
|
-
["0 0 * ? * *", false, "Monday", RECURRENCE_TYPES.CRON, "hourly pattern when not allowed"],
|
|
10
|
-
[undefined, true, "Monday", RECURRENCE_TYPES.HOURLY, "default hourly when allowed and no cron"],
|
|
11
|
-
// Basic daily patterns
|
|
12
|
-
["0 0 0 ? * *", false, "Monday", RECURRENCE_TYPES.DAILY, "daily pattern"],
|
|
13
|
-
["0 0 0 ? * *", true, "Monday", RECURRENCE_TYPES.DAILY, "daily pattern with hourly allowed"],
|
|
14
|
-
[
|
|
15
|
-
undefined,
|
|
16
|
-
false,
|
|
17
|
-
"Monday",
|
|
18
|
-
RECURRENCE_TYPES.DAILY,
|
|
19
|
-
"default daily when hourly not allowed and no cron",
|
|
20
|
-
],
|
|
21
|
-
// Weekly patterns - Monday week start
|
|
22
|
-
["0 0 0 ? * 1", false, "Monday", RECURRENCE_TYPES.WEEKLY, "Monday numeric weekly"],
|
|
23
|
-
["0 0 0 ? * MON", false, "Monday", RECURRENCE_TYPES.WEEKLY, "Monday string weekly"],
|
|
24
|
-
["0 0 0 ? * 0", false, "Monday", RECURRENCE_TYPES.CRON, "Sunday with Monday week start"],
|
|
25
|
-
["0 0 0 ? * SUN", false, "Monday", RECURRENCE_TYPES.CRON, "Sunday string with Monday week start"],
|
|
26
|
-
["0 0 0 ? * 2", false, "Monday", RECURRENCE_TYPES.CRON, "Tuesday with Monday week start"],
|
|
27
|
-
// Weekly patterns - Sunday week start
|
|
28
|
-
["0 0 0 ? * 0", false, "Sunday", RECURRENCE_TYPES.WEEKLY, "Sunday numeric weekly"],
|
|
29
|
-
["0 0 0 ? * SUN", false, "Sunday", RECURRENCE_TYPES.WEEKLY, "Sunday string weekly"],
|
|
30
|
-
["0 0 0 ? * 1", false, "Sunday", RECURRENCE_TYPES.CRON, "Monday with Sunday week start"],
|
|
31
|
-
["0 0 0 ? * MON", false, "Sunday", RECURRENCE_TYPES.CRON, "Monday string with Sunday week start"],
|
|
32
|
-
// Weekly patterns - undefined week start (defaults to Monday)
|
|
33
|
-
[
|
|
34
|
-
"0 0 0 ? * 1",
|
|
35
|
-
false,
|
|
36
|
-
undefined,
|
|
37
|
-
RECURRENCE_TYPES.WEEKLY,
|
|
38
|
-
"Monday numeric with undefined week start",
|
|
39
|
-
],
|
|
40
|
-
[
|
|
41
|
-
"0 0 0 ? * MON",
|
|
42
|
-
false,
|
|
43
|
-
undefined,
|
|
44
|
-
RECURRENCE_TYPES.WEEKLY,
|
|
45
|
-
"Monday string with undefined week start",
|
|
46
|
-
],
|
|
47
|
-
// Monthly patterns
|
|
48
|
-
["0 0 0 1 * *", false, "Monday", RECURRENCE_TYPES.MONTHLY, "monthly pattern"],
|
|
49
|
-
["0 0 0 1 * *", true, "Monday", RECURRENCE_TYPES.MONTHLY, "monthly pattern with hourly allowed"],
|
|
50
|
-
// Custom/complex cron patterns
|
|
51
|
-
["0 30 10 ? * MON-FRI", false, "Monday", RECURRENCE_TYPES.CRON, "complex business days pattern"],
|
|
52
|
-
["0 15 8 ? * TUE", false, "Monday", RECURRENCE_TYPES.CRON, "Tuesday at specific time"],
|
|
53
|
-
["0 0 8 ? * MON#1", false, "Monday", RECURRENCE_TYPES.CRON, "first Monday of month pattern"],
|
|
54
|
-
["0 30 14 ? * MON-FRI", false, "Monday", RECURRENCE_TYPES.CRON, "complex pattern"],
|
|
55
|
-
// Invalid/edge cases
|
|
56
|
-
["invalid cron", false, "Monday", RECURRENCE_TYPES.CRON, "invalid cron expression"],
|
|
57
|
-
["", false, "Monday", RECURRENCE_TYPES.CRON, "empty string"],
|
|
58
|
-
[" ", false, "Monday", RECURRENCE_TYPES.CRON, "whitespace-only string"],
|
|
59
|
-
[null, false, "Monday", RECURRENCE_TYPES.DAILY, "null cron expression"],
|
|
60
|
-
])("should return %s for cron '%s' with allowHourly=%s, weekStart=%s (%s)", (cronExpression, allowHourly, weekStart, expectedType, _description) => {
|
|
61
|
-
const result = simpleRecurrenceTypeMappingFn(undefined, // Date parameter is not used, so we can pass undefined
|
|
62
|
-
cronExpression, allowHourly, false, weekStart);
|
|
63
|
-
expect(result).toBe(expectedType);
|
|
64
|
-
});
|
|
65
|
-
// Test demonstrating that the date parameter is indeed optional and not used
|
|
66
|
-
it("should work the same regardless of date parameter", () => {
|
|
67
|
-
const cronExpression = "0 0 0 ? * *";
|
|
68
|
-
const allowHourly = false;
|
|
69
|
-
const weekStart = "Monday";
|
|
70
|
-
const resultWithDate = simpleRecurrenceTypeMappingFn(new Date("2024-01-15T10:30:00"), cronExpression, allowHourly, false, weekStart);
|
|
71
|
-
const resultWithoutDate = simpleRecurrenceTypeMappingFn(undefined, cronExpression, allowHourly, false, weekStart);
|
|
72
|
-
const resultWithNull = simpleRecurrenceTypeMappingFn(null, cronExpression, allowHourly, false, weekStart);
|
|
73
|
-
expect(resultWithDate).toBe(RECURRENCE_TYPES.DAILY);
|
|
74
|
-
expect(resultWithoutDate).toBe(RECURRENCE_TYPES.DAILY);
|
|
75
|
-
expect(resultWithNull).toBe(RECURRENCE_TYPES.DAILY);
|
|
76
|
-
expect(resultWithDate).toBe(resultWithoutDate);
|
|
77
|
-
expect(resultWithoutDate).toBe(resultWithNull);
|
|
78
|
-
});
|
|
79
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../../src/RecurrenceForm/utils/utils.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
// (C) 2024-2026 GoodData Corporation
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
3
|
-
import { createIntlMock } from "@gooddata/sdk-ui";
|
|
4
|
-
import { RECURRENCE_TYPES } from "../constants.js";
|
|
5
|
-
import { constructCronExpression, isLastOccurrenceOfWeekdayInMonth, transformCronExpressionToRecurrenceType, transformRecurrenceTypeToDescription, } from "./utils.js";
|
|
6
|
-
const sampleCronExp = "0 0 1 ? * 2";
|
|
7
|
-
const sampleDate = new Date("2023-04-05T14:34:21");
|
|
8
|
-
const sampleDate2 = new Date("2023-04-13T15:34:21");
|
|
9
|
-
const sampleDate3 = new Date("2023-04-18T16:34:21");
|
|
10
|
-
const sampleDate4 = new Date("2023-03-24T12:34:21");
|
|
11
|
-
const sampleDate5 = new Date("2023-04-24T17:34:21");
|
|
12
|
-
const sampleDate6 = new Date("2023-04-30T18:34:21");
|
|
13
|
-
describe("isLastOccurrenceOfWeekdayInMonth", () => {
|
|
14
|
-
it.each([
|
|
15
|
-
[true, new Date("2023-04-30"), "5th Sunday of April 2023, last because April 2023 has 5 Sundays"],
|
|
16
|
-
[
|
|
17
|
-
false,
|
|
18
|
-
new Date("2023-04-02"),
|
|
19
|
-
"1st Sunday of April 2023, not last because April 2023 has 5 Sundays",
|
|
20
|
-
],
|
|
21
|
-
[true, new Date("2023-07-28"), "4th Friday of July 2023, last because July 2023 has 4 Fridays"],
|
|
22
|
-
[
|
|
23
|
-
true,
|
|
24
|
-
new Date("2024-02-25"),
|
|
25
|
-
"4th Sunday of February 2024, last because February 2024 has 4 Sundays (leap year)",
|
|
26
|
-
],
|
|
27
|
-
[true, new Date("2023-05-25"), "4th Thursday of May 2023, last because May 2023 has 4 Thursdays"],
|
|
28
|
-
[true, new Date("2023-05-31"), "5th Wednesday of May 2023, last because May 2023 has 5 Wednesdays"],
|
|
29
|
-
[
|
|
30
|
-
true,
|
|
31
|
-
new Date("2023-12-28"),
|
|
32
|
-
"4th Thursday of December 2023, last because December 2023 has 4 Thursdays",
|
|
33
|
-
],
|
|
34
|
-
[
|
|
35
|
-
true,
|
|
36
|
-
new Date("2023-12-31"),
|
|
37
|
-
"5th Sunday of December 2023, last because December 2023 has 5 Sundays",
|
|
38
|
-
],
|
|
39
|
-
[
|
|
40
|
-
true,
|
|
41
|
-
new Date("2023-09-28"),
|
|
42
|
-
"4th Thursday of September 2023, last because September 2023 has 4 Thursdays",
|
|
43
|
-
],
|
|
44
|
-
[
|
|
45
|
-
false,
|
|
46
|
-
new Date("2023-09-21"),
|
|
47
|
-
"3rd Thursday of September 2023, not last because September 2023 has 4 Thursdays",
|
|
48
|
-
],
|
|
49
|
-
[
|
|
50
|
-
true,
|
|
51
|
-
new Date("2023-02-22"),
|
|
52
|
-
"4th Wednesday of February 2023, last because February 2023 has 4 Wednesdays",
|
|
53
|
-
],
|
|
54
|
-
[
|
|
55
|
-
false,
|
|
56
|
-
new Date("2023-02-15"),
|
|
57
|
-
"3rd Wednesday of February 2023, not last because February 2023 has 4 Wednesdays",
|
|
58
|
-
],
|
|
59
|
-
])("should return %s for %s", (expectedResult, date) => {
|
|
60
|
-
expect(isLastOccurrenceOfWeekdayInMonth(date)).toBe(expectedResult);
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
describe("constructCronExpression with date", () => {
|
|
64
|
-
it.each([
|
|
65
|
-
["hourly", sampleDate, sampleCronExp, "0 0 * ? * *", "every hour"],
|
|
66
|
-
["daily", sampleDate, sampleCronExp, "0 0 14 ? * *", "every day at the same time"],
|
|
67
|
-
["weekly", sampleDate, sampleCronExp, "0 0 14 ? * WED", "every week at the same day and time"],
|
|
68
|
-
["monthly", sampleDate, sampleCronExp, "0 0 14 ? * WED#1", "every month on the first wednesday"],
|
|
69
|
-
["monthly", sampleDate2, sampleCronExp, "0 0 15 ? * THU#2", "every month on the second thursday"],
|
|
70
|
-
["monthly", sampleDate3, sampleCronExp, "0 0 16 ? * TUE#3", "every month on the third tuesday"],
|
|
71
|
-
["monthly", sampleDate4, sampleCronExp, "0 0 12 ? * FRI#4", "every month on the fourth friday"],
|
|
72
|
-
["monthly", sampleDate5, sampleCronExp, "0 0 17 ? * MONL", "every month on the last (fourth) monday"],
|
|
73
|
-
["monthly", sampleDate6, sampleCronExp, "0 0 18 ? * SUNL", "every month on the last (fifth) sunday"],
|
|
74
|
-
["cron", sampleDate, sampleCronExp, sampleCronExp, "provided cron expression"],
|
|
75
|
-
])("should transform date and recurrence type to %s expression", (recurrenceType, date, defaultCronExpression, expectedCronExpression, _description) => {
|
|
76
|
-
expect(constructCronExpression(date, recurrenceType, defaultCronExpression, "Monday")).toEqual(expectedCronExpression);
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
describe("constructCronExpression without date, default Monday", () => {
|
|
80
|
-
it.each([
|
|
81
|
-
["hourly", sampleCronExp, "0 0 * ? * *", "every hour"],
|
|
82
|
-
["daily", sampleCronExp, "0 0 0 ? * *", "every day at the same time"],
|
|
83
|
-
["weekly", sampleCronExp, "0 0 0 ? * MON", "every week at the same day and time"],
|
|
84
|
-
["monthly", sampleCronExp, "0 0 0 1 * *", "every month at first day"],
|
|
85
|
-
["cron", sampleCronExp, sampleCronExp, "provided cron expression"],
|
|
86
|
-
])("should transform date and recurrence type to %s expression", (recurrenceType, defaultCronExpression, expectedCronExpression, _description) => {
|
|
87
|
-
expect(constructCronExpression(null, recurrenceType, defaultCronExpression, "Monday")).toEqual(expectedCronExpression);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
describe("constructCronExpression without date, default Sunday", () => {
|
|
91
|
-
it.each([
|
|
92
|
-
["hourly", sampleCronExp, "0 0 * ? * *", "every hour"],
|
|
93
|
-
["daily", sampleCronExp, "0 0 0 ? * *", "every day at the same time"],
|
|
94
|
-
["weekly", sampleCronExp, "0 0 0 ? * SUN", "every week at the same day and time"],
|
|
95
|
-
["monthly", sampleCronExp, "0 0 0 1 * *", "every month at first day"],
|
|
96
|
-
["cron", sampleCronExp, sampleCronExp, "provided cron expression"],
|
|
97
|
-
])("should transform date and recurrence type to %s expression", (recurrenceType, defaultCronExpression, expectedCronExpression, _description) => {
|
|
98
|
-
expect(constructCronExpression(null, recurrenceType, defaultCronExpression, "Sunday")).toEqual(expectedCronExpression);
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
describe("transformCronExpressionToRecurrenceType with date", () => {
|
|
102
|
-
const universal = new Date();
|
|
103
|
-
const D2024_01_01_01 = new Date(2024, 0, 1, 1, 0, 0);
|
|
104
|
-
const D2024_01_01_09 = new Date(2024, 0, 1, 9, 0, 0);
|
|
105
|
-
const D2024_01_01_18 = new Date(2024, 0, 1, 18, 0, 0);
|
|
106
|
-
const D2024_01_07_01 = new Date(2024, 0, 7, 1, 0, 0);
|
|
107
|
-
const D2024_01_08_09 = new Date(2024, 0, 8, 9, 0, 0);
|
|
108
|
-
const D2024_01_09_12 = new Date(2024, 0, 9, 12, 0, 0);
|
|
109
|
-
const D2024_01_12_18 = new Date(2024, 0, 12, 18, 0, 0);
|
|
110
|
-
const D2024_01_13_23 = new Date(2024, 0, 13, 23, 0, 0);
|
|
111
|
-
const D2024_01_01_15 = new Date(2024, 0, 1, 15, 0, 0);
|
|
112
|
-
const D2024_01_05_15 = new Date(2024, 0, 5, 15, 0, 0);
|
|
113
|
-
const D2024_01_09_15 = new Date(2024, 0, 9, 15, 0, 0);
|
|
114
|
-
const D2024_01_17_15 = new Date(2024, 0, 17, 15, 0, 0);
|
|
115
|
-
const D2024_01_25_15 = new Date(2024, 0, 25, 15, 0, 0);
|
|
116
|
-
it.each([
|
|
117
|
-
["0 0 * ? * *", true, false, universal, "hourly"],
|
|
118
|
-
["0 0 * ? * *", false, false, universal, "cron"],
|
|
119
|
-
["0 0 1 ? * *", true, false, D2024_01_01_01, "daily"],
|
|
120
|
-
["0 0 9 ? * *", true, false, D2024_01_01_09, "daily"],
|
|
121
|
-
["0 0 18 ? * *", true, false, D2024_01_01_18, "daily"],
|
|
122
|
-
["0 0 10 ? * *", true, false, D2024_01_01_18, "cron"],
|
|
123
|
-
["0 0 1 ? * SUN", true, false, D2024_01_07_01, "weekly"],
|
|
124
|
-
["0 0 9 ? * MON", true, false, D2024_01_08_09, "weekly"],
|
|
125
|
-
["0 0 12 ? * TUE", true, false, D2024_01_09_12, "weekly"],
|
|
126
|
-
["0 0 18 ? * FRI", true, false, D2024_01_12_18, "weekly"],
|
|
127
|
-
["0 0 23 ? * SAT", true, false, D2024_01_13_23, "weekly"],
|
|
128
|
-
["0 0 23 ? * FRI", true, false, D2024_01_13_23, "cron"],
|
|
129
|
-
["0 0 10 ? * SAT", true, false, D2024_01_13_23, "cron"],
|
|
130
|
-
["0 0 15 ? * MON#1", true, false, D2024_01_01_15, "monthly", "every first monday"],
|
|
131
|
-
["0 0 15 ? * FRI#1", true, false, D2024_01_05_15, "monthly", "every first friday"],
|
|
132
|
-
["0 0 15 ? * TUE#2", true, false, D2024_01_09_15, "monthly", "every second tuesday"],
|
|
133
|
-
["0 0 15 ? * WED#3", true, false, D2024_01_17_15, "monthly", "every third wednesday"],
|
|
134
|
-
["0 0 15 ? * THUL", true, false, D2024_01_25_15, "monthly", "every last (fourth) thursday"],
|
|
135
|
-
["0 0 15 ? * THU#5", true, false, D2024_01_25_15, "cron"],
|
|
136
|
-
["0 0 8 ? * TUE#2", true, false, D2024_01_09_15, "cron"],
|
|
137
|
-
["* * * * * *", true, false, universal, "cron"],
|
|
138
|
-
["* * * ? * *", true, false, universal, "cron"],
|
|
139
|
-
["1 1 1 1 1 1", true, false, universal, "cron"],
|
|
140
|
-
["1 1 1 ? 1 1", true, false, universal, "cron"],
|
|
141
|
-
["0 0 1 ? * 5", true, false, universal, "cron"],
|
|
142
|
-
["0 0 1 ? JAN SUN", true, false, universal, "cron"],
|
|
143
|
-
["0 0 1 ? * 1-3", true, false, universal, "cron"],
|
|
144
|
-
["0 0 1 ? * 1,2", true, false, universal, "cron"],
|
|
145
|
-
["0 0 1 ? * 1/2", true, false, universal, "cron"],
|
|
146
|
-
["0 0 0 1 * *", true, false, universal, "cron"],
|
|
147
|
-
["", true, true, universal, "inherit"],
|
|
148
|
-
["", true, true, undefined, "inherit"],
|
|
149
|
-
[undefined, true, true, undefined, "inherit"],
|
|
150
|
-
[undefined, true, false, undefined, "cron"],
|
|
151
|
-
])("should correctly identify %s with hourly %s and date %s as %s", ((cronExpression, allowHourly, allowInherit, date, expected) => {
|
|
152
|
-
expect(transformCronExpressionToRecurrenceType(date ?? null, cronExpression, allowHourly, allowInherit, "Monday")).toEqual(expected);
|
|
153
|
-
}));
|
|
154
|
-
});
|
|
155
|
-
describe("transformCronExpressionToRecurrenceType without date, default Monday", () => {
|
|
156
|
-
it.each([
|
|
157
|
-
["0 0 * ? * *", true, false, "hourly"],
|
|
158
|
-
["0 0 * ? * *", false, false, "cron"],
|
|
159
|
-
["0 0 1 ? * *", true, false, "daily"],
|
|
160
|
-
["0 0 9 ? * *", true, false, "daily"],
|
|
161
|
-
["0 0 18 ? * *", true, false, "daily"],
|
|
162
|
-
["0 0 10 ? * *", true, false, "daily"],
|
|
163
|
-
["0 0 1 ? * SUN", true, false, "weekly"],
|
|
164
|
-
["0 0 9 ? * MON", true, false, "weekly"],
|
|
165
|
-
["0 0 12 ? * TUE", true, false, "weekly"],
|
|
166
|
-
["0 0 18 ? * FRI", true, false, "weekly"],
|
|
167
|
-
["0 0 23 ? * SAT", true, false, "weekly"],
|
|
168
|
-
["0 0 23 ? * FRI", true, false, "weekly"],
|
|
169
|
-
["0 0 10 ? * SAT", true, false, "weekly"],
|
|
170
|
-
["0 0 15 ? * MON#1", true, false, "monthly", "every first monday"],
|
|
171
|
-
["0 0 15 ? * FRI#1", true, false, "monthly", "every first friday"],
|
|
172
|
-
["0 0 15 ? * TUE#2", true, false, "monthly", "every second tuesday"],
|
|
173
|
-
["0 0 15 ? * WED#3", true, false, "monthly", "every third wednesday"],
|
|
174
|
-
["0 0 15 ? * THUL", true, false, "monthly", "every last (fourth) thursday"],
|
|
175
|
-
["0 0 15 ? * THU#5", true, false, "monthly"],
|
|
176
|
-
["0 0 8 ? * TUE#2", true, false, "monthly"],
|
|
177
|
-
["0 0 0 1 * *", true, false, "monthly"],
|
|
178
|
-
["* * * * * *", true, false, "cron"],
|
|
179
|
-
["* * * ? * *", true, false, "cron"],
|
|
180
|
-
["1 1 1 1 1 1", true, false, "cron"],
|
|
181
|
-
["1 1 1 ? 1 1", true, false, "cron"],
|
|
182
|
-
["0 0 1 ? * 5", true, false, "cron"],
|
|
183
|
-
["0 0 1 ? JAN SUN", true, false, "cron"],
|
|
184
|
-
["0 0 1 ? * 1-3", true, false, "cron"],
|
|
185
|
-
["0 0 1 ? * 1,2", true, false, "cron"],
|
|
186
|
-
["0 0 1 ? * 1/2", true, false, "cron"],
|
|
187
|
-
["0 0 1 ? * 1/2", true, false, "cron"],
|
|
188
|
-
["", true, true, "inherit"],
|
|
189
|
-
["", true, true, "inherit"],
|
|
190
|
-
[undefined, true, true, "inherit"],
|
|
191
|
-
[undefined, true, false, "cron"],
|
|
192
|
-
])("should correctly identify %s with hourly %s as %s", ((cronExpression, allowHourly, allowInherit, expected) => {
|
|
193
|
-
expect(transformCronExpressionToRecurrenceType(null, cronExpression, allowHourly, allowInherit, "Monday")).toEqual(expected);
|
|
194
|
-
}));
|
|
195
|
-
});
|
|
196
|
-
describe("transformRecurrenceTypeToDescription", () => {
|
|
197
|
-
const intl = createIntlMock();
|
|
198
|
-
const d1 = new Date(2024, 7, 13, 22, 0, 0);
|
|
199
|
-
it.each([
|
|
200
|
-
[RECURRENCE_TYPES.HOURLY, null, "Monday", "At start of every hour"],
|
|
201
|
-
[RECURRENCE_TYPES.HOURLY, null, "Sunday", "At start of every hour"],
|
|
202
|
-
[RECURRENCE_TYPES.DAILY, null, "Monday", "At 12 AM every day"],
|
|
203
|
-
[RECURRENCE_TYPES.DAILY, null, "Sunday", "At 12 AM every day"],
|
|
204
|
-
[RECURRENCE_TYPES.WEEKLY, null, "Monday", "At 12 AM every week start"],
|
|
205
|
-
[RECURRENCE_TYPES.WEEKLY, null, "Sunday", "At 12 AM every week start"],
|
|
206
|
-
[RECURRENCE_TYPES.MONTHLY, null, "Monday", "At 12 AM every month start"],
|
|
207
|
-
[RECURRENCE_TYPES.MONTHLY, null, "Sunday", "At 12 AM every month start"],
|
|
208
|
-
[RECURRENCE_TYPES.CRON, null, "Monday", ""],
|
|
209
|
-
[RECURRENCE_TYPES.CRON, null, "Sunday", ""],
|
|
210
|
-
[RECURRENCE_TYPES.HOURLY, d1, "Monday", "At start of every hour"],
|
|
211
|
-
[RECURRENCE_TYPES.HOURLY, d1, "Sunday", "At start of every hour"],
|
|
212
|
-
[RECURRENCE_TYPES.DAILY, d1, "Monday", "At 10 PM every day"],
|
|
213
|
-
[RECURRENCE_TYPES.DAILY, d1, "Sunday", "At 10 PM every day"],
|
|
214
|
-
[RECURRENCE_TYPES.WEEKLY, d1, "Monday", "At 10 PM on Tuesday every week"],
|
|
215
|
-
[RECURRENCE_TYPES.WEEKLY, d1, "Sunday", "At 10 PM on Tuesday every week"],
|
|
216
|
-
[RECURRENCE_TYPES.MONTHLY, d1, "Monday", "At 10 PM on Tuesday every 2. week in month"],
|
|
217
|
-
[RECURRENCE_TYPES.MONTHLY, d1, "Sunday", "At 10 PM on Tuesday every 2. week in month"],
|
|
218
|
-
[RECURRENCE_TYPES.CRON, d1, "Monday", ""],
|
|
219
|
-
[RECURRENCE_TYPES.CRON, d1, "Sunday", ""],
|
|
220
|
-
[RECURRENCE_TYPES.INHERIT, d1, "Sunday", ""],
|
|
221
|
-
])("should correctly describe %s", ((recurrenceType, date, weekStart, expected) => {
|
|
222
|
-
expect(transformRecurrenceTypeToDescription(intl, recurrenceType, date, weekStart)).toEqual(expected);
|
|
223
|
-
}));
|
|
224
|
-
});
|