@gooddata/sdk-ui-dashboard 11.53.0-alpha.1 → 11.53.0-alpha.2
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/__version.d.ts +1 -1
- package/esm/__version.js +1 -1
- package/esm/index.d.ts +3 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/internal.d.ts +1 -1
- package/esm/internal.d.ts.map +1 -1
- package/esm/model/commandHandlers/dashboard/saveDashboardHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/dashboard/saveDashboardHandler.js +43 -8
- package/esm/model/react/useInitializeDashboardStore.d.ts.map +1 -1
- package/esm/model/react/useInitializeDashboardStore.js +11 -0
- package/esm/model/store/config/configReducers.d.ts +8 -0
- package/esm/model/store/config/configReducers.d.ts.map +1 -1
- package/esm/model/store/config/configReducers.js +12 -0
- package/esm/model/store/config/index.d.ts +2 -0
- package/esm/model/store/config/index.d.ts.map +1 -1
- package/esm/model/store/dashboardStore.d.ts.map +1 -1
- package/esm/model/store/dashboardStore.js +1 -0
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogHeader.d.ts +1 -11
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogHeader.d.ts.map +1 -1
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/AlertingDialogHeader.js +7 -11
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/DefaultAlertingDialog.d.ts +6 -3
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/DefaultAlertingDialog.d.ts.map +1 -1
- package/esm/presentation/automations/alerting/DefaultAlertingDialog/DefaultAlertingDialog.js +22 -4
- package/esm/presentation/automations/alerting/state/useAlertFormState.d.ts +1 -1
- package/esm/presentation/automations/alerting/state/useAlertFormState.d.ts.map +1 -1
- package/esm/presentation/automations/alerting/state/useAlertFormState.js +3 -2
- package/esm/presentation/automations/alerting/types.d.ts +51 -1
- package/esm/presentation/automations/alerting/types.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.d.ts +23 -3
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.js +40 -4
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/Header/ScheduleEmailDialogHeader.d.ts +1 -12
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/Header/ScheduleEmailDialogHeader.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/Header/ScheduleEmailDialogHeader.js +10 -14
- package/esm/presentation/automations/scheduledEmail/state/useScheduledEmailFormState.d.ts +1 -1
- package/esm/presentation/automations/scheduledEmail/state/useScheduledEmailFormState.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/state/useScheduledEmailFormState.js +3 -2
- package/esm/presentation/automations/scheduledEmail/types.d.ts +55 -1
- package/esm/presentation/automations/scheduledEmail/types.d.ts.map +1 -1
- package/esm/presentation/automations/shared/automationFilters/components/AutomationParameter.d.ts.map +1 -1
- package/esm/presentation/automations/shared/automationFilters/components/AutomationParameter.js +2 -2
- package/esm/presentation/automations/shared/slots/types.d.ts +58 -0
- package/esm/presentation/automations/shared/slots/types.d.ts.map +1 -0
- package/esm/presentation/automations/shared/slots/types.js +2 -0
- package/esm/presentation/automations/shared/utils/automationTitle.d.ts +5 -0
- package/esm/presentation/automations/shared/utils/automationTitle.d.ts.map +1 -0
- package/esm/presentation/automations/shared/utils/automationTitle.js +7 -0
- package/esm/presentation/dragAndDrop/draggableParameterFilter/DefaultParameterDraggingComponent.d.ts.map +1 -1
- package/esm/presentation/dragAndDrop/draggableParameterFilter/DefaultParameterDraggingComponent.js +9 -2
- package/esm/presentation/filterBar/filterBar/DefaultFilterBarContainer.d.ts.map +1 -1
- package/esm/presentation/filterBar/filterBar/DefaultFilterBarContainer.js +8 -2
- package/esm/presentation/filterBar/parameterFilter/DashboardParameterFilter.d.ts.map +1 -1
- package/esm/presentation/filterBar/parameterFilter/DashboardParameterFilter.js +4 -3
- package/esm/sdk-ui-dashboard.d.ts +195 -2
- package/package.json +21 -21
- package/styles/css/main.css +62 -0
- package/styles/css/main.css.map +1 -1
package/esm/presentation/automations/alerting/DefaultAlertingDialog/DefaultAlertingDialog.js
CHANGED
|
@@ -41,7 +41,8 @@ import { isMobileView } from "./utils/responsive.js";
|
|
|
41
41
|
const OVERLAY_POSITION_TYPE = "sameAsTarget";
|
|
42
42
|
const CLOSE_ON_PARENT_SCROLL = true;
|
|
43
43
|
const overlayController = OverlayController.getInstance(DASHBOARD_DIALOG_OVERS_Z_INDEX);
|
|
44
|
-
export function AlertingDialogRenderer({ onCancel, onDeleteSuccess, onDeleteError, onError, onSuccess, onSaveError, onSaveSuccess, }) {
|
|
44
|
+
export function AlertingDialogRenderer({ onCancel, onDeleteSuccess, onDeleteError, onError, onSuccess, onSaveError, onSaveSuccess, slots, }) {
|
|
45
|
+
const HeaderSlot = slots?.Header;
|
|
45
46
|
const intl = useIntl();
|
|
46
47
|
const dialogTitleRef = useRef(null);
|
|
47
48
|
const { isWhiteLabeled, isSecondaryTitleVisible, externalRecipient: externalRecipientOverride, maxAutomationsRecipients, isExecutionTimestampMode, features: { enableAlertOncePerInterval, enableAnomalyDetectionAlert, canUseAiAssistant: enableAiAssistant, }, catalogAttributes, catalogDateDatasets, separators, allowHourlyRecurrence, } = useAutomationsContext();
|
|
@@ -128,9 +129,23 @@ export function AlertingDialogRenderer({ onCancel, onDeleteSuccess, onDeleteErro
|
|
|
128
129
|
? intl.formatMessage({
|
|
129
130
|
id: "dialogs.alert.save.executionTimestampMode",
|
|
130
131
|
})
|
|
131
|
-
: undefined, initialFocus: dialogTitleRef, submitOnEnterKey: false, onCancel: onCancel, onSubmit: () => void submit(), headline: undefined, headerLeftButtonRenderer: () =>
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
: undefined, initialFocus: dialogTitleRef, submitOnEnterKey: false, onCancel: onCancel, onSubmit: () => void submit(), headline: undefined, headerLeftButtonRenderer: () => {
|
|
133
|
+
const headerDefaultProps = {
|
|
134
|
+
title: editedAutomation?.title ?? "",
|
|
135
|
+
onChange: onTitleChange,
|
|
136
|
+
onCancel,
|
|
137
|
+
placeholder: intl.formatMessage({
|
|
138
|
+
id: "dialogs.alert.title.placeholder",
|
|
139
|
+
}),
|
|
140
|
+
ref: dialogTitleRef,
|
|
141
|
+
secondaryTitle,
|
|
142
|
+
secondaryTitleIcon,
|
|
143
|
+
isSecondaryTitleVisible: isSecondaryTitleVisible
|
|
144
|
+
? isParentValid
|
|
145
|
+
: undefined,
|
|
146
|
+
};
|
|
147
|
+
return HeaderSlot ? (_jsx(HeaderSlot, { Default: AlertingDialogHeader, defaultProps: headerDefaultProps })) : (_jsx(AlertingDialogHeader, { ...headerDefaultProps }));
|
|
148
|
+
}, children: [
|
|
134
149
|
_jsx("h2", { className: "sr-only", id: titleElementId, children: intl.formatMessage({ id: "dialogs.alert.accessibility.label.title" }) }), _jsxs(ScrollablePanel, { className: "gd-notifications-channel-dialog-content-wrapper gd-notification-channel-dialog-with-automation-filters", children: [
|
|
135
150
|
_jsx("div", { className: "gd-divider-with-margin" }), _jsxs(_Fragment, { children: [
|
|
136
151
|
_jsx(AutomationFiltersSelect, { availableFilters: availableFilters, selectedFilters: selectedFilters, onFiltersChange: onFiltersChange, storeFilters: true, onStoreFiltersChange: () => { }, isDashboardAutomation: false, overlayPositionType: OVERLAY_POSITION_TYPE, disableDateFilters: isAnomalyDetection(editedAutomation?.alert), parameters: automationParameters, onParameterChange: onParameterChange, onParameterDelete: onParameterDelete, availableParameters: availableParameters, onParameterAdd: onParameterAdd }), _jsx(ContentDivider, { className: "gd-divider-with-margin" })
|
|
@@ -174,6 +189,9 @@ export function AlertingDialogRenderer({ onCancel, onDeleteSuccess, onDeleteErro
|
|
|
174
189
|
* that is what lets a wholesale replacement receive the same contexts. Rendering this component
|
|
175
190
|
* outside those providers throws at runtime.
|
|
176
191
|
*
|
|
192
|
+
* Slots render only in the fully rendered dialog: not while the dialog context reports loading,
|
|
193
|
+
* and not while the stale-filters confirmation step is shown.
|
|
194
|
+
*
|
|
177
195
|
* @alpha
|
|
178
196
|
*/
|
|
179
197
|
export function DefaultAlertingDialog(props) {
|
|
@@ -40,7 +40,7 @@ export declare function useAlertFormState({ alertToEdit, insight, widget, notifi
|
|
|
40
40
|
onParameterDelete: (ref: import("@gooddata/sdk-model").IdentifierRef) => void;
|
|
41
41
|
onParameterAdd: (ref: import("@gooddata/sdk-model").IdentifierRef) => void;
|
|
42
42
|
dropStaleParameters: () => void;
|
|
43
|
-
onTitleChange: (value: string
|
|
43
|
+
onTitleChange: (value: string) => void;
|
|
44
44
|
onMeasureChange: (measure: AlertMetric) => void;
|
|
45
45
|
onAttributeChange: (attribute: AlertAttribute | undefined, value: {
|
|
46
46
|
title: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAlertFormState.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/alerting/state/useAlertFormState.ts"],"names":[],"mappings":"AAMA,OAAO,EACH,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,iCAAiC,EACtC,KAAK,iCAAiC,EACtC,KAAK,wBAAwB,EAC7B,KAAK,gCAAgC,EACrC,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,mCAAmC,EACxC,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,QAAQ,EAEb,KAAK,8BAA8B,EACnC,KAAK,kCAAkC,EACvC,KAAK,OAAO,EACf,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"useAlertFormState.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/alerting/state/useAlertFormState.ts"],"names":[],"mappings":"AAMA,OAAO,EACH,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,iCAAiC,EACtC,KAAK,iCAAiC,EACtC,KAAK,wBAAwB,EAC7B,KAAK,gCAAgC,EACrC,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,mCAAmC,EACxC,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,QAAQ,EAEb,KAAK,8BAA8B,EACnC,KAAK,kCAAkC,EACvC,KAAK,OAAO,EACf,MAAM,qBAAqB,CAAC;AAiB7B,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AAWnF,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAEpG;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACpC,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACxC,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oBAAoB,EAAE,8BAA8B,EAAE,GAAG,kCAAkC,EAAE,CAAC;IAC9F,uBAAuB,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC9C,gCAAgC,CAAC,EAAE,wBAAwB,EAAE,GAAG,SAAS,CAAC;IAC1E,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,iBAAiB,EAAE,WAAW,EAAE,CAAC;IACjC,mBAAmB,EAAE,cAAc,EAAE,CAAC;IACtC,gBAAgB,EAAE,iBAAiB,CAAC;CACvC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,EAC9B,WAAW,EACX,OAAO,EACP,MAAM,EACN,oBAAoB,EACpB,uBAAuB,EACvB,gCAAgC,EAChC,yBAAyB,EACzB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EACnB,EAAE,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwZzB"}
|
|
@@ -6,6 +6,7 @@ import { useAutomationsContext } from "../../contexts/AutomationsContext.js";
|
|
|
6
6
|
import { setAlertExecutionParameters } from "../../shared/automationFilters/automationParameters.js";
|
|
7
7
|
import { useAutomationAlertParameters } from "../../shared/automationFilters/useAutomationAlertParameters.js";
|
|
8
8
|
import { getAppliedWidgetFilters, getVisibleFiltersByFilters, resolveFilterDimensionalityLocalRefs, } from "../../shared/filters/index.js";
|
|
9
|
+
import { isAutomationTitleValid } from "../../shared/utils/automationTitle.js";
|
|
9
10
|
import { convertExternalRecipientToAutomationRecipient, convertUserToAutomationRecipient, } from "../../shared/utils/automationUtils.js";
|
|
10
11
|
import { createDefaultAlert } from "../DefaultAlertingDialog/utils/convertors.js";
|
|
11
12
|
import { transformAlertByAnomalyDetection, transformAlertByAttribute, transformAlertByComparisonOperator, transformAlertByDestination, transformAlertByGranularity, transformAlertByMetric, transformAlertByRelativeOperator, transformAlertBySensitivity, } from "../DefaultAlertingDialog/utils/transformation.js";
|
|
@@ -84,8 +85,8 @@ export function useAlertFormState({ alertToEdit, insight, widget, notificationCh
|
|
|
84
85
|
//
|
|
85
86
|
// Handlers
|
|
86
87
|
//
|
|
87
|
-
const onTitleChange = useCallback((value
|
|
88
|
-
setIsTitleValid(
|
|
88
|
+
const onTitleChange = useCallback((value) => {
|
|
89
|
+
setIsTitleValid(isAutomationTitleValid(value));
|
|
89
90
|
setEditedAutomation((s) => (s ? { ...s, title: value } : undefined));
|
|
90
91
|
}, [setEditedAutomation]);
|
|
91
92
|
const onMeasureChange = useCallback((measure) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { type ComponentType } from "react";
|
|
1
|
+
import { type ComponentType, type Ref } from "react";
|
|
2
2
|
import { type DateAttributeGranularity, type IAttribute, type IAutomationMetadataObject, type IDataSetMetadataObject, type IInsight, type IMeasure, type INotificationChannelIdentifier, type INotificationChannelMetadataObject, type IWidget } from "@gooddata/sdk-model";
|
|
3
3
|
import { type GoodDataSdkError } from "@gooddata/sdk-ui";
|
|
4
|
+
import { type IAutomationDialogHeaderProps, type ISlotProps } from "../shared/slots/types.js";
|
|
4
5
|
/**
|
|
5
6
|
* @alpha
|
|
6
7
|
*/
|
|
@@ -72,6 +73,55 @@ export interface IAlertingDialogProps {
|
|
|
72
73
|
*/
|
|
73
74
|
onDeleteError?: (error: GoodDataSdkError) => void;
|
|
74
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Props of the default alerting dialog's header region (the title input row).
|
|
78
|
+
*
|
|
79
|
+
* @alpha
|
|
80
|
+
*/
|
|
81
|
+
export interface IAlertingDialogHeaderProps extends IAutomationDialogHeaderProps {
|
|
82
|
+
/**
|
|
83
|
+
* Called when the header's back/close button is pressed. The default dialog closes on it.
|
|
84
|
+
*/
|
|
85
|
+
onCancel?: () => void;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The exact props the default dialog renders its header with, including the dialog's
|
|
89
|
+
* initial-focus ref.
|
|
90
|
+
*
|
|
91
|
+
* @alpha
|
|
92
|
+
*/
|
|
93
|
+
export type AlertingDialogHeaderDefaultProps = IAlertingDialogHeaderProps & {
|
|
94
|
+
ref?: Ref<HTMLInputElement>;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Section-level overrides of the default alerting dialog.
|
|
98
|
+
*
|
|
99
|
+
* @alpha
|
|
100
|
+
*/
|
|
101
|
+
export interface IAlertingDialogSlots {
|
|
102
|
+
/**
|
|
103
|
+
* Wraps or replaces the dialog header (the title input row). Must have a stable reference
|
|
104
|
+
* identity — see {@link ISlotProps}.
|
|
105
|
+
*/
|
|
106
|
+
Header?: ComponentType<ISlotProps<AlertingDialogHeaderDefaultProps>>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Props of {@link DefaultAlertingDialog}.
|
|
110
|
+
*
|
|
111
|
+
* @remarks
|
|
112
|
+
* Extends the shared {@link IAlertingDialogProps} with customization only the default implementation
|
|
113
|
+
* supports. Slots render only in the fully rendered dialog: not while the dialog context reports
|
|
114
|
+
* loading, and not while the stale-filters confirmation step is shown.
|
|
115
|
+
*
|
|
116
|
+
* @alpha
|
|
117
|
+
*/
|
|
118
|
+
export interface IDefaultAlertingDialogProps extends IAlertingDialogProps {
|
|
119
|
+
/**
|
|
120
|
+
* Section-level overrides. Each slot receives `{ Default, defaultProps }` and may render its own
|
|
121
|
+
* content (replace) or `<Default {...defaultProps} />` inside its own markup (wrap).
|
|
122
|
+
*/
|
|
123
|
+
slots?: IAlertingDialogSlots;
|
|
124
|
+
}
|
|
75
125
|
/**
|
|
76
126
|
* @alpha
|
|
77
127
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/presentation/automations/alerting/types.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/presentation/automations/alerting/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,27 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
export declare function ScheduledMailDialogRenderer({ onBack, onCancel, onDeleteSuccess, onDeleteError, onError, onSave, onSaveError, onSaveSuccess, onSubmit, onSuccess }:
|
|
1
|
+
import { type IDefaultScheduledEmailDialogProps } from "../types.js";
|
|
2
|
+
export declare function ScheduledMailDialogRenderer({ onBack, onCancel, onDeleteSuccess, onDeleteError, onError, onSave, onSaveError, onSaveSuccess, onSubmit, onSuccess, slots }: IDefaultScheduledEmailDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
/**
|
|
4
|
+
* Default implementation of the scheduled export create/edit dialog.
|
|
5
|
+
*
|
|
6
|
+
* This component is a pure consumer of `AutomationsContext`, `ScheduledEmailDialogContext`, and the
|
|
7
|
+
* scheduled export dialog state contexts: it reads org/workspace data, per-dialog state, and the
|
|
8
|
+
* export draft's state from those contexts rather than from the dashboard store. It must therefore
|
|
9
|
+
* be rendered within an `AutomationsContextProvider`, a `ScheduledEmailDialogContextProvider` (for
|
|
10
|
+
* the create/edit flow), and a `ScheduledEmailDialogStateProvider`, whose state model establishes
|
|
11
|
+
* itself once `useScheduledEmailDialogContext().isLoading` is false. Inside a `Dashboard`, the
|
|
12
|
+
* scheduled export connector supplies the first two providers above the
|
|
13
|
+
* `ScheduledEmailDialogComponent` slot and mounts `ScheduledEmailDialogStateProvider` around the
|
|
14
|
+
* resolved slot component — so the default component, and any wholesale slot replacement, inherit
|
|
15
|
+
* all three contexts automatically and require no extra wiring.
|
|
16
|
+
*
|
|
17
|
+
* The providers are intentionally hoisted above the slot rather than built inside this component:
|
|
18
|
+
* that is what lets a wholesale replacement receive the same contexts. Rendering this component
|
|
19
|
+
* outside those providers throws at runtime.
|
|
20
|
+
*
|
|
21
|
+
* Slots render only in the fully rendered dialog: not while the dialog context reports loading,
|
|
22
|
+
* and not while the stale-filters confirmation step is shown.
|
|
23
|
+
*
|
|
4
24
|
* @alpha
|
|
5
25
|
*/
|
|
6
|
-
export declare function DefaultScheduledEmailDialog(props:
|
|
26
|
+
export declare function DefaultScheduledEmailDialog(props: IDefaultScheduledEmailDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
7
27
|
//# sourceMappingURL=DefaultScheduledEmailDialog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultScheduledEmailDialog.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.tsx"],"names":[],"mappings":"AA8CA,OAAO,
|
|
1
|
+
{"version":3,"file":"DefaultScheduledEmailDialog.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/DefaultScheduledEmailDialog.tsx"],"names":[],"mappings":"AA8CA,OAAO,EACH,KAAK,iCAAiC,EAEzC,MAAM,aAAa,CAAC;AA6DrB,wBAAgB,2BAA2B,CAAC,EACxC,MAAM,EACN,QAAQ,EACR,eAAe,EACf,aAAa,EACb,OAAO,EACP,MAAM,EACN,WAAW,EACX,aAAa,EACb,QAAQ,EACR,SAAS,EACT,KAAK,EACR,EAAE,iCAAiC,2CA6gBnC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,iCAAiC,2CAYnF"}
|
|
@@ -41,7 +41,8 @@ function ScheduledEmailDialogFooter({ isWhiteLabeled, helpTextId, scheduledExpor
|
|
|
41
41
|
const intl = useIntl();
|
|
42
42
|
return (_jsxs("div", { className: "gd-notifications-channels-dialog-footer-link", children: [isWhiteLabeled ? null : (_jsx(Hyperlink, { text: intl.formatMessage({ id: helpTextId }), href: "https://www.gooddata.com/docs/cloud/create-dashboards/automation/scheduled-exports/#ScheduleExportsinDashboards-ScheduleExport", iconClass: "gd-icon-circle-question" })), scheduledExportToEdit ? (_jsx(Button, { className: "gd-button-link-dimmed", value: intl.formatMessage({ id: "delete" }), onClick: onDeleteClick, disabled: isSavingScheduledEmail })) : null] }));
|
|
43
43
|
}
|
|
44
|
-
export function ScheduledMailDialogRenderer({ onBack, onCancel, onDeleteSuccess, onDeleteError, onError, onSave, onSaveError, onSaveSuccess, onSubmit, onSuccess, }) {
|
|
44
|
+
export function ScheduledMailDialogRenderer({ onBack, onCancel, onDeleteSuccess, onDeleteError, onError, onSave, onSaveError, onSaveSuccess, onSubmit, onSuccess, slots, }) {
|
|
45
|
+
const HeaderSlot = slots?.Header;
|
|
45
46
|
const intl = useIntl();
|
|
46
47
|
const dialogTitleRef = useRef(null);
|
|
47
48
|
const generalTabContentRef = useRef(null);
|
|
@@ -149,9 +150,24 @@ export function ScheduledMailDialogRenderer({ onBack, onCancel, onDeleteSuccess,
|
|
|
149
150
|
? intl.formatMessage({
|
|
150
151
|
id: "dialogs.schedule.email.save.executionTimestampMode",
|
|
151
152
|
})
|
|
152
|
-
: undefined, initialFocus: dialogTitleRef, submitOnEnterKey: false, onCancel: onCancel, onSubmit: handleSaveScheduledEmail, headline: undefined, headerLeftButtonRenderer: () =>
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
: undefined, initialFocus: dialogTitleRef, submitOnEnterKey: false, onCancel: onCancel, onSubmit: handleSaveScheduledEmail, headline: undefined, headerLeftButtonRenderer: () => {
|
|
154
|
+
const headerDefaultProps = {
|
|
155
|
+
title: editedAutomation.title ?? "",
|
|
156
|
+
onChange: onTitleChange,
|
|
157
|
+
onBack,
|
|
158
|
+
placeholder: intl.formatMessage({
|
|
159
|
+
id: "dialogs.schedule.email.title.placeholder",
|
|
160
|
+
}),
|
|
161
|
+
ref: dialogTitleRef,
|
|
162
|
+
onTitleKeyDown: handleSubmitForm,
|
|
163
|
+
secondaryTitle,
|
|
164
|
+
secondaryTitleIcon,
|
|
165
|
+
isSecondaryTitleVisible: isSecondaryTitleVisible
|
|
166
|
+
? isParentValid
|
|
167
|
+
: undefined,
|
|
168
|
+
};
|
|
169
|
+
return HeaderSlot ? (_jsx(HeaderSlot, { Default: ScheduledEmailDialogHeader, defaultProps: headerDefaultProps })) : (_jsx(ScheduledEmailDialogHeader, { ...headerDefaultProps }));
|
|
170
|
+
}, children: [
|
|
155
171
|
_jsx("h2", { className: "sr-only", id: titleElementId, children: intl.formatMessage({ id: "dialogs.schedule.email.accessibilityTitle" }) }), tabs.length > 1 ? (_jsx(UiTabs, { tabs: tabs, selectedTabId: selectedTabId, onTabSelect: handleTabSelect, size: "medium", accessibilityConfig: {
|
|
156
172
|
role: "tablist",
|
|
157
173
|
tabRole: "tab",
|
|
@@ -180,6 +196,26 @@ export function ScheduledMailDialogRenderer({ onBack, onCancel, onDeleteSuccess,
|
|
|
180
196
|
] }) }) }) }), scheduledEmailToDelete ? (_jsx(DeleteScheduleConfirmDialog, { scheduledEmail: scheduledEmailToDelete, onCancel: () => setScheduledEmailToDelete(null), onSuccess: handleScheduleDeleteSuccess, onError: onDeleteError })) : null] }));
|
|
181
197
|
}
|
|
182
198
|
/**
|
|
199
|
+
* Default implementation of the scheduled export create/edit dialog.
|
|
200
|
+
*
|
|
201
|
+
* This component is a pure consumer of `AutomationsContext`, `ScheduledEmailDialogContext`, and the
|
|
202
|
+
* scheduled export dialog state contexts: it reads org/workspace data, per-dialog state, and the
|
|
203
|
+
* export draft's state from those contexts rather than from the dashboard store. It must therefore
|
|
204
|
+
* be rendered within an `AutomationsContextProvider`, a `ScheduledEmailDialogContextProvider` (for
|
|
205
|
+
* the create/edit flow), and a `ScheduledEmailDialogStateProvider`, whose state model establishes
|
|
206
|
+
* itself once `useScheduledEmailDialogContext().isLoading` is false. Inside a `Dashboard`, the
|
|
207
|
+
* scheduled export connector supplies the first two providers above the
|
|
208
|
+
* `ScheduledEmailDialogComponent` slot and mounts `ScheduledEmailDialogStateProvider` around the
|
|
209
|
+
* resolved slot component — so the default component, and any wholesale slot replacement, inherit
|
|
210
|
+
* all three contexts automatically and require no extra wiring.
|
|
211
|
+
*
|
|
212
|
+
* The providers are intentionally hoisted above the slot rather than built inside this component:
|
|
213
|
+
* that is what lets a wholesale replacement receive the same contexts. Rendering this component
|
|
214
|
+
* outside those providers throws at runtime.
|
|
215
|
+
*
|
|
216
|
+
* Slots render only in the fully rendered dialog: not while the dialog context reports loading,
|
|
217
|
+
* and not while the stale-filters confirmation step is shown.
|
|
218
|
+
*
|
|
183
219
|
* @alpha
|
|
184
220
|
*/
|
|
185
221
|
export function DefaultScheduledEmailDialog(props) {
|
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
interface IScheduledEmailDialogHeaderProps {
|
|
3
|
-
title: string;
|
|
4
|
-
placeholder: string;
|
|
5
|
-
isSecondaryTitleVisible?: boolean;
|
|
6
|
-
secondaryTitle?: string;
|
|
7
|
-
secondaryTitleIcon: ReactNode;
|
|
8
|
-
onChange: (value: string, isValid: boolean) => void;
|
|
9
|
-
onKeyDownSubmit: (e: KeyboardEvent) => void;
|
|
10
|
-
onBack?: () => void;
|
|
11
|
-
}
|
|
1
|
+
import { type IScheduledEmailDialogHeaderProps } from "../../../types.js";
|
|
12
2
|
export declare const ScheduledEmailDialogHeader: import("react").ForwardRefExoticComponent<IScheduledEmailDialogHeaderProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
13
|
-
export {};
|
|
14
3
|
//# sourceMappingURL=ScheduleEmailDialogHeader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScheduleEmailDialogHeader.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/Header/ScheduleEmailDialogHeader.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ScheduleEmailDialogHeader.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/Header/ScheduleEmailDialogHeader.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,KAAK,gCAAgC,EAAE,MAAM,mBAAmB,CAAC;AAE1E,eAAO,MAAM,0BAA0B,+HA2ItC,CAAC"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// (C) 2025-2026 GoodData Corporation
|
|
3
|
-
import { forwardRef, useCallback
|
|
3
|
+
import { forwardRef, useCallback } from "react";
|
|
4
4
|
import cx from "classnames";
|
|
5
5
|
import { useIntl } from "react-intl";
|
|
6
6
|
import { createInvalidDatapoint, createInvalidNode, useValidationContextValue } from "@gooddata/sdk-ui";
|
|
7
7
|
import { Bubble, BubbleHoverTrigger, Button, IconError, useIdPrefixed } from "@gooddata/sdk-ui-kit";
|
|
8
|
-
|
|
8
|
+
import { MAX_AUTOMATION_TITLE_LENGTH, isAutomationTitleValid, } from "../../../../shared/utils/automationTitle.js";
|
|
9
9
|
export const ScheduledEmailDialogHeader = forwardRef((props, ref) => {
|
|
10
|
-
const { title, placeholder, secondaryTitle, secondaryTitleIcon, isSecondaryTitleVisible, onChange, onBack,
|
|
10
|
+
const { title, placeholder, secondaryTitle, secondaryTitleIcon, isSecondaryTitleVisible, onChange, onBack, onTitleKeyDown, } = props;
|
|
11
11
|
const { formatMessage } = useIntl();
|
|
12
12
|
const validationContextValue = useValidationContextValue(createInvalidNode({ id: "ScheduleEmailDialogHeader" }));
|
|
13
13
|
const { isValid, getInvalidDatapoints, setInvalidDatapoints } = validationContextValue;
|
|
@@ -21,13 +21,10 @@ export const ScheduledEmailDialogHeader = forwardRef((props, ref) => {
|
|
|
21
21
|
setInvalidDatapoints(() => [
|
|
22
22
|
createInvalidDatapoint({
|
|
23
23
|
id: errorId,
|
|
24
|
-
message: formatMessage({ id: "dialogs.schedule.error.too_long" }, { value:
|
|
24
|
+
message: formatMessage({ id: "dialogs.schedule.error.too_long" }, { value: MAX_AUTOMATION_TITLE_LENGTH }),
|
|
25
25
|
}),
|
|
26
26
|
]);
|
|
27
27
|
}, [errorId, formatMessage, setInvalidDatapoints]);
|
|
28
|
-
const isValueValid = useCallback((value) => {
|
|
29
|
-
return value.length <= TITLE_MAX_LENGTH;
|
|
30
|
-
}, []);
|
|
31
28
|
const dialogHeaderClasses = cx("gd-notifications-channels-dialog-title", "s-gd-notifications-channels-dialog-title", {
|
|
32
29
|
placeholder: title === "",
|
|
33
30
|
"has-error": !isValid,
|
|
@@ -37,22 +34,21 @@ export const ScheduledEmailDialogHeader = forwardRef((props, ref) => {
|
|
|
37
34
|
});
|
|
38
35
|
const handleOnChange = useCallback((e) => {
|
|
39
36
|
const { value } = e.target;
|
|
40
|
-
const validationResult = isValueValid(value);
|
|
41
37
|
if (!isValid) {
|
|
42
|
-
setHasError(!
|
|
38
|
+
setHasError(!isAutomationTitleValid(value));
|
|
43
39
|
}
|
|
44
|
-
onChange(value
|
|
45
|
-
}, [
|
|
40
|
+
onChange(value);
|
|
41
|
+
}, [isValid, onChange, setHasError]);
|
|
46
42
|
const handleBlur = useCallback((e) => {
|
|
47
|
-
setHasError(!
|
|
48
|
-
}, [
|
|
43
|
+
setHasError(!isAutomationTitleValid(e.target.value));
|
|
44
|
+
}, [setHasError]);
|
|
49
45
|
return (_jsxs("div", { className: cx("gd-notifications-channels-dialog-header", {
|
|
50
46
|
"gd-notifications-channels-dialog-header--large": isSecondaryTitleVisible,
|
|
51
47
|
}), children: [
|
|
52
48
|
_jsx(Button, { className: "gd-button-primary gd-button-icon-only gd-icon-navigateleft s-schedule-email-dialog-button", onClick: onBack, accessibilityConfig: {
|
|
53
49
|
ariaLabel: formatMessage({ id: "dialogs.schedule.email.backLabel" }),
|
|
54
50
|
} }), _jsx("div", { className: dialogHeaderClasses, children: _jsxs("div", { className: "gd-input-wrapper", children: [
|
|
55
|
-
_jsx("input", { ref: ref, type: "text", autoFocus: true, className: inputHeaderClasses, onBlur: handleBlur, value: title, placeholder: placeholder, onChange: handleOnChange, onKeyDown:
|
|
51
|
+
_jsx("input", { ref: ref, type: "text", autoFocus: true, className: inputHeaderClasses, onBlur: handleBlur, value: title, placeholder: placeholder, onChange: handleOnChange, onKeyDown: onTitleKeyDown, autoComplete: "off", "aria-describedby": isValid ? undefined : errorId, "aria-label": formatMessage({
|
|
56
52
|
id: "dialogs.schedule.accessibility.label.email.title",
|
|
57
53
|
}) }), invalidDatapoint ? (_jsxs("span", { id: errorId, className: "gd-notifications-channels-dialog-error-icon", children: [
|
|
58
54
|
_jsx("div", { className: "sr-only", children: invalidDatapoint.message }), _jsxs(BubbleHoverTrigger, { showDelay: 0, hideDelay: 0, children: [
|
|
@@ -35,7 +35,7 @@ export declare function useScheduledEmailFormState({ scheduledExportToEdit, widg
|
|
|
35
35
|
originalAutomation: IAutomationMetadataObjectDefinition;
|
|
36
36
|
defaultRecipient: IAutomationRecipient;
|
|
37
37
|
defaultUser: IAutomationRecipient;
|
|
38
|
-
onTitleChange: (value: string
|
|
38
|
+
onTitleChange: (value: string) => void;
|
|
39
39
|
onRecurrenceChange: (cronExpression: string, startDate: Date | null, isValid: boolean) => void;
|
|
40
40
|
onEvaluationModeChange: (isShared: boolean) => void;
|
|
41
41
|
onDestinationChange: (notificationChannelId: string) => void;
|
package/esm/presentation/automations/scheduledEmail/state/useScheduledEmailFormState.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useScheduledEmailFormState.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/scheduledEmail/state/useScheduledEmailFormState.ts"],"names":[],"mappings":"AAIA,OAAO,EAEH,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAE9B,KAAK,mCAAmC,EACxC,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,4CAA4C,EACjD,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,8BAA8B,EACnC,KAAK,kCAAkC,EACvC,KAAK,OAAO,EACf,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"useScheduledEmailFormState.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/scheduledEmail/state/useScheduledEmailFormState.ts"],"names":[],"mappings":"AAIA,OAAO,EAEH,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAE9B,KAAK,mCAAmC,EACxC,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,4CAA4C,EACjD,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,8BAA8B,EACnC,KAAK,kCAAkC,EACvC,KAAK,OAAO,EACf,MAAM,qBAAqB,CAAC;AAsB7B,MAAM,WAAW,gCAAgC;IAC7C,qBAAqB,CAAC,EAAE,yBAAyB,CAAC;IAClD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,oBAAoB,EAAE,8BAA8B,EAAE,GAAG,kCAAkC,EAAE,CAAC;IAC9F,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,sBAAsB,EAAE,OAAO,EAAE,CAAC;IAClC,iCAAiC,EAAE,OAAO,EAAE,CAAC;IAC7C,6BAA6B,EAAE,wBAAwB,EAAE,GAAG,SAAS,CAAC;IACtE,yBAAyB,EAAE,iBAAiB,EAAE,GAAG,SAAS,CAAC;IAC3D,8BAA8B,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,GAAG,SAAS,CAAC;IAChF,gCAAgC,EAAE,wBAAwB,EAAE,GAAG,SAAS,CAAC;IACzE,qCAAqC,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,EAAE,CAAC,GAAG,SAAS,CAAC;IAC9F,+BAA+B,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,EAAE,CAAC,GAAG,SAAS,CAAC;IACzF,kBAAkB,CAAC,EAAE,4CAA4C,CAAC,UAAU,CAAC,CAAC;CACjF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,EACvC,qBAAqB,EACrB,MAAM,EACN,OAAO,EACP,oBAAoB,EACpB,yBAAyB,EACzB,sBAAsB,EACtB,iCAAiC,EACjC,6BAA6B,EAC7B,yBAAyB,EACzB,8BAA8B,EAC9B,gCAAgC,EAChC,qCAAqC,EACrC,+BAA+B,EAC/B,kBAAkB,EACrB,EAAE,gCAAgC;;;;;;;;;;;;;;;;;;EAyJlC"}
|
|
@@ -3,6 +3,7 @@ import { useCallback, useMemo, useState } from "react";
|
|
|
3
3
|
import { setExportParametersByTab } from "../../../../_staging/automation/index.js";
|
|
4
4
|
import { useAutomationsContext } from "../../contexts/AutomationsContext.js";
|
|
5
5
|
import { useScheduledEmailDialogContext } from "../../contexts/ScheduledEmailDialogContext.js";
|
|
6
|
+
import { isAutomationTitleValid } from "../../shared/utils/automationTitle.js";
|
|
6
7
|
import { convertExternalRecipientToAutomationRecipient, convertUserToAutomationRecipient, } from "../../shared/utils/automationUtils.js";
|
|
7
8
|
import { toModifiedISOStringToTimezone, toNormalizedFirstRunAndCron, toNormalizedStartDate, } from "../utils/date.js";
|
|
8
9
|
import { getUserTimezone } from "../utils/timezone.js";
|
|
@@ -70,8 +71,8 @@ export function useScheduledEmailFormState({ scheduledExportToEdit, widget, insi
|
|
|
70
71
|
const [isTitleValid, setIsTitleValid] = useState(true);
|
|
71
72
|
const [isSubjectValid, setIsSubjectValid] = useState(true);
|
|
72
73
|
const [isOnMessageValid, setIsOnMessageValid] = useState(true);
|
|
73
|
-
const onTitleChange = useCallback((value
|
|
74
|
-
setIsTitleValid(
|
|
74
|
+
const onTitleChange = useCallback((value) => {
|
|
75
|
+
setIsTitleValid(isAutomationTitleValid(value));
|
|
75
76
|
setEditedAutomation((s) => ({ ...s, title: value }));
|
|
76
77
|
}, []);
|
|
77
78
|
const onRecurrenceChange = useCallback((cronExpression, startDate, isValid) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { type ComponentType } from "react";
|
|
1
|
+
import { type ComponentType, type KeyboardEvent, type Ref } from "react";
|
|
2
2
|
import { type FilterContextItem, type IAutomationMetadataObject, type IAutomationMetadataObjectDefinition, type IFilter, type IInsight, type INotificationChannelIdentifier, type INotificationChannelMetadataObject, type IWidget } from "@gooddata/sdk-model";
|
|
3
3
|
import { type GoodDataSdkError } from "@gooddata/sdk-ui";
|
|
4
|
+
import { type IAutomationDialogHeaderProps, type ISlotProps } from "../shared/slots/types.js";
|
|
4
5
|
/**
|
|
5
6
|
* @alpha
|
|
6
7
|
*/
|
|
@@ -114,6 +115,59 @@ export interface IScheduledEmailDialogProps {
|
|
|
114
115
|
*/
|
|
115
116
|
onDeleteError?: (error: GoodDataSdkError) => void;
|
|
116
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Props of the default scheduled email dialog's header region (the title input row).
|
|
120
|
+
*
|
|
121
|
+
* @alpha
|
|
122
|
+
*/
|
|
123
|
+
export interface IScheduledEmailDialogHeaderProps extends IAutomationDialogHeaderProps {
|
|
124
|
+
/**
|
|
125
|
+
* Called on key-down inside the title input.
|
|
126
|
+
*/
|
|
127
|
+
onTitleKeyDown: (event: KeyboardEvent) => void;
|
|
128
|
+
/**
|
|
129
|
+
* Called when the header's back button is pressed.
|
|
130
|
+
*/
|
|
131
|
+
onBack?: () => void;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The exact props the default dialog renders its header with, including the dialog's
|
|
135
|
+
* initial-focus ref.
|
|
136
|
+
*
|
|
137
|
+
* @alpha
|
|
138
|
+
*/
|
|
139
|
+
export type ScheduledEmailDialogHeaderDefaultProps = IScheduledEmailDialogHeaderProps & {
|
|
140
|
+
ref?: Ref<HTMLInputElement>;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Section-level overrides of the default scheduled email dialog.
|
|
144
|
+
*
|
|
145
|
+
* @alpha
|
|
146
|
+
*/
|
|
147
|
+
export interface IScheduledEmailDialogSlots {
|
|
148
|
+
/**
|
|
149
|
+
* Wraps or replaces the dialog header (the title input row). Must have a stable reference
|
|
150
|
+
* identity — see {@link ISlotProps}.
|
|
151
|
+
*/
|
|
152
|
+
Header?: ComponentType<ISlotProps<ScheduledEmailDialogHeaderDefaultProps>>;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Props of {@link DefaultScheduledEmailDialog}.
|
|
156
|
+
*
|
|
157
|
+
* @remarks
|
|
158
|
+
* Extends the shared {@link IScheduledEmailDialogProps} with customization only the default implementation
|
|
159
|
+
* supports. Slots render only in the fully rendered dialog: not while the dialog context reports
|
|
160
|
+
* loading, and not while the stale-filters confirmation step is shown.
|
|
161
|
+
*
|
|
162
|
+
* @alpha
|
|
163
|
+
*/
|
|
164
|
+
export interface IDefaultScheduledEmailDialogProps extends IScheduledEmailDialogProps {
|
|
165
|
+
/**
|
|
166
|
+
* Section-level overrides. Each slot receives `{ Default, defaultProps }` and may render its own
|
|
167
|
+
* content (replace) or `<Default {...defaultProps} />` inside its own markup (wrap).
|
|
168
|
+
*/
|
|
169
|
+
slots?: IScheduledEmailDialogSlots;
|
|
170
|
+
}
|
|
117
171
|
/**
|
|
118
172
|
*
|
|
119
173
|
* @alpha
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/presentation/automations/scheduledEmail/types.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/presentation/automations/scheduledEmail/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutomationParameter.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/components/AutomationParameter.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI3D,OAAO,
|
|
1
|
+
{"version":3,"file":"AutomationParameter.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/automations/shared/automationFilters/components/AutomationParameter.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI3D,OAAO,EAEH,KAAK,aAAa,EAClB,KAAK,cAAc,EAEtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEH,KAAK,mBAAmB,EAM3B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACtC,SAAS,EAAE,oBAAoB,CAAC;IAChC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC/D,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;IACxC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAChC,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,mBAAmB,EACnB,UAAU,EACb,EAAE,yBAAyB,GAAG,SAAS,CA6FvC"}
|
package/esm/presentation/automations/shared/automationFilters/components/AutomationParameter.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useIntl } from "react-intl";
|
|
3
|
-
import { DashboardParameterModeValues } from "@gooddata/sdk-model";
|
|
3
|
+
import { DashboardParameterModeValues, getParameterValueTitle, } from "@gooddata/sdk-model";
|
|
4
4
|
import { Dropdown, ParameterControl, UiChip, UiTooltip, isActionKey, useIdPrefixed, } from "@gooddata/sdk-ui-kit";
|
|
5
5
|
/**
|
|
6
6
|
* Workspace parameter as an editable chip in automation dialogs.
|
|
@@ -11,7 +11,7 @@ export function AutomationParameter({ parameter, onChange, onDelete, overlayPosi
|
|
|
11
11
|
const intl = useIntl();
|
|
12
12
|
const { ref, title, value, mode, definition } = parameter;
|
|
13
13
|
const testId = `automation-parameter-${ref.identifier}`;
|
|
14
|
-
const label = intl.formatMessage({ id: "dialogs.automation.parameters.chip" }, { title, value });
|
|
14
|
+
const label = intl.formatMessage({ id: "dialogs.automation.parameters.chip" }, { title, value: getParameterValueTitle(definition, value) });
|
|
15
15
|
const lockedTooltip = intl.formatMessage({ id: "dialogs.automation.filters.lockedTooltip" });
|
|
16
16
|
const deleteAriaLabel = intl.formatMessage({ id: "dialogs.automation.filters.deleteAriaLabel" });
|
|
17
17
|
const tooltipId = useIdPrefixed("automation-parameter-tooltip");
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type ComponentType, type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Contract of a section-level slot: the default implementation and the exact props the default
|
|
4
|
+
* dialog would render it with.
|
|
5
|
+
*
|
|
6
|
+
* The component a customer assigns to a slot is rendered as an element type, so its reference
|
|
7
|
+
* identity is load-bearing: define it at module scope (or memoize it), never inline in a render
|
|
8
|
+
* function — an inline definition gets a fresh identity on every render of the declaring
|
|
9
|
+
* component, which unmounts and remounts the region, losing focus and transient DOM state.
|
|
10
|
+
*
|
|
11
|
+
* Render `<Default {...defaultProps} />` inside your own markup to wrap the region rather than
|
|
12
|
+
* replace it; a slot that does not spread `defaultProps` onto `Default` loses the default
|
|
13
|
+
* behavior wired through them (including the dialog's initial-focus ref).
|
|
14
|
+
*
|
|
15
|
+
* @alpha
|
|
16
|
+
*/
|
|
17
|
+
export interface ISlotProps<TProps> {
|
|
18
|
+
/**
|
|
19
|
+
* The default implementation of the region.
|
|
20
|
+
*/
|
|
21
|
+
Default: ComponentType<TProps>;
|
|
22
|
+
/**
|
|
23
|
+
* The exact props the default dialog would render {@link ISlotProps.Default} with.
|
|
24
|
+
*/
|
|
25
|
+
defaultProps: TProps;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Members shared by both automation dialogs' header regions.
|
|
29
|
+
*
|
|
30
|
+
* @alpha
|
|
31
|
+
*/
|
|
32
|
+
export interface IAutomationDialogHeaderProps {
|
|
33
|
+
/**
|
|
34
|
+
* Current automation title.
|
|
35
|
+
*/
|
|
36
|
+
title: string;
|
|
37
|
+
/**
|
|
38
|
+
* Placeholder shown while the title is empty.
|
|
39
|
+
*/
|
|
40
|
+
placeholder: string;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the secondary title row is shown.
|
|
43
|
+
*/
|
|
44
|
+
isSecondaryTitleVisible?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Secondary title text (e.g. the widget name).
|
|
47
|
+
*/
|
|
48
|
+
secondaryTitle?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Icon rendered before the secondary title.
|
|
51
|
+
*/
|
|
52
|
+
secondaryTitleIcon: ReactNode;
|
|
53
|
+
/**
|
|
54
|
+
* Called on every title change with the new value. The dialog validates the title itself.
|
|
55
|
+
*/
|
|
56
|
+
onChange: (value: string) => void;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/shared/slots/types.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE3D;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,UAAU,CAAC,MAAM;IAC9B;;OAEG;IACH,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAE/B;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IACzC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,kBAAkB,EAAE,SAAS,CAAC;IAE9B;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Maximum permitted length for an automation title, inclusive. */
|
|
2
|
+
export declare const MAX_AUTOMATION_TITLE_LENGTH = 255;
|
|
3
|
+
/** Returns whether an automation title is within the permitted length. */
|
|
4
|
+
export declare function isAutomationTitleValid(value: string): boolean;
|
|
5
|
+
//# sourceMappingURL=automationTitle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"automationTitle.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/automations/shared/utils/automationTitle.ts"],"names":[],"mappings":"AAEA,mEAAmE;AACnE,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C,0EAA0E;AAC1E,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE7D"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
/** Maximum permitted length for an automation title, inclusive. */
|
|
3
|
+
export const MAX_AUTOMATION_TITLE_LENGTH = 255;
|
|
4
|
+
/** Returns whether an automation title is within the permitted length. */
|
|
5
|
+
export function isAutomationTitleValid(value) {
|
|
6
|
+
return value.length <= MAX_AUTOMATION_TITLE_LENGTH;
|
|
7
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultParameterDraggingComponent.d.ts","sourceRoot":"","sources":["../../../../src/presentation/dragAndDrop/draggableParameterFilter/DefaultParameterDraggingComponent.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DefaultParameterDraggingComponent.d.ts","sourceRoot":"","sources":["../../../../src/presentation/dragAndDrop/draggableParameterFilter/DefaultParameterDraggingComponent.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,gCAAgC;IAC7C,QAAQ,EAAE,WAAW,CAAC;IACtB,IAAI,EAAE,sBAAsB,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAAC,EAAE,IAAI,EAAE,EAAE,gCAAgC,kDAgB3F"}
|